techlify-inventory-common 18.1.0 → 18.2.0

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.
Files changed (53) hide show
  1. package/esm2022/lib/inventory-common/inventory-common-routing.module.mjs +11 -1
  2. package/esm2022/lib/inventory-common/inventory-common.module.mjs +8 -4
  3. package/esm2022/lib/inventory-common/inventory-dashboard-page/inventory-dashboard-page.component.mjs +10 -8
  4. package/esm2022/lib/inventory-common/inventory-value-report.service.mjs +21 -0
  5. package/esm2022/lib/inventory-common/low-stock-report.service.mjs +23 -0
  6. package/esm2022/lib/inventory-common/product/low-stock-products-widget/low-stock-products-widget.component.mjs +9 -7
  7. package/esm2022/lib/inventory-common/product/product-list/product-list.component.mjs +3 -3
  8. package/esm2022/lib/inventory-common/product/product-quick-search/product-quick-search.component.mjs +92 -0
  9. package/esm2022/lib/inventory-common/product/widgets/product-category-badges/product-category-badges.component.mjs +18 -0
  10. package/esm2022/lib/inventory-common/reports/inventory-value-report/inventory-value-report.component.mjs +170 -0
  11. package/esm2022/lib/inventory-common/reports/low-stock-report/low-stock-report.component.mjs +165 -0
  12. package/esm2022/lib/inventory-common/supplier/supplier-delete-button/supplier-delete-button.component.mjs +64 -0
  13. package/esm2022/lib/inventory-common/supplier/supplier-form/supplier-form-button/supplier-form-button.component.mjs +43 -0
  14. package/esm2022/lib/inventory-common/supplier/supplier.module.mjs +11 -3
  15. package/esm2022/lib/inventory-common/supplier/suppliers-list/suppliers-list.component.mjs +6 -65
  16. package/fesm2022/{techlify-inventory-common-category.module-CNm2bEsx.mjs → techlify-inventory-common-category.module-BKEBFEeZ.mjs} +9 -9
  17. package/fesm2022/{techlify-inventory-common-category.module-CNm2bEsx.mjs.map → techlify-inventory-common-category.module-BKEBFEeZ.mjs.map} +1 -1
  18. package/fesm2022/{techlify-inventory-common-measure.module-BEaRHh5Z.mjs → techlify-inventory-common-measure.module-CZHhYoQd.mjs} +9 -9
  19. package/fesm2022/{techlify-inventory-common-measure.module-BEaRHh5Z.mjs.map → techlify-inventory-common-measure.module-CZHhYoQd.mjs.map} +1 -1
  20. package/fesm2022/{techlify-inventory-common-stock-issuances.module-BQRRP-hW.mjs → techlify-inventory-common-stock-issuances.module-BjPbzqUW.mjs} +2 -4
  21. package/fesm2022/{techlify-inventory-common-stock-issuances.module-BQRRP-hW.mjs.map → techlify-inventory-common-stock-issuances.module-BjPbzqUW.mjs.map} +1 -1
  22. package/fesm2022/{techlify-inventory-common-supplier.module-Bwa7gx14.mjs → techlify-inventory-common-supplier.module-CFDwJ-TS.mjs} +251 -218
  23. package/fesm2022/techlify-inventory-common-supplier.module-CFDwJ-TS.mjs.map +1 -0
  24. package/fesm2022/techlify-inventory-common-techlify-inventory-common-CYiCJfk9.mjs +3143 -0
  25. package/fesm2022/techlify-inventory-common-techlify-inventory-common-CYiCJfk9.mjs.map +1 -0
  26. package/fesm2022/techlify-inventory-common.mjs +1 -1
  27. package/lib/inventory-common/inventory-common.module.d.ts +2 -1
  28. package/lib/inventory-common/inventory-value-report.service.d.ts +9 -0
  29. package/lib/inventory-common/low-stock-report.service.d.ts +10 -0
  30. package/lib/inventory-common/product/product-quick-search/product-quick-search.component.d.ts +15 -0
  31. package/lib/inventory-common/product/widgets/product-category-badges/product-category-badges.component.d.ts +6 -0
  32. package/lib/inventory-common/reports/inventory-value-report/inventory-value-report.component.d.ts +26 -0
  33. package/lib/inventory-common/reports/low-stock-report/low-stock-report.component.d.ts +26 -0
  34. package/lib/inventory-common/supplier/supplier-delete-button/supplier-delete-button.component.d.ts +18 -0
  35. package/lib/inventory-common/supplier/supplier-form/supplier-form-button/supplier-form-button.component.d.ts +13 -0
  36. package/lib/inventory-common/supplier/supplier.module.d.ts +3 -1
  37. package/lib/inventory-common/supplier/suppliers-list/suppliers-list.component.d.ts +0 -8
  38. package/package.json +1 -1
  39. package/fesm2022/techlify-inventory-common-product.module-BV9Cy88x.mjs +0 -1168
  40. package/fesm2022/techlify-inventory-common-product.module-BV9Cy88x.mjs.map +0 -1
  41. package/fesm2022/techlify-inventory-common-stock-issuances-list.module-Dt6gx-ji.mjs +0 -436
  42. package/fesm2022/techlify-inventory-common-stock-issuances-list.module-Dt6gx-ji.mjs.map +0 -1
  43. package/fesm2022/techlify-inventory-common-stock-receipt-form.module-DND0GNlf.mjs +0 -302
  44. package/fesm2022/techlify-inventory-common-stock-receipt-form.module-DND0GNlf.mjs.map +0 -1
  45. package/fesm2022/techlify-inventory-common-stock-receipts.module-BvYaKITT.mjs +0 -253
  46. package/fesm2022/techlify-inventory-common-stock-receipts.module-BvYaKITT.mjs.map +0 -1
  47. package/fesm2022/techlify-inventory-common-supplier-form.component-DVBnhiyH.mjs +0 -177
  48. package/fesm2022/techlify-inventory-common-supplier-form.component-DVBnhiyH.mjs.map +0 -1
  49. package/fesm2022/techlify-inventory-common-supplier.module-Bwa7gx14.mjs.map +0 -1
  50. package/fesm2022/techlify-inventory-common-techlify-form-service-CiVfwYTS.mjs +0 -14
  51. package/fesm2022/techlify-inventory-common-techlify-form-service-CiVfwYTS.mjs.map +0 -1
  52. package/fesm2022/techlify-inventory-common-techlify-inventory-common-GFYF7JCA.mjs +0 -495
  53. package/fesm2022/techlify-inventory-common-techlify-inventory-common-GFYF7JCA.mjs.map +0 -1
@@ -1,1168 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { Inject, Component, Injectable, EventEmitter, Input, Output, NgModule } from '@angular/core';
3
- import * as i4 from '@angular/common';
4
- import { CommonModule } from '@angular/common';
5
- import { __decorate } from 'tslib';
6
- import * as i2 from '@angular/forms';
7
- import { Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
8
- import * as i1 from '@angular/material/dialog';
9
- import { MAT_DIALOG_DATA } from '@angular/material/dialog';
10
- import { P as ProductService, S as StockSummaryService } from './techlify-inventory-common-techlify-inventory-common-GFYF7JCA.mjs';
11
- import * as i3 from 'ngx-spinner';
12
- import * as i1$1 from 'ngx-techlify-core';
13
- import { TechlifyServiceBaseClass, TechlifyFormComponentInterface, TechlifyListingControllerInterface, AuthenticationGuard, MaterialModule, SearchableSelectorModule, TimelineFilterModule, ImportCsvModule, ColumnSelectorModule } from 'ngx-techlify-core';
14
- import * as i7 from '@angular/material/button';
15
- import * as i6 from '@angular/material/form-field';
16
- import * as i7$1 from '@angular/material/input';
17
- import * as i10 from '@angular/flex-layout';
18
- import { FlexModule } from '@angular/flex-layout';
19
- import * as i6$1 from '@angular/material/table';
20
- import { MatTableDataSource } from '@angular/material/table';
21
- import { debounceTime } from 'rxjs/operators';
22
- import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy';
23
- import * as i2$1 from '@angular/router';
24
- import { RouterModule } from '@angular/router';
25
- import * as i3$1 from '@angular/material/icon';
26
- import * as i10$1 from '@angular/material/core';
27
- import * as i11 from '@angular/material/select';
28
- import * as i5 from '@angular/material/sort';
29
- import * as i10$2 from 'ngx-infinite-scroll';
30
- import { InfiniteScrollModule } from 'ngx-infinite-scroll';
31
- import moment from 'moment';
32
- import { T as TechlifyFormService } from './techlify-inventory-common-techlify-form-service-CiVfwYTS.mjs';
33
- import * as i9 from '@angular/material/datepicker';
34
- import { a as StockReceiptFormButtonComponent, S as StockReceiptFormModule } from './techlify-inventory-common-stock-receipt-form.module-DND0GNlf.mjs';
35
- import { c as StockIssueFormButtonComponent, S as StockIssuancesListComponent, a as StockIssueFormModule, b as StockIssuancesListModule } from './techlify-inventory-common-stock-issuances-list.module-Dt6gx-ji.mjs';
36
- import * as i3$2 from '@angular/material/card';
37
- import * as i2$2 from '@angular/material/tooltip';
38
- import * as i7$2 from '@angular/material/progress-bar';
39
- import { MatProgressBarModule } from '@angular/material/progress-bar';
40
- import { S as StockReceiptsListPageComponent, a as StockReceiptsModule } from './techlify-inventory-common-stock-receipts.module-BvYaKITT.mjs';
41
- import * as i6$2 from '@angular/material/divider';
42
-
43
- const errorMessages$1 = {
44
- title: {
45
- required: "Please Enter Title",
46
- },
47
- description: {
48
- required: "Please Enter Description",
49
- },
50
- };
51
- class ProductMeasureFormComponent {
52
- productService;
53
- fb;
54
- dialogRef;
55
- data;
56
- spinnerService;
57
- formValidatorService;
58
- errorService;
59
- alertService;
60
- productMeasureForm;
61
- isWorking = false;
62
- isUpdate = false;
63
- constructor(productService, fb, dialogRef, data, spinnerService, formValidatorService, errorService, alertService) {
64
- this.productService = productService;
65
- this.fb = fb;
66
- this.dialogRef = dialogRef;
67
- this.data = data;
68
- this.spinnerService = spinnerService;
69
- this.formValidatorService = formValidatorService;
70
- this.errorService = errorService;
71
- this.alertService = alertService;
72
- this.productMeasureForm = this.fb.group({
73
- id: [""],
74
- title: ["", Validators.compose([Validators.required])],
75
- description: ["", Validators.compose([Validators.required])],
76
- });
77
- }
78
- ngOnInit() {
79
- if (this.data.details) {
80
- this.isUpdate = true;
81
- this.productMeasureForm.patchValue(this.data.details);
82
- }
83
- }
84
- async save() {
85
- if (!this.productMeasureForm.valid) {
86
- this.alertService.addAlert("Please Fill All Required Fields", "warn");
87
- this.productMeasureForm.markAllAsTouched();
88
- return;
89
- }
90
- let productMeasure = this.productMeasureForm.value;
91
- try {
92
- this.spinnerService.show();
93
- this.isWorking = true;
94
- let result = this.isUpdate
95
- ? await this.productService.updateProductMeasure(productMeasure)
96
- : await this.productService.createProductMeasure(productMeasure);
97
- this.dialogRef.close(result);
98
- }
99
- catch (error) {
100
- this.errorService.handleError(error);
101
- }
102
- finally {
103
- this.isWorking = false;
104
- this.spinnerService.hide();
105
- }
106
- }
107
- /**
108
- * Method to evaluate form fields
109
- */
110
- isFieldValid(field) {
111
- return this.formValidatorService.isFieldValid(field, this.productMeasureForm);
112
- }
113
- /**
114
- * Method to find error in form fields
115
- */
116
- getErrorMessage(field) {
117
- return this.formValidatorService.getErrorMessage(field, this.productMeasureForm, errorMessages$1);
118
- }
119
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasureFormComponent, deps: [{ token: ProductService }, { token: i2.FormBuilder }, { token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: i3.NgxSpinnerService }, { token: i1$1.FormValidatorService }, { token: i1$1.ErrorHandlerService }, { token: i1$1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
120
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductMeasureFormComponent, selector: "app-product-measure-form", ngImport: i0, template: "<div>\n <form [formGroup]=\"productMeasureForm\" (ngSubmit)=\"save()\">\n <h3 class=\"text-center\">Create/Update Product Measure</h3>\n <div fxLayout=\"column\">\n <div fxLayout=\"column\">\n <mat-form-field>\n <input\n matInput\n placeholder=\"Title\"\n formControlName=\"title\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('title')\"\n >{{ getErrorMessage(\"title\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field>\n <input\n matInput\n placeholder=\"Description\"\n formControlName=\"description\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('description')\"\n >{{ getErrorMessage(\"description\") }}\n </mat-error>\n </mat-form-field>\n <div fxFlex=\"100%\" fxLayout fxLayoutGap=\"1rem\">\n <button\n mat-button\n class=\"mt-2\"\n type=\"button\"\n (click)=\"dialogRef.close()\"\n >\n Cancel\n </button>\n <button mat-raised-button color=\"primary\" class=\"mt-2\" type=\"submit\">\n Save\n </button>\n </div>\n </div>\n </div>\n </form>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i10.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i10.DefaultLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i10.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], preserveWhitespaces: true });
121
- }
122
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasureFormComponent, decorators: [{
123
- type: Component,
124
- args: [{ selector: "app-product-measure-form", template: "<div>\n <form [formGroup]=\"productMeasureForm\" (ngSubmit)=\"save()\">\n <h3 class=\"text-center\">Create/Update Product Measure</h3>\n <div fxLayout=\"column\">\n <div fxLayout=\"column\">\n <mat-form-field>\n <input\n matInput\n placeholder=\"Title\"\n formControlName=\"title\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('title')\"\n >{{ getErrorMessage(\"title\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field>\n <input\n matInput\n placeholder=\"Description\"\n formControlName=\"description\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('description')\"\n >{{ getErrorMessage(\"description\") }}\n </mat-error>\n </mat-form-field>\n <div fxFlex=\"100%\" fxLayout fxLayoutGap=\"1rem\">\n <button\n mat-button\n class=\"mt-2\"\n type=\"button\"\n (click)=\"dialogRef.close()\"\n >\n Cancel\n </button>\n <button mat-raised-button color=\"primary\" class=\"mt-2\" type=\"submit\">\n Save\n </button>\n </div>\n </div>\n </div>\n </form>\n</div>\n" }]
125
- }], ctorParameters: () => [{ type: ProductService }, { type: i2.FormBuilder }, { type: i1.MatDialogRef }, { type: undefined, decorators: [{
126
- type: Inject,
127
- args: [MAT_DIALOG_DATA]
128
- }] }, { type: i3.NgxSpinnerService }, { type: i1$1.FormValidatorService }, { type: i1$1.ErrorHandlerService }, { type: i1$1.AlertService }] });
129
-
130
- let ProductMeasuresListComponent = class ProductMeasuresListComponent {
131
- fb;
132
- dialog;
133
- filterService;
134
- activatedRoute;
135
- productService;
136
- filterFormGroup;
137
- lastPage;
138
- page = 1;
139
- perPage = 25;
140
- totalItems = 0;
141
- currentPage = 1;
142
- num_items = 25;
143
- routeFilters;
144
- productMeasures = [];
145
- columnDefinitions = [
146
- { def: "#", isShow: true },
147
- { def: "Title", isShow: true },
148
- { def: "Description", isShow: true },
149
- { def: "Actions", isShow: true },
150
- ];
151
- displayedColumns = ["#", "Title", "Description", "Actions"];
152
- dataSource = new MatTableDataSource();
153
- constructor(fb, dialog, filterService, activatedRoute, productService) {
154
- this.fb = fb;
155
- this.dialog = dialog;
156
- this.filterService = filterService;
157
- this.activatedRoute = activatedRoute;
158
- this.productService = productService;
159
- this.filterFormGroup = this.fb.group({
160
- num_items: [this.num_items + "|" + this.currentPage],
161
- search: [""],
162
- type_ids: [""],
163
- sort_by: [""],
164
- });
165
- }
166
- ngOnInit() {
167
- this.patchFiltersFromRoute();
168
- this.listenForChanges();
169
- this.loadData();
170
- }
171
- listenForChanges() {
172
- this.filterFormGroup.valueChanges
173
- .pipe(debounceTime(500), untilDestroyed(this))
174
- .subscribe((changes) => {
175
- this.filterService.applyFilterToRoute(this.activatedRoute, this.filterFormGroup.value);
176
- this.reload();
177
- });
178
- }
179
- patchFiltersFromRoute() {
180
- this.routeFilters = this.filterService.getFiltersFromRoute(this.activatedRoute, this.filterFormGroup.value);
181
- this.filterFormGroup.setValue(this.routeFilters);
182
- if (this.routeFilters.type_ids) {
183
- this.filterFormGroup
184
- .get("type_ids")
185
- .setValue(this.routeFilters.type_ids.split(",").map(Number));
186
- }
187
- }
188
- async loadData() {
189
- let filters = this.filterFormGroup.value;
190
- filters.page = this.page;
191
- filters.per_page = this.perPage;
192
- filters.type_ids = filters.type_ids.toString();
193
- filters.num_items = this.num_items + "|" + this.currentPage;
194
- let res = await this.productService.getProductMeasures(filters);
195
- if (this.productMeasures.length < 1) {
196
- this.productMeasures = res.data;
197
- }
198
- else {
199
- res.data.forEach((item) => this.productMeasures.push(item));
200
- }
201
- this.dataSource = new MatTableDataSource(this.productMeasures);
202
- this.totalItems = res.total;
203
- this.lastPage = res.last_page || this.page;
204
- }
205
- reload() {
206
- this.productMeasures = [];
207
- this.currentPage = 1;
208
- this.loadData();
209
- }
210
- modifyProductMeasure(model) {
211
- const dialogRef = this.dialog.open(ProductMeasureFormComponent, {
212
- width: "600px",
213
- data: {
214
- details: model,
215
- },
216
- });
217
- dialogRef.afterClosed().subscribe((result) => {
218
- if (result) {
219
- this.reload();
220
- }
221
- });
222
- }
223
- onScroll() {
224
- if (this.totalItems > this.productMeasures.length) {
225
- this.currentPage += 1;
226
- this.loadData();
227
- }
228
- }
229
- assignFilter(column, direction) {
230
- if (column) {
231
- return this.filterFormGroup
232
- .get("sort_by")
233
- ?.setValue(column + "|" + direction);
234
- }
235
- }
236
- sortColumn(event) {
237
- var direction = event.direction.toString().toUpperCase();
238
- this.assignFilter(event.active, direction);
239
- }
240
- // eslint-disable-next-line @angular-eslint/use-lifecycle-interface
241
- // eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
242
- ngOnDestroy() {
243
- //Called once, before the instance is destroyed.
244
- //Add 'implements OnDestroy' to the class.
245
- }
246
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasuresListComponent, deps: [{ token: i2.FormBuilder }, { token: i1.MatDialog }, { token: i1$1.FilterService }, { token: i2$1.ActivatedRoute }, { token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
247
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductMeasuresListComponent, selector: "app-product-measure-list", ngImport: i0, template: "<div fxLayout=\"column\">\n <div class=\"text-center\" fxLayoutAlign=\"center center\">\n <h3 fxLayout>\n <span class=\"mt-1\"> Product Measures </span>\n <button\n mat-raised-button\n class=\"ml-2\"\n color=\"primary\"\n (click)=\"modifyProductMeasure()\"\n >\n <mat-icon>add</mat-icon>\n Product Measure\n </button>\n </h3>\n </div>\n\n <div fxLayout>\n <form [formGroup]=\"filterFormGroup\" fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field>\n <input\n matInput\n placeholder=\"Item Name, Description, etc.\"\n formControlName=\"search\"\n />\n </mat-form-field>\n </form>\n\n <mat-form-field class=\"ml-2\" fxFlex=\"0 1 calc(11.11% - 0.5rem)\">\n <mat-label>Columns</mat-label>\n <mat-select [(ngModel)]=\"displayedColumns\" multiple name=\"column\">\n <mat-option\n *ngFor=\"let column of columnDefinitions\"\n [value]=\"column.def\"\n [disabled]=\"!column.isShow\"\n >\n {{ column?.def }}</mat-option\n >\n </mat-select>\n </mat-form-field>\n </div>\n\n <table\n mat-table\n #table\n [dataSource]=\"dataSource\"\n class=\"mat-elevation-z8 w-100 mt-4 table-hover\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n [fromRoot]=\"true\"\n infiniteScrollContainer=\"mat-sidenav-content\"\n matSort\n (matSortChange)=\"sortColumn($event)\"\n matSortDisableClear=\"true\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Title Column -->\n <ng-container matColumnDef=\"Title\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Title</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.title }}</td>\n </ng-container>\n\n <!-- Description Column -->\n <ng-container matColumnDef=\"Description\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Description</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.description }}</td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary\" fxLayoutGap=\"1rem\">\n <button mat-icon-button (click)=\"modifyProductMeasure(element)\">\n <mat-icon>edit</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i7.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i10$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i11.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"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i5.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i5.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i6$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i6$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i10$2.InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "directive", type: i10.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i10.DefaultLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i10.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i10.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], preserveWhitespaces: true });
248
- };
249
- ProductMeasuresListComponent = __decorate([
250
- UntilDestroy()
251
- ], ProductMeasuresListComponent);
252
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasuresListComponent, decorators: [{
253
- type: Component,
254
- args: [{ selector: "app-product-measure-list", template: "<div fxLayout=\"column\">\n <div class=\"text-center\" fxLayoutAlign=\"center center\">\n <h3 fxLayout>\n <span class=\"mt-1\"> Product Measures </span>\n <button\n mat-raised-button\n class=\"ml-2\"\n color=\"primary\"\n (click)=\"modifyProductMeasure()\"\n >\n <mat-icon>add</mat-icon>\n Product Measure\n </button>\n </h3>\n </div>\n\n <div fxLayout>\n <form [formGroup]=\"filterFormGroup\" fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field>\n <input\n matInput\n placeholder=\"Item Name, Description, etc.\"\n formControlName=\"search\"\n />\n </mat-form-field>\n </form>\n\n <mat-form-field class=\"ml-2\" fxFlex=\"0 1 calc(11.11% - 0.5rem)\">\n <mat-label>Columns</mat-label>\n <mat-select [(ngModel)]=\"displayedColumns\" multiple name=\"column\">\n <mat-option\n *ngFor=\"let column of columnDefinitions\"\n [value]=\"column.def\"\n [disabled]=\"!column.isShow\"\n >\n {{ column?.def }}</mat-option\n >\n </mat-select>\n </mat-form-field>\n </div>\n\n <table\n mat-table\n #table\n [dataSource]=\"dataSource\"\n class=\"mat-elevation-z8 w-100 mt-4 table-hover\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n [fromRoot]=\"true\"\n infiniteScrollContainer=\"mat-sidenav-content\"\n matSort\n (matSortChange)=\"sortColumn($event)\"\n matSortDisableClear=\"true\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Title Column -->\n <ng-container matColumnDef=\"Title\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Title</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.title }}</td>\n </ng-container>\n\n <!-- Description Column -->\n <ng-container matColumnDef=\"Description\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Description</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.description }}</td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary\" fxLayoutGap=\"1rem\">\n <button mat-icon-button (click)=\"modifyProductMeasure(element)\">\n <mat-icon>edit</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n</div>\n" }]
255
- }], ctorParameters: () => [{ type: i2.FormBuilder }, { type: i1.MatDialog }, { type: i1$1.FilterService }, { type: i2$1.ActivatedRoute }, { type: ProductService }] });
256
-
257
- class ProductFormService extends TechlifyFormService {
258
- constructor() {
259
- super();
260
- }
261
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
262
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormService, providedIn: "root" });
263
- }
264
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormService, decorators: [{
265
- type: Injectable,
266
- args: [{
267
- providedIn: "root",
268
- }]
269
- }], ctorParameters: () => [] });
270
-
271
- const initial_quantity = 0;
272
- const reorder_point = 10;
273
- const errorMessages = {
274
- type_id: {
275
- required: "Please Enter Type",
276
- },
277
- name: {
278
- required: "Please Enter Name",
279
- },
280
- sale_price: {
281
- required: "Please Enter Sales Price",
282
- },
283
- minimum_price: {
284
- required: "Please Enter Minimum Price",
285
- },
286
- reorder_point: {
287
- required: "Please Enter Reorder Point",
288
- },
289
- };
290
- class ProductFormComponent {
291
- productService;
292
- fb;
293
- formValidatorService;
294
- alertService;
295
- datePipe;
296
- productFormService;
297
- productForm;
298
- isWorking = false;
299
- isUpdate = false;
300
- saved = new EventEmitter();
301
- cancelled = new EventEmitter();
302
- product;
303
- displayedFormFields = [
304
- "name",
305
- "product type",
306
- "sku",
307
- "description",
308
- "product measure",
309
- "reorder point",
310
- "initial quantity",
311
- "initial quantity date",
312
- "sales price",
313
- "minimum price",
314
- "maximum price",
315
- "income account",
316
- "expense account",
317
- ];
318
- displayedFormSections = [
319
- "basic information",
320
- "inventory information",
321
- "sales information",
322
- "accounts information",
323
- ];
324
- constructor(productService, fb, formValidatorService, alertService, datePipe, productFormService) {
325
- this.productService = productService;
326
- this.fb = fb;
327
- this.formValidatorService = formValidatorService;
328
- this.alertService = alertService;
329
- this.datePipe = datePipe;
330
- this.productFormService = productFormService;
331
- this.productForm = this.fb.group({
332
- id: [""],
333
- type_id: [1, Validators.compose([Validators.required])],
334
- sku: [""],
335
- name: ["", Validators.compose([Validators.required])],
336
- initial_quantity: [initial_quantity],
337
- initial_quantity_date: [moment().format()],
338
- reorder_point: [reorder_point, Validators.compose([Validators.required])],
339
- description: [""],
340
- sale_price: [0, Validators.compose([Validators.required])],
341
- income_account_id: [""],
342
- expense_account_id: [""],
343
- measure_id: [1],
344
- minimum_price: ["", Validators.compose([Validators.required])],
345
- maximum_price: [""],
346
- condition_type_id: [1],
347
- current_quantity: [],
348
- category_ids: [""],
349
- });
350
- }
351
- ngOnInit() {
352
- if (this.product?.id) {
353
- this.isUpdate = true;
354
- let data = { ...this.product };
355
- if (this.product?.categories?.length > 0) {
356
- data.category_ids = this.product.categories.map((category) => category?.id);
357
- }
358
- if (data?.initial_quantity_date) {
359
- data.initial_quantity_date = moment(data.initial_quantity_date).toISOString();
360
- }
361
- this.productForm.patchValue(data);
362
- }
363
- }
364
- async save() {
365
- this.productForm.markAllAsTouched();
366
- if (this.productForm.invalid) {
367
- this.alertService.addAlert("Please Fill All Required Fields", "warn");
368
- return;
369
- }
370
- let product = this.productForm.value;
371
- if (product.maximum_price <= 0 || !product.maximum_price) {
372
- product.maximum_price = product.minimum_price;
373
- }
374
- if (product?.initial_quantity_date) {
375
- product.initial_quantity_date = moment(product.initial_quantity_date).format("YYYY-MM-DD");
376
- }
377
- this.isWorking = true;
378
- product.with = "type,measure,incomeAccount,expenseAccount";
379
- let request = this.productService.store(product);
380
- if (this.isUpdate) {
381
- request = this.productService.update(product);
382
- }
383
- request.subscribe({
384
- next: (response) => {
385
- this.saved.emit(response?.item);
386
- this.isWorking = false;
387
- this.productFormService.listUpdated(true);
388
- this.alertService.addAlert("Product saved successfully!", "success");
389
- },
390
- error: () => (this.isWorking = false),
391
- });
392
- }
393
- /**
394
- * Method to evaluate form fields
395
- */
396
- isFieldValid(field) {
397
- return this.formValidatorService.isFieldValid(field, this.productForm);
398
- }
399
- /**
400
- * Method to find error in form fields
401
- */
402
- getErrorMessage(field) {
403
- return this.formValidatorService.getErrorMessage(field, this.productForm, errorMessages);
404
- }
405
- /**
406
- * Checks displayed Form Fields array for form field and returns boolean result
407
- */
408
- isFormFieldShown(fieldName) {
409
- return (this.displayedFormFields.length > 0 &&
410
- this.displayedFormFields.includes(fieldName));
411
- }
412
- /**
413
- * Checks displayed Form Section array for form section and returns boolean result
414
- */
415
- isFormSectionShown(sectionName) {
416
- return (this.displayedFormSections.length > 0 &&
417
- this.displayedFormSections.includes(sectionName));
418
- }
419
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormComponent, deps: [{ token: ProductService }, { token: i2.FormBuilder }, { token: i1$1.FormValidatorService }, { token: i1$1.AlertService }, { token: i4.DatePipe }, { token: ProductFormService }], target: i0.ɵɵFactoryTarget.Component });
420
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductFormComponent, selector: "app-product-form", inputs: { product: "product", displayedFormFields: "displayedFormFields", displayedFormSections: "displayedFormSections" }, outputs: { saved: "saved", cancelled: "cancelled" }, ngImport: i0, template: "<form [formGroup]=\"productForm\" (submit)=\"save()\">\n <h3 class=\"text-center\">{{ product?.id ? \"Update\" : \"Create\" }} Product</h3>\n <div fxLayout=\"column\">\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('basic information')\">\n <h3><strong>Basic Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('name')\">\n <input matInput placeholder=\"Name\" formControlName=\"name\" required />\n <mat-error *ngIf=\"isFieldValid('name')\"\n >{{ getErrorMessage(\"name\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('product type')\">\n <mat-label>Product Type</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-types\"\n formControlName=\"type_id\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('type_id')\"\n >{{ getErrorMessage(\"type_id\") }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('sku')\">\n <input matInput placeholder=\"SKU\" formControlName=\"sku\" />\n <mat-error *ngIf=\"isFieldValid('sku')\"\n >{{ getErrorMessage(\"sku\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field fxFlex=\"50%\">\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('category_ids')\">\n {{ getErrorMessage(\"category_ids\") }}\n </mat-error>\n </mat-form-field>\n </div>\n\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"100%\" *ngIf=\"isFormFieldShown('description')\">\n <textarea\n matInput\n placeholder=\"Description\"\n formControlName=\"description\"\n ></textarea>\n </mat-form-field>\n </div>\n </div>\n\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('inventory information')\">\n <h3><strong>Inventory Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('product measure')\"\n >\n <mat-label>Measure</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-measures\"\n formControlName=\"measure_id\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('measure_id')\"\n >{{ getErrorMessage(\"measure_id\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('reorder point')\">\n <input\n matInput\n placeholder=\"Reorder Point\"\n formControlName=\"reorder_point\"\n type=\"number\"\n />\n <mat-error *ngIf=\"isFieldValid('reorder_point')\"\n >{{ getErrorMessage(\"reorder_point\") }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('initial quantity')\"\n >\n <input\n matInput\n placeholder=\"Initial Quantity\"\n formControlName=\"initial_quantity\"\n />\n <mat-error *ngIf=\"isFieldValid('initial_quantity')\"\n >{{ getErrorMessage(\"initial_quantity\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('initial quantity date')\"\n >\n <input\n matInput\n [matDatepicker]=\"pickerInitialQuantityDate\"\n placeholder=\"Initial Quantity Date\"\n formControlName=\"initial_quantity_date\"\n />\n <mat-datepicker-toggle\n matSuffix\n [for]=\"pickerInitialQuantityDate\"\n ></mat-datepicker-toggle>\n <mat-datepicker #pickerInitialQuantityDate></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('initial_quantity_date')\"\n >{{ getErrorMessage(\"initial_quantity_date\") }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('sales information')\">\n <h3><strong>Sale Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('sales price')\">\n <input\n matInput\n placeholder=\"Selling Price\"\n formControlName=\"sale_price\"\n required\n type=\"number\"\n step=\"any\"\n />\n <mat-error *ngIf=\"isFieldValid('sale_price')\"\n >{{ getErrorMessage(\"sale_price\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('condition types')\"\n >\n <mat-label>Condition</mat-label>\n <app-searchable-selector\n apiUrl=\"api/condition-types\"\n formControlName=\"condition_type_id\"\n ></app-searchable-selector>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('minimum price')\">\n <input\n matInput\n placeholder=\"Minimum Price\"\n formControlName=\"minimum_price\"\n required\n type=\"number\"\n step=\"any\"\n />\n <mat-error *ngIf=\"isFieldValid('minimum_price')\"\n >{{ getErrorMessage(\"minimum_price\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('maximum price')\">\n <input\n matInput\n placeholder=\"Maximum Price\"\n formControlName=\"maximum_price\"\n type=\"number\"\n step=\"any\"\n />\n </mat-form-field>\n </div>\n </div>\n <!-- <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('accounts information')\">-->\n <!-- <h3><strong>Accounts Information</strong></h3>-->\n <!-- <div fxLayout fxLayoutGap=\"0.5rem\">-->\n <!-- <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('income account')\">-->\n <!-- <mat-label>Income Account</mat-label>-->\n <!-- <app-searchable-selector apiUrl=\"api/accounts\" formControlName=\"income_account_id\"> </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('expense account')\">-->\n <!-- <mat-label>Expense Account</mat-label>-->\n <!-- <app-searchable-selector apiUrl=\"api/accounts\" formControlName=\"expense_account_id\">-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- </div>-->\n <!-- </div>-->\n <div fxFlex=\"100%\" fxLayout fxLayoutAlign=\"end\" fxLayoutGap=\"1rem\">\n <button\n [disabled]=\"isWorking\"\n mat-button\n class=\"mt-2\"\n type=\"button\"\n (click)=\"cancelled.emit(true)\"\n >\n Cancel\n </button>\n <button\n [disabled]=\"isWorking\"\n mat-raised-button\n color=\"primary\"\n class=\"mt-2\"\n type=\"submit\"\n >\n Save\n </button>\n </div>\n </div>\n</form>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1$1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "component", type: i7.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i9.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i9.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i10.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i10.DefaultLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i10.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i10.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], preserveWhitespaces: true });
421
- }
422
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormComponent, decorators: [{
423
- type: Component,
424
- args: [{ selector: "app-product-form", template: "<form [formGroup]=\"productForm\" (submit)=\"save()\">\n <h3 class=\"text-center\">{{ product?.id ? \"Update\" : \"Create\" }} Product</h3>\n <div fxLayout=\"column\">\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('basic information')\">\n <h3><strong>Basic Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('name')\">\n <input matInput placeholder=\"Name\" formControlName=\"name\" required />\n <mat-error *ngIf=\"isFieldValid('name')\"\n >{{ getErrorMessage(\"name\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('product type')\">\n <mat-label>Product Type</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-types\"\n formControlName=\"type_id\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('type_id')\"\n >{{ getErrorMessage(\"type_id\") }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('sku')\">\n <input matInput placeholder=\"SKU\" formControlName=\"sku\" />\n <mat-error *ngIf=\"isFieldValid('sku')\"\n >{{ getErrorMessage(\"sku\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field fxFlex=\"50%\">\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('category_ids')\">\n {{ getErrorMessage(\"category_ids\") }}\n </mat-error>\n </mat-form-field>\n </div>\n\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"100%\" *ngIf=\"isFormFieldShown('description')\">\n <textarea\n matInput\n placeholder=\"Description\"\n formControlName=\"description\"\n ></textarea>\n </mat-form-field>\n </div>\n </div>\n\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('inventory information')\">\n <h3><strong>Inventory Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('product measure')\"\n >\n <mat-label>Measure</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-measures\"\n formControlName=\"measure_id\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('measure_id')\"\n >{{ getErrorMessage(\"measure_id\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('reorder point')\">\n <input\n matInput\n placeholder=\"Reorder Point\"\n formControlName=\"reorder_point\"\n type=\"number\"\n />\n <mat-error *ngIf=\"isFieldValid('reorder_point')\"\n >{{ getErrorMessage(\"reorder_point\") }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('initial quantity')\"\n >\n <input\n matInput\n placeholder=\"Initial Quantity\"\n formControlName=\"initial_quantity\"\n />\n <mat-error *ngIf=\"isFieldValid('initial_quantity')\"\n >{{ getErrorMessage(\"initial_quantity\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('initial quantity date')\"\n >\n <input\n matInput\n [matDatepicker]=\"pickerInitialQuantityDate\"\n placeholder=\"Initial Quantity Date\"\n formControlName=\"initial_quantity_date\"\n />\n <mat-datepicker-toggle\n matSuffix\n [for]=\"pickerInitialQuantityDate\"\n ></mat-datepicker-toggle>\n <mat-datepicker #pickerInitialQuantityDate></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('initial_quantity_date')\"\n >{{ getErrorMessage(\"initial_quantity_date\") }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('sales information')\">\n <h3><strong>Sale Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('sales price')\">\n <input\n matInput\n placeholder=\"Selling Price\"\n formControlName=\"sale_price\"\n required\n type=\"number\"\n step=\"any\"\n />\n <mat-error *ngIf=\"isFieldValid('sale_price')\"\n >{{ getErrorMessage(\"sale_price\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('condition types')\"\n >\n <mat-label>Condition</mat-label>\n <app-searchable-selector\n apiUrl=\"api/condition-types\"\n formControlName=\"condition_type_id\"\n ></app-searchable-selector>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('minimum price')\">\n <input\n matInput\n placeholder=\"Minimum Price\"\n formControlName=\"minimum_price\"\n required\n type=\"number\"\n step=\"any\"\n />\n <mat-error *ngIf=\"isFieldValid('minimum_price')\"\n >{{ getErrorMessage(\"minimum_price\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('maximum price')\">\n <input\n matInput\n placeholder=\"Maximum Price\"\n formControlName=\"maximum_price\"\n type=\"number\"\n step=\"any\"\n />\n </mat-form-field>\n </div>\n </div>\n <!-- <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('accounts information')\">-->\n <!-- <h3><strong>Accounts Information</strong></h3>-->\n <!-- <div fxLayout fxLayoutGap=\"0.5rem\">-->\n <!-- <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('income account')\">-->\n <!-- <mat-label>Income Account</mat-label>-->\n <!-- <app-searchable-selector apiUrl=\"api/accounts\" formControlName=\"income_account_id\"> </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('expense account')\">-->\n <!-- <mat-label>Expense Account</mat-label>-->\n <!-- <app-searchable-selector apiUrl=\"api/accounts\" formControlName=\"expense_account_id\">-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- </div>-->\n <!-- </div>-->\n <div fxFlex=\"100%\" fxLayout fxLayoutAlign=\"end\" fxLayoutGap=\"1rem\">\n <button\n [disabled]=\"isWorking\"\n mat-button\n class=\"mt-2\"\n type=\"button\"\n (click)=\"cancelled.emit(true)\"\n >\n Cancel\n </button>\n <button\n [disabled]=\"isWorking\"\n mat-raised-button\n color=\"primary\"\n class=\"mt-2\"\n type=\"submit\"\n >\n Save\n </button>\n </div>\n </div>\n</form>\n" }]
425
- }], ctorParameters: () => [{ type: ProductService }, { type: i2.FormBuilder }, { type: i1$1.FormValidatorService }, { type: i1$1.AlertService }, { type: i4.DatePipe }, { type: ProductFormService }], propDecorators: { saved: [{
426
- type: Output
427
- }], cancelled: [{
428
- type: Output
429
- }], product: [{
430
- type: Input
431
- }], displayedFormFields: [{
432
- type: Input
433
- }], displayedFormSections: [{
434
- type: Input
435
- }] } });
436
-
437
- class ProductFormButtonComponent {
438
- matDialog;
439
- productFormService;
440
- product;
441
- saved = new EventEmitter();
442
- constructor(matDialog, productFormService) {
443
- this.matDialog = matDialog;
444
- this.productFormService = productFormService;
445
- }
446
- showForm(templateRef) {
447
- this.matDialog.open(templateRef, { width: "600px" });
448
- }
449
- /**
450
- * Handle on product saved event.
451
- *
452
- * @param product
453
- */
454
- onProductSaved(product) {
455
- this.saved.emit(product);
456
- this.matDialog?.closeAll();
457
- this.productFormService.listUpdated(true);
458
- }
459
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormButtonComponent, deps: [{ token: i1.MatDialog }, { token: ProductFormService }], target: i0.ɵɵFactoryTarget.Component });
460
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductFormButtonComponent, selector: "app-product-form-button", inputs: { product: "product" }, outputs: { saved: "saved" }, ngImport: i0, template: "<mat-icon\n color=\"primary\"\n class=\"cursor-pointer\"\n [class.text-secondary]=\"product\"\n (click)=\"showForm(addProductForm)\"\n>\n {{ product ? \"edit\" : \"add\" }}\n</mat-icon>\n\n<ng-template #addProductForm>\n <app-product-form\n [product]=\"product\"\n mat-dialog-content\n (saved)=\"onProductSaved($event)\"\n (cancelled)=\"matDialog.closeAll()\"\n ></app-product-form>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ProductFormComponent, selector: "app-product-form", inputs: ["product", "displayedFormFields", "displayedFormSections"], outputs: ["saved", "cancelled"] }], preserveWhitespaces: true });
461
- }
462
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormButtonComponent, decorators: [{
463
- type: Component,
464
- args: [{ selector: "app-product-form-button", template: "<mat-icon\n color=\"primary\"\n class=\"cursor-pointer\"\n [class.text-secondary]=\"product\"\n (click)=\"showForm(addProductForm)\"\n>\n {{ product ? \"edit\" : \"add\" }}\n</mat-icon>\n\n<ng-template #addProductForm>\n <app-product-form\n [product]=\"product\"\n mat-dialog-content\n (saved)=\"onProductSaved($event)\"\n (cancelled)=\"matDialog.closeAll()\"\n ></app-product-form>\n</ng-template>\n" }]
465
- }], ctorParameters: () => [{ type: i1.MatDialog }, { type: ProductFormService }], propDecorators: { product: [{
466
- type: Input
467
- }], saved: [{
468
- type: Output
469
- }] } });
470
-
471
- let ProductListComponent = class ProductListComponent {
472
- fb;
473
- dialog;
474
- activatedRoute;
475
- productService;
476
- requestHelperService;
477
- productFormService;
478
- filterForm;
479
- lastPage;
480
- page = 1;
481
- perPage = 25;
482
- totalItems = 0;
483
- currentPage = 1;
484
- num_items = 25;
485
- routeFilters;
486
- products = [];
487
- dataSource = new MatTableDataSource();
488
- isLoading = false;
489
- columnConfig = [
490
- { label: '#', def: '#', isSelected: true, isEditable: true },
491
- { label: 'Name', def: 'name', isSelected: true, isEditable: true },
492
- { label: 'SKU', def: 'sku', isSelected: true, isEditable: true },
493
- { label: 'Categories', def: 'categories', isSelected: true, isEditable: true },
494
- { label: 'Initial Quantity', def: 'initial_quantity', isSelected: true, isEditable: true },
495
- { label: 'Reorder Point', def: 'reorder_point', isSelected: true, isEditable: true },
496
- { label: 'Stock Receipts', def: 'stock_receipts', isSelected: true, isEditable: true },
497
- { label: 'Stock Issuances', def: 'stock_issuances', isSelected: true, isEditable: true },
498
- { label: 'On Hand', def: 'on_hand', isSelected: true, isEditable: true },
499
- { label: 'Sale Price', def: 'sale_price', isSelected: true, isEditable: true },
500
- { label: 'Income Account', def: 'income_account', isSelected: false, isEditable: true },
501
- { label: 'Expense Account', def: 'expense_account', isSelected: false, isEditable: true },
502
- { label: 'Creator', def: 'creator', isSelected: false, isEditable: true },
503
- { label: 'Actions', def: 'Actions', isSelected: true, isEditable: true },
504
- ];
505
- selectedColumns = this.columnConfig.filter(col => col.isSelected);
506
- get displayedColumns() {
507
- return this.selectedColumns.map(col => col.def);
508
- }
509
- importId;
510
- constructor(fb, dialog, activatedRoute, productService, requestHelperService, productFormService) {
511
- this.fb = fb;
512
- this.dialog = dialog;
513
- this.activatedRoute = activatedRoute;
514
- this.productService = productService;
515
- this.requestHelperService = requestHelperService;
516
- this.productFormService = productFormService;
517
- this.filterForm = this.fb.group({
518
- search: [""],
519
- category_ids: [""],
520
- type_ids: [""],
521
- income_account_ids: [""],
522
- expense_account_ids: [""],
523
- sort_by: [""],
524
- });
525
- }
526
- ngOnInit() {
527
- if (this.activatedRoute.snapshot.params?.["import_id"]) {
528
- this.importId = parseInt(this.activatedRoute.snapshot.params?.["import_id"]);
529
- }
530
- // update form with URL query params
531
- this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
532
- type_ids: { multiple: true },
533
- category_ids: { multiple: true },
534
- income_account_ids: { multiple: true },
535
- expense_account_ids: { multiple: true },
536
- });
537
- // Update URL query params on filter change
538
- this.filterForm.valueChanges.pipe(debounceTime(800)).subscribe(() => {
539
- this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData({
540
- ...this.filterForm.value,
541
- }));
542
- });
543
- // fetch task on params change
544
- this.activatedRoute.queryParams
545
- .pipe(debounceTime(800))
546
- .subscribe(() => this.reload());
547
- // listen form product add or update event and reload.
548
- this.productFormService.isListUpdated().subscribe((val) => {
549
- if (val && !this.isLoading) {
550
- this.reload();
551
- }
552
- });
553
- }
554
- loadData() {
555
- let params = {
556
- ...this.requestHelperService.convertToFormData(this.filterForm.value),
557
- };
558
- params.page = this.page;
559
- params.perPage = this.perPage;
560
- params.num_items = this.num_items + "|" + this.currentPage;
561
- params.with = "categories,lastStockReceipt,lastStockIssuance,creator";
562
- if (this.importId) {
563
- params.import_id = this.importId;
564
- }
565
- this.isLoading = true;
566
- this.productService.index(params).subscribe({
567
- next: (res) => {
568
- this.isLoading = false;
569
- this.dataSource = new MatTableDataSource(this.dataSource.data.concat(res?.data));
570
- this.totalItems = res.total;
571
- // stop reloading data once data loaded.
572
- this.productFormService.listUpdated(false);
573
- },
574
- error: () => (this.isLoading = false),
575
- });
576
- }
577
- reload() {
578
- if (this.isLoading)
579
- return;
580
- this.dataSource = new MatTableDataSource();
581
- this.currentPage = 1;
582
- this.loadData();
583
- }
584
- modifyProduct(model) {
585
- const dialogRef = this.dialog.open(ProductFormComponent, {
586
- width: "600px",
587
- data: {
588
- details: model,
589
- },
590
- });
591
- dialogRef.afterClosed().subscribe((result) => {
592
- if (result) {
593
- this.reload();
594
- }
595
- });
596
- }
597
- assignFilter(column, direction) {
598
- if (column) {
599
- return this.filterForm.get("sort_by")?.setValue(column + "|" + direction);
600
- }
601
- }
602
- sortColumn(event) {
603
- var direction = event.direction.toString().toUpperCase();
604
- this.assignFilter(event.active, direction);
605
- }
606
- onScroll() {
607
- if (this.totalItems > this.dataSource.data.length) {
608
- this.currentPage += 1;
609
- this.loadData();
610
- }
611
- }
612
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductListComponent, deps: [{ token: i2.FormBuilder }, { token: i1.MatDialog }, { token: i2$1.ActivatedRoute }, { token: ProductService }, { token: i1$1.RequestHelperService }, { token: ProductFormService }], target: i0.ɵɵFactoryTarget.Component });
613
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductListComponent, selector: "app-product-list", ngImport: i0, template: "<mat-card class=\"mb-3\">\n <mat-card-content>\n <form\n [formGroup]=\"filterForm\"\n class=\"d-flex justify-content-between align-items-center gap-2\"\n >\n <div class=\"d-flex justify-content-center align-items-center gap-2\">\n <h3 class=\"mb-0\">Products</h3>\n <app-product-form-button class=\"mt-2\"></app-product-form-button>\n <span matTooltip=\"Import\" routerLink=\"import\" class=\"cursor-pointer mt-1 material-symbols-outlined\">\n file_save\n </span>\n <app-column-selector\n mode=\"icon\"\n class=\"mb-2 d-print-none\"\n [columnConfigs]=\"columnConfig\"\n [(selectedColumns)]=\"selectedColumns\"\n ></app-column-selector>\n </div>\n\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <mat-form-field style=\"width: 120px\">\n <input matInput placeholder=\"Product\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field style=\"width: 120px\">\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field style=\"width: 120px\">\n <mat-label>Type</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-types\"\n formControlName=\"type_ids\"\n titleField=\"title\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n <!-- <mat-form-field style=\"width: 150px\">-->\n <!-- <mat-label>Income Account</mat-label>-->\n <!-- <app-searchable-selector-->\n <!-- apiUrl=\"api/accounts\"-->\n <!-- formControlName=\"income_account_ids\"-->\n <!-- titleField=\"title\"-->\n <!-- [multiple]=\"true\"-->\n <!-- >-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- <mat-form-field style=\"width: 150px\">-->\n <!-- <mat-label>Expense Account</mat-label>-->\n <!-- <app-searchable-selector-->\n <!-- apiUrl=\"api/accounts\"-->\n <!-- formControlName=\"expense_account_ids\"-->\n <!-- titleField=\"title\"-->\n <!-- [multiple]=\"true\"-->\n <!-- >-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n </div>\n </form>\n </mat-card-content>\n</mat-card>\n\n<mat-card>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"dataSource\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n [fromRoot]=\"true\"\n matSort\n (matSortChange)=\"sortColumn($event)\"\n matSortDisableClear=\"true\"\n aria-describedby=\"Products List\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Name</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex flex-column gap-1\">\n <a class=\"text-decoration-none text-dark\" [routerLink]=\"[element?.id, 'view']\">{{ element.name }}</a>\n <small class=\"text-secondary\" *ngIf=\"element.type\">{{ element.type?.title }}</small>\n </div>\n </td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"categories\">\n <th mat-header-cell *matHeaderCellDef>Categories</th>\n <td mat-cell *matCellDef=\"let element\" style=\"max-width: 200px\">\n <div\n *ngIf=\"element?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1 flex-wrap\"\n >\n <span\n class=\"badge bg-secondary\"\n *ngFor=\"let category of element?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"sku\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.sku }}</td>\n </ng-container>\n\n <!-- Initial Quantity Column -->\n <ng-container matColumnDef=\"initial_quantity\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n Initial Quantity\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element.initial_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.initial_quantity_date\">\n on {{ element?.initial_quantity_date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- Stock Receipts Column -->\n <ng-container matColumnDef=\"stock_receipts\">\n <th mat-header-cell mat-sort-header=\"stock_receipts_sum_quantity\" *matHeaderCellDef>\n Stock Receipts\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.stock_receipts_sum_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_receipt\">\n last added on {{ element?.last_stock_receipt?.date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- Stock Issuances Column -->\n <ng-container matColumnDef=\"stock_issuances\">\n <th mat-header-cell mat-sort-header=\"stock_issuances_sum_quantity\" *matHeaderCellDef>\n Stock Issuances\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.stock_issuances_sum_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_issuance\">\n last issued on {{ element?.last_stock_issuance?.date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- On Hand Column -->\n <ng-container matColumnDef=\"on_hand\">\n <th mat-header-cell mat-sort-header=\"stock_balance\" *matHeaderCellDef>On Hand</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock_balance }}\n </td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"reorder_point\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Reorder Point</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element.reorder_point }}\n </td>\n </ng-container>\n\n <!-- Selling Price Column -->\n <ng-container matColumnDef=\"sale_price\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Selling Price</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element.sale_price | currency }}\n </td>\n </ng-container>\n\n <!-- Income Account Column -->\n <ng-container matColumnDef=\"income_account\">\n <th mat-header-cell *matHeaderCellDef>Income Account</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.income_account?.title }}\n </td>\n </ng-container>\n\n <!-- Expense Account Column -->\n <ng-container matColumnDef=\"expense_account\">\n <th mat-header-cell *matHeaderCellDef>Expense Account</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.expense_account?.title }}\n </td>\n </ng-container>\n\n <!-- Creator Column -->\n <ng-container matColumnDef=\"creator\">\n <th mat-header-cell *matHeaderCellDef>Creator</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.creator?.name }}</p>\n <small class=\"text-secondary\">{{ element?.created_at | date }}</small>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary d-flex gap-1\">\n <app-product-form-button\n [product]=\"element\"\n ></app-product-form-button>\n <mat-icon\n class=\"cursor-pointer\"\n matTooltip=\"View\"\n [routerLink]=\"[element.id, 'view']\"\n routerLinkActive=\"route-link-active\"\n >\n remove_red_eye\n </mat-icon>\n\n <app-stock-receipt-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-issue-form-button>\n </div>\n </td>\n </ng-container>\n <tr\n mat-header-row\n *matHeaderRowDef=\"displayedColumns; sticky: true\"\n ></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2$1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: i1$1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "component", type: StockReceiptFormButtonComponent, selector: "app-stock-receipt-form-button", inputs: ["product", "stockReceipt", "icon"], outputs: ["saved"] }, { kind: "component", type: StockIssueFormButtonComponent, selector: "app-stock-issue-form-button", inputs: ["product", "stockIssuance", "icon", "issuableType", "issuableId"], outputs: ["saved"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i5.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i5.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i6$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i6$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i3$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i3$2.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i2$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i7$2.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: i10$2.InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i1$1.ColumnSelectorComponent, selector: "app-column-selector", inputs: ["label", "mode", "columnConfigs", "selectedColumns"], outputs: ["selectedColumnsChange", "displayedColumnsChange"] }, { kind: "component", type: ProductFormButtonComponent, selector: "app-product-form-button", inputs: ["product"], outputs: ["saved"] }, { kind: "pipe", type: i4.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i4.DatePipe, name: "date" }], preserveWhitespaces: true });
614
- };
615
- ProductListComponent = __decorate([
616
- UntilDestroy()
617
- ], ProductListComponent);
618
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductListComponent, decorators: [{
619
- type: Component,
620
- args: [{ selector: "app-product-list", template: "<mat-card class=\"mb-3\">\n <mat-card-content>\n <form\n [formGroup]=\"filterForm\"\n class=\"d-flex justify-content-between align-items-center gap-2\"\n >\n <div class=\"d-flex justify-content-center align-items-center gap-2\">\n <h3 class=\"mb-0\">Products</h3>\n <app-product-form-button class=\"mt-2\"></app-product-form-button>\n <span matTooltip=\"Import\" routerLink=\"import\" class=\"cursor-pointer mt-1 material-symbols-outlined\">\n file_save\n </span>\n <app-column-selector\n mode=\"icon\"\n class=\"mb-2 d-print-none\"\n [columnConfigs]=\"columnConfig\"\n [(selectedColumns)]=\"selectedColumns\"\n ></app-column-selector>\n </div>\n\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <mat-form-field style=\"width: 120px\">\n <input matInput placeholder=\"Product\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field style=\"width: 120px\">\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field style=\"width: 120px\">\n <mat-label>Type</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-types\"\n formControlName=\"type_ids\"\n titleField=\"title\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n <!-- <mat-form-field style=\"width: 150px\">-->\n <!-- <mat-label>Income Account</mat-label>-->\n <!-- <app-searchable-selector-->\n <!-- apiUrl=\"api/accounts\"-->\n <!-- formControlName=\"income_account_ids\"-->\n <!-- titleField=\"title\"-->\n <!-- [multiple]=\"true\"-->\n <!-- >-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- <mat-form-field style=\"width: 150px\">-->\n <!-- <mat-label>Expense Account</mat-label>-->\n <!-- <app-searchable-selector-->\n <!-- apiUrl=\"api/accounts\"-->\n <!-- formControlName=\"expense_account_ids\"-->\n <!-- titleField=\"title\"-->\n <!-- [multiple]=\"true\"-->\n <!-- >-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n </div>\n </form>\n </mat-card-content>\n</mat-card>\n\n<mat-card>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"dataSource\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n [fromRoot]=\"true\"\n matSort\n (matSortChange)=\"sortColumn($event)\"\n matSortDisableClear=\"true\"\n aria-describedby=\"Products List\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Name</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex flex-column gap-1\">\n <a class=\"text-decoration-none text-dark\" [routerLink]=\"[element?.id, 'view']\">{{ element.name }}</a>\n <small class=\"text-secondary\" *ngIf=\"element.type\">{{ element.type?.title }}</small>\n </div>\n </td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"categories\">\n <th mat-header-cell *matHeaderCellDef>Categories</th>\n <td mat-cell *matCellDef=\"let element\" style=\"max-width: 200px\">\n <div\n *ngIf=\"element?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1 flex-wrap\"\n >\n <span\n class=\"badge bg-secondary\"\n *ngFor=\"let category of element?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"sku\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.sku }}</td>\n </ng-container>\n\n <!-- Initial Quantity Column -->\n <ng-container matColumnDef=\"initial_quantity\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n Initial Quantity\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element.initial_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.initial_quantity_date\">\n on {{ element?.initial_quantity_date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- Stock Receipts Column -->\n <ng-container matColumnDef=\"stock_receipts\">\n <th mat-header-cell mat-sort-header=\"stock_receipts_sum_quantity\" *matHeaderCellDef>\n Stock Receipts\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.stock_receipts_sum_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_receipt\">\n last added on {{ element?.last_stock_receipt?.date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- Stock Issuances Column -->\n <ng-container matColumnDef=\"stock_issuances\">\n <th mat-header-cell mat-sort-header=\"stock_issuances_sum_quantity\" *matHeaderCellDef>\n Stock Issuances\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.stock_issuances_sum_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_issuance\">\n last issued on {{ element?.last_stock_issuance?.date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- On Hand Column -->\n <ng-container matColumnDef=\"on_hand\">\n <th mat-header-cell mat-sort-header=\"stock_balance\" *matHeaderCellDef>On Hand</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock_balance }}\n </td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"reorder_point\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Reorder Point</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element.reorder_point }}\n </td>\n </ng-container>\n\n <!-- Selling Price Column -->\n <ng-container matColumnDef=\"sale_price\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Selling Price</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element.sale_price | currency }}\n </td>\n </ng-container>\n\n <!-- Income Account Column -->\n <ng-container matColumnDef=\"income_account\">\n <th mat-header-cell *matHeaderCellDef>Income Account</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.income_account?.title }}\n </td>\n </ng-container>\n\n <!-- Expense Account Column -->\n <ng-container matColumnDef=\"expense_account\">\n <th mat-header-cell *matHeaderCellDef>Expense Account</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.expense_account?.title }}\n </td>\n </ng-container>\n\n <!-- Creator Column -->\n <ng-container matColumnDef=\"creator\">\n <th mat-header-cell *matHeaderCellDef>Creator</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.creator?.name }}</p>\n <small class=\"text-secondary\">{{ element?.created_at | date }}</small>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary d-flex gap-1\">\n <app-product-form-button\n [product]=\"element\"\n ></app-product-form-button>\n <mat-icon\n class=\"cursor-pointer\"\n matTooltip=\"View\"\n [routerLink]=\"[element.id, 'view']\"\n routerLinkActive=\"route-link-active\"\n >\n remove_red_eye\n </mat-icon>\n\n <app-stock-receipt-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-issue-form-button>\n </div>\n </td>\n </ng-container>\n <tr\n mat-header-row\n *matHeaderRowDef=\"displayedColumns; sticky: true\"\n ></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n" }]
621
- }], ctorParameters: () => [{ type: i2.FormBuilder }, { type: i1.MatDialog }, { type: i2$1.ActivatedRoute }, { type: ProductService }, { type: i1$1.RequestHelperService }, { type: ProductFormService }] });
622
-
623
- class ProductNavBarComponent {
624
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductNavBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
625
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductNavBarComponent, selector: "app-product-nav-bar", ngImport: i0, template: "<div>\n <router-outlet></router-outlet>\n</div>\n", dependencies: [{ kind: "directive", type: i2$1.RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], preserveWhitespaces: true });
626
- }
627
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductNavBarComponent, decorators: [{
628
- type: Component,
629
- args: [{ selector: "app-product-nav-bar", template: "<div>\n <router-outlet></router-outlet>\n</div>\n" }]
630
- }] });
631
-
632
- class ProductTaxService extends TechlifyServiceBaseClass {
633
- constructor(httpService) {
634
- super(httpService, "product-taxes");
635
- }
636
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxService, deps: [{ token: i1$1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
637
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxService, providedIn: "root" });
638
- }
639
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxService, decorators: [{
640
- type: Injectable,
641
- args: [{
642
- providedIn: "root",
643
- }]
644
- }], ctorParameters: () => [{ type: i1$1.HttpService }] });
645
-
646
- class ProductTaxFormButtonComponent extends TechlifyFormComponentInterface {
647
- matDialog;
648
- productTaxService;
649
- formBuilder;
650
- alertService;
651
- product;
652
- saved = new EventEmitter();
653
- isSaving;
654
- constructor(matDialog, productTaxService, formValidatorService, formBuilder, alertService) {
655
- super(formValidatorService);
656
- this.matDialog = matDialog;
657
- this.productTaxService = productTaxService;
658
- this.formBuilder = formBuilder;
659
- this.alertService = alertService;
660
- this.errorMessages = {
661
- tax_id: {
662
- required: "The tax field is required.",
663
- },
664
- };
665
- this.form = this.formBuilder.group({
666
- product_id: [""],
667
- tax_id: ["", Validators.required],
668
- });
669
- }
670
- ngOnInit() {
671
- if (this.product) {
672
- this.form.get("product_id")?.setValue(this.product?.id);
673
- }
674
- }
675
- showForm(templateRef) {
676
- this.matDialog.open(templateRef, { width: "400px" });
677
- }
678
- save() {
679
- this.form.markAllAsTouched();
680
- if (this.form.invalid) {
681
- this.alertService.addAlert("Please check the form for errors.", "error");
682
- return;
683
- }
684
- const data = { ...this.form.value };
685
- const params = {
686
- with: "tax.type",
687
- };
688
- this.isSaving = true;
689
- this.productTaxService.store(data, params).subscribe({
690
- next: (response) => {
691
- this.isSaving = false;
692
- this.matDialog.closeAll();
693
- this.alertService.addAlert("Product tax saved successfully!", "success");
694
- this.saved.emit(response?.item);
695
- },
696
- error: () => (this.isSaving = false),
697
- });
698
- }
699
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxFormButtonComponent, deps: [{ token: i1.MatDialog }, { token: ProductTaxService }, { token: i1$1.FormValidatorService }, { token: i2.FormBuilder }, { token: i1$1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
700
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductTaxFormButtonComponent, selector: "app-product-tax-form-button", inputs: { product: "product" }, outputs: { saved: "saved" }, usesInheritance: true, ngImport: i0, template: "<mat-icon\n color=\"primary\"\n class=\"cursor-pointer\"\n (click)=\"showForm(formTemplate)\"\n>\n add\n</mat-icon>\n\n<ng-template #formTemplate>\n <form\n [formGroup]=\"form\"\n (submit)=\"save()\"\n mat-dialog-content\n class=\"d-flex flex-column gap-2\"\n >\n <h3 class=\"text-dark\">Add tax for {{ product?.name }}</h3>\n <mat-form-field>\n <mat-label>Tax</mat-label>\n <app-searchable-selector\n formControlName=\"tax_id\"\n required\n apiUrl=\"api/taxes\"\n [enableSearch]=\"false\"\n ></app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('tax_id')\">\n {{ getErrorMessage(\"tax_id\") }}\n </mat-error>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-3\">\n <button\n [disabled]=\"isSaving\"\n type=\"submit\"\n mat-raised-button\n color=\"primary\"\n >\n Save\n </button>\n <button\n [disabled]=\"isSaving\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n </form>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i1$1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }], preserveWhitespaces: true });
701
- }
702
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxFormButtonComponent, decorators: [{
703
- type: Component,
704
- args: [{ selector: "app-product-tax-form-button", template: "<mat-icon\n color=\"primary\"\n class=\"cursor-pointer\"\n (click)=\"showForm(formTemplate)\"\n>\n add\n</mat-icon>\n\n<ng-template #formTemplate>\n <form\n [formGroup]=\"form\"\n (submit)=\"save()\"\n mat-dialog-content\n class=\"d-flex flex-column gap-2\"\n >\n <h3 class=\"text-dark\">Add tax for {{ product?.name }}</h3>\n <mat-form-field>\n <mat-label>Tax</mat-label>\n <app-searchable-selector\n formControlName=\"tax_id\"\n required\n apiUrl=\"api/taxes\"\n [enableSearch]=\"false\"\n ></app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('tax_id')\">\n {{ getErrorMessage(\"tax_id\") }}\n </mat-error>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-3\">\n <button\n [disabled]=\"isSaving\"\n type=\"submit\"\n mat-raised-button\n color=\"primary\"\n >\n Save\n </button>\n <button\n [disabled]=\"isSaving\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n </form>\n</ng-template>\n" }]
705
- }], ctorParameters: () => [{ type: i1.MatDialog }, { type: ProductTaxService }, { type: i1$1.FormValidatorService }, { type: i2.FormBuilder }, { type: i1$1.AlertService }], propDecorators: { product: [{
706
- type: Input
707
- }], saved: [{
708
- type: Output
709
- }] } });
710
-
711
- class ProductTaxDeleteButtonComponent {
712
- matDialog;
713
- productTaxService;
714
- alertService;
715
- productTax;
716
- deleted = new EventEmitter();
717
- isDeleting;
718
- constructor(matDialog, productTaxService, alertService) {
719
- this.matDialog = matDialog;
720
- this.productTaxService = productTaxService;
721
- this.alertService = alertService;
722
- }
723
- /**
724
- * Delete the product.
725
- */
726
- delete() {
727
- this.isDeleting = true;
728
- this.productTaxService.delete(this.productTax).subscribe({
729
- next: () => {
730
- this.matDialog?.closeAll();
731
- this.deleted.emit();
732
- this.isDeleting = false;
733
- this.alertService.addAlert("Product tax deleted successfully!", "success");
734
- },
735
- error: () => (this.isDeleting = false),
736
- });
737
- }
738
- /**
739
- * Show delete product dialog.
740
- *
741
- * @param templateRef
742
- */
743
- showDeleteDialog(templateRef) {
744
- this.matDialog.open(templateRef, { width: "500px" });
745
- }
746
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxDeleteButtonComponent, deps: [{ token: i1.MatDialog }, { token: ProductTaxService }, { token: i1$1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
747
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductTaxDeleteButtonComponent, selector: "app-product-tax-delete-button", inputs: { productTax: "productTax" }, outputs: { deleted: "deleted" }, ngImport: i0, template: "<mat-icon\n class=\"cursor-pointer text-secondary\"\n (click)=\"showDeleteDialog(deleteConfirmDialog)\"\n>\n delete\n</mat-icon>\n\n<ng-template #deleteConfirmDialog>\n <h3 mat-dialog-title>Delete Product Tax</h3>\n <div mat-dialog-content>\n Are you sure? You want to delete the product tax?\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-raised-button\n color=\"warn\"\n (click)=\"delete()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: i7.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], preserveWhitespaces: true });
748
- }
749
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxDeleteButtonComponent, decorators: [{
750
- type: Component,
751
- args: [{ selector: "app-product-tax-delete-button", template: "<mat-icon\n class=\"cursor-pointer text-secondary\"\n (click)=\"showDeleteDialog(deleteConfirmDialog)\"\n>\n delete\n</mat-icon>\n\n<ng-template #deleteConfirmDialog>\n <h3 mat-dialog-title>Delete Product Tax</h3>\n <div mat-dialog-content>\n Are you sure? You want to delete the product tax?\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-raised-button\n color=\"warn\"\n (click)=\"delete()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n</ng-template>\n" }]
752
- }], ctorParameters: () => [{ type: i1.MatDialog }, { type: ProductTaxService }, { type: i1$1.AlertService }], propDecorators: { productTax: [{
753
- type: Input
754
- }], deleted: [{
755
- type: Output
756
- }] } });
757
-
758
- class ProductTaxListComponent extends TechlifyListingControllerInterface {
759
- product;
760
- displayedColumns = ["#", "Tax", "Actions"];
761
- ngOnInit() {
762
- this.loadData();
763
- }
764
- loadData() {
765
- this.models = this.product?.taxes ?? [];
766
- }
767
- onCreated(productTax) {
768
- this.models.unshift(productTax);
769
- this.models = [...this.models];
770
- }
771
- onDeleted(index) {
772
- this.models.splice(index, 1);
773
- this.models = [...this.models];
774
- }
775
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
776
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductTaxListComponent, selector: "app-product-tax-list", inputs: { product: "product" }, usesInheritance: true, ngImport: i0, template: "<mat-card>\n <mat-card-content\n class=\"pb-3 d-flex justify-content-between align-items-center gap-3\"\n >\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> percent </span>\n <strong class=\"mb-0 text-dark\">Product Taxes</strong>\n </div>\n <app-product-tax-form-button\n [product]=\"product\"\n (saved)=\"onCreated($event)\"\n ></app-product-tax-form-button>\n </mat-card-content>\n <mat-divider></mat-divider>\n <mat-card-content class=\"p-0\">\n <table mat-table [dataSource]=\"models\" class=\"w-100\">\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <ng-container matColumnDef=\"Tax\">\n <th mat-header-cell *matHeaderCellDef>Tax</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">\n {{ element?.tax?.title }} ({{ element?.tax?.code }})\n </p>\n <small class=\"text-secondary\"\n >{{ element?.tax?.value }} - {{ element?.tax?.type?.title }}</small\n >\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">\n <app-product-tax-delete-button\n [productTax]=\"element\"\n (deleted)=\"onDeleted(i)\"\n ></app-product-tax-delete-button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n </mat-card-content>\n</mat-card>\n", dependencies: [{ kind: "component", type: i6$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i6$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i3$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i3$2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i6$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: ProductTaxFormButtonComponent, selector: "app-product-tax-form-button", inputs: ["product"], outputs: ["saved"] }, { kind: "component", type: ProductTaxDeleteButtonComponent, selector: "app-product-tax-delete-button", inputs: ["productTax"], outputs: ["deleted"] }], preserveWhitespaces: true });
777
- }
778
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxListComponent, decorators: [{
779
- type: Component,
780
- args: [{ selector: "app-product-tax-list", template: "<mat-card>\n <mat-card-content\n class=\"pb-3 d-flex justify-content-between align-items-center gap-3\"\n >\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> percent </span>\n <strong class=\"mb-0 text-dark\">Product Taxes</strong>\n </div>\n <app-product-tax-form-button\n [product]=\"product\"\n (saved)=\"onCreated($event)\"\n ></app-product-tax-form-button>\n </mat-card-content>\n <mat-divider></mat-divider>\n <mat-card-content class=\"p-0\">\n <table mat-table [dataSource]=\"models\" class=\"w-100\">\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <ng-container matColumnDef=\"Tax\">\n <th mat-header-cell *matHeaderCellDef>Tax</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">\n {{ element?.tax?.title }} ({{ element?.tax?.code }})\n </p>\n <small class=\"text-secondary\"\n >{{ element?.tax?.value }} - {{ element?.tax?.type?.title }}</small\n >\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">\n <app-product-tax-delete-button\n [productTax]=\"element\"\n (deleted)=\"onDeleted(i)\"\n ></app-product-tax-delete-button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n </mat-card-content>\n</mat-card>\n" }]
781
- }], propDecorators: { product: [{
782
- type: Input
783
- }] } });
784
-
785
- class ProductDeleteButtonComponent {
786
- matDialog;
787
- productService;
788
- alertService;
789
- product;
790
- deleted = new EventEmitter();
791
- isDeleting;
792
- constructor(matDialog, productService, alertService) {
793
- this.matDialog = matDialog;
794
- this.productService = productService;
795
- this.alertService = alertService;
796
- }
797
- /**
798
- * Delete the product.
799
- */
800
- deleteProduct() {
801
- this.isDeleting = true;
802
- this.productService.delete(this.product).subscribe({
803
- next: () => {
804
- this.deleted.emit();
805
- this.isDeleting = false;
806
- this.matDialog.closeAll();
807
- this.alertService.addAlert("Product deleted successfully!", "success");
808
- },
809
- error: () => (this.isDeleting = false),
810
- });
811
- }
812
- /**
813
- * Show delete product dialog.
814
- *
815
- * @param templateRef
816
- */
817
- showDeleteDialog(templateRef) {
818
- this.matDialog.open(templateRef, { width: "500px" });
819
- }
820
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductDeleteButtonComponent, deps: [{ token: i1.MatDialog }, { token: ProductService }, { token: i1$1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
821
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductDeleteButtonComponent, selector: "app-product-delete-button", inputs: { product: "product" }, outputs: { deleted: "deleted" }, ngImport: i0, template: "<mat-icon\n class=\"cursor-pointer text-secondary\"\n (click)=\"showDeleteDialog(deleteProductDialog)\"\n>\n delete\n</mat-icon>\n\n<ng-template #deleteProductDialog>\n <h3 mat-dialog-title>Delete Product</h3>\n <div mat-dialog-content>\n Are you sure? You want to delete the\n <strong>{{ product?.name }}</strong> ?\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-raised-button\n color=\"warn\"\n (click)=\"deleteProduct()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: i7.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], preserveWhitespaces: true });
822
- }
823
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductDeleteButtonComponent, decorators: [{
824
- type: Component,
825
- args: [{ selector: "app-product-delete-button", template: "<mat-icon\n class=\"cursor-pointer text-secondary\"\n (click)=\"showDeleteDialog(deleteProductDialog)\"\n>\n delete\n</mat-icon>\n\n<ng-template #deleteProductDialog>\n <h3 mat-dialog-title>Delete Product</h3>\n <div mat-dialog-content>\n Are you sure? You want to delete the\n <strong>{{ product?.name }}</strong> ?\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-raised-button\n color=\"warn\"\n (click)=\"deleteProduct()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n</ng-template>\n" }]
826
- }], ctorParameters: () => [{ type: i1.MatDialog }, { type: ProductService }, { type: i1$1.AlertService }], propDecorators: { product: [{
827
- type: Input
828
- }], deleted: [{
829
- type: Output
830
- }] } });
831
-
832
- class ProductBasicInfoComponent {
833
- stockSummaryService;
834
- product;
835
- saved = new EventEmitter();
836
- deleted = new EventEmitter();
837
- stockSummary;
838
- constructor(stockSummaryService) {
839
- this.stockSummaryService = stockSummaryService;
840
- }
841
- ngOnInit() {
842
- if (this.product) {
843
- this.loadProductStocksSummary();
844
- }
845
- }
846
- onProductSaved(product) {
847
- this.product = product;
848
- this.saved.emit(this.product);
849
- }
850
- /**
851
- * Load product stocks summary.
852
- */
853
- loadProductStocksSummary() {
854
- const params = {
855
- product_ids: this.product?.id,
856
- include: "stock_receipts_quantity_sum,stock_issuances_quantity_sum,stock_quantity_remaining",
857
- };
858
- this.stockSummaryService.summary(params).subscribe({
859
- next: (response) => {
860
- this.stockSummary = response;
861
- },
862
- });
863
- }
864
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBasicInfoComponent, deps: [{ token: StockSummaryService }], target: i0.ɵɵFactoryTarget.Component });
865
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductBasicInfoComponent, selector: "app-product-basic-info", inputs: { product: "product" }, outputs: { saved: "saved", deleted: "deleted" }, ngImport: i0, template: "<mat-card *ngIf=\"product\" class=\"w-100\">\n <mat-card-content\n class=\"d-flex justify-content-between align-items-center mb-1 mb-2\"\n >\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> campaign </span>\n <strong class=\"mb-0 text-dark\">Product Information</strong>\n </div>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <app-product-form-button\n [product]=\"product\"\n (saved)=\"onProductSaved($event)\"\n ></app-product-form-button>\n <app-product-delete-button\n [product]=\"product\"\n (deleted)=\"deleted.emit()\"\n ></app-product-delete-button>\n </div>\n </mat-card-content>\n <mat-divider></mat-divider>\n <mat-card-content class=\"mt-3\">\n <h3 class=\"mb-1 font-weight-bold\">{{ product?.name }}</h3>\n <div class=\"d-flex flex-wrap gap-1\">\n <span\n class=\"badge badge-primary\"\n *ngFor=\"let category of product?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-3 d-flex justify-content-between align-items-start\"\n >\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">SKU</small>\n <p class=\"mb-0\">{{ product?.sku }}</p>\n </div>\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Measure</small>\n <p class=\"mb-0\">{{ product?.measure?.title }}</p>\n </div>\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Reorder Point</small>\n <p class=\"mb-0\">{{ product?.reorder_point }}</p>\n </div>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-3 d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Description</small>\n <p class=\"mb-0\">{{ product?.description }}</p>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-5 d-flex justify-content-between align-items-start\"\n >\n <div\n *ngIf=\"stockSummary\"\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Stock Receipts</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> arrow_downward </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_receipts_quantity_sum }}\n </p>\n </div>\n <small *ngIf=\"product?.last_stock_receipt\" class=\"text-secondary\">\n Last Added On {{ product?.last_stock_receipt?.date | date }}\n </small>\n </div>\n <div\n *ngIf=\"stockSummary\"\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Stock Issuances</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> ungroup </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_issuances_quantity_sum }}\n </p>\n </div>\n <small *ngIf=\"product?.last_stock_issuance\" class=\"text-secondary\">\n Last Added On {{ product?.last_stock_issuance?.date | date }}\n </small>\n </div>\n </mat-card-content>\n\n <mat-card-content\n *ngIf=\"stockSummary\"\n class=\"mt-3 d-flex justify-content-center align-items-center\"\n >\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">On Hand</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> inventory_2 </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_quantity_remaining }}\n </p>\n </div>\n </div>\n </mat-card-content>\n</mat-card>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i3$2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i6$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: ProductFormButtonComponent, selector: "app-product-form-button", inputs: ["product"], outputs: ["saved"] }, { kind: "component", type: ProductDeleteButtonComponent, selector: "app-product-delete-button", inputs: ["product"], outputs: ["deleted"] }, { kind: "pipe", type: i4.DatePipe, name: "date" }], preserveWhitespaces: true });
866
- }
867
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBasicInfoComponent, decorators: [{
868
- type: Component,
869
- args: [{ selector: "app-product-basic-info", template: "<mat-card *ngIf=\"product\" class=\"w-100\">\n <mat-card-content\n class=\"d-flex justify-content-between align-items-center mb-1 mb-2\"\n >\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> campaign </span>\n <strong class=\"mb-0 text-dark\">Product Information</strong>\n </div>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <app-product-form-button\n [product]=\"product\"\n (saved)=\"onProductSaved($event)\"\n ></app-product-form-button>\n <app-product-delete-button\n [product]=\"product\"\n (deleted)=\"deleted.emit()\"\n ></app-product-delete-button>\n </div>\n </mat-card-content>\n <mat-divider></mat-divider>\n <mat-card-content class=\"mt-3\">\n <h3 class=\"mb-1 font-weight-bold\">{{ product?.name }}</h3>\n <div class=\"d-flex flex-wrap gap-1\">\n <span\n class=\"badge badge-primary\"\n *ngFor=\"let category of product?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-3 d-flex justify-content-between align-items-start\"\n >\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">SKU</small>\n <p class=\"mb-0\">{{ product?.sku }}</p>\n </div>\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Measure</small>\n <p class=\"mb-0\">{{ product?.measure?.title }}</p>\n </div>\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Reorder Point</small>\n <p class=\"mb-0\">{{ product?.reorder_point }}</p>\n </div>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-3 d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Description</small>\n <p class=\"mb-0\">{{ product?.description }}</p>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-5 d-flex justify-content-between align-items-start\"\n >\n <div\n *ngIf=\"stockSummary\"\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Stock Receipts</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> arrow_downward </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_receipts_quantity_sum }}\n </p>\n </div>\n <small *ngIf=\"product?.last_stock_receipt\" class=\"text-secondary\">\n Last Added On {{ product?.last_stock_receipt?.date | date }}\n </small>\n </div>\n <div\n *ngIf=\"stockSummary\"\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Stock Issuances</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> ungroup </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_issuances_quantity_sum }}\n </p>\n </div>\n <small *ngIf=\"product?.last_stock_issuance\" class=\"text-secondary\">\n Last Added On {{ product?.last_stock_issuance?.date | date }}\n </small>\n </div>\n </mat-card-content>\n\n <mat-card-content\n *ngIf=\"stockSummary\"\n class=\"mt-3 d-flex justify-content-center align-items-center\"\n >\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">On Hand</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> inventory_2 </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_quantity_remaining }}\n </p>\n </div>\n </div>\n </mat-card-content>\n</mat-card>\n" }]
870
- }], ctorParameters: () => [{ type: StockSummaryService }], propDecorators: { product: [{
871
- type: Input
872
- }], saved: [{
873
- type: Output
874
- }], deleted: [{
875
- type: Output
876
- }] } });
877
-
878
- class ProductViewPageComponent {
879
- productService;
880
- activatedRoute;
881
- location;
882
- product;
883
- id;
884
- isLoading;
885
- constructor(productService, activatedRoute, location) {
886
- this.productService = productService;
887
- this.activatedRoute = activatedRoute;
888
- this.location = location;
889
- this.id = this.activatedRoute.snapshot.params?.["id"];
890
- }
891
- ngOnInit() {
892
- if (this.id) {
893
- this.getProduct(this.id);
894
- }
895
- }
896
- /**
897
- * Get the product details.
898
- *
899
- * @param productId
900
- */
901
- getProduct(productId) {
902
- this.isLoading = true;
903
- const params = {
904
- with: "type,measure,incomeAccount,expenseAccount,categories,lastStockReceipt,lastStockIssuance,taxes.tax.type",
905
- };
906
- this.productService.show(productId, params).subscribe({
907
- next: (result) => {
908
- this.isLoading = false;
909
- this.product = result?.item;
910
- },
911
- error: () => (this.isLoading = false),
912
- });
913
- }
914
- /**
915
- * Handle the on product update event.
916
- *
917
- * @param product
918
- */
919
- onProductUpdated(product) {
920
- this.getProduct(this.id);
921
- }
922
- /**
923
- * Handle on product delete event.
924
- */
925
- onProductDeleted() {
926
- this.location.back();
927
- }
928
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductViewPageComponent, deps: [{ token: ProductService }, { token: i2$1.ActivatedRoute }, { token: i4.Location }], target: i0.ɵɵFactoryTarget.Component });
929
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductViewPageComponent, selector: "app-product-view-page", ngImport: i0, template: "<mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n\n<div\n *ngIf=\"product\"\n class=\"d-flex justify-content-start align-items-start gap-3\"\n>\n <div style=\"width: calc(25% - 1rem)\" class=\"d-flex flex-column gap-3\">\n <app-product-basic-info\n [product]=\"product\"\n #productBasicInfoComponent\n (deleted)=\"onProductDeleted()\"\n (saved)=\"onProductUpdated($event)\"\n ></app-product-basic-info>\n\n <app-product-tax-list [product]=\"product\"></app-product-tax-list>\n </div>\n <div style=\"width: calc(75%)\" class=\"d-flex flex-column gap-3\">\n <app-stock-receipts-list-page\n [product]=\"product\"\n (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"\n ></app-stock-receipts-list-page>\n\n <app-stock-issuances-list\n [product]=\"product\"\n (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"\n ></app-stock-issuances-list>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: StockReceiptsListPageComponent, selector: "app-stock-receipts-list-page", inputs: ["product"], outputs: ["listUpdated"] }, { kind: "component", type: StockIssuancesListComponent, selector: "app-stock-issuances-list", inputs: ["product", "issuableType", "issuableId", "label"], outputs: ["listUpdated"] }, { kind: "component", type: ProductTaxListComponent, selector: "app-product-tax-list", inputs: ["product"] }, { kind: "component", type: i7$2.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: ProductBasicInfoComponent, selector: "app-product-basic-info", inputs: ["product"], outputs: ["saved", "deleted"] }], preserveWhitespaces: true });
930
- }
931
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductViewPageComponent, decorators: [{
932
- type: Component,
933
- args: [{ selector: "app-product-view-page", template: "<mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n\n<div\n *ngIf=\"product\"\n class=\"d-flex justify-content-start align-items-start gap-3\"\n>\n <div style=\"width: calc(25% - 1rem)\" class=\"d-flex flex-column gap-3\">\n <app-product-basic-info\n [product]=\"product\"\n #productBasicInfoComponent\n (deleted)=\"onProductDeleted()\"\n (saved)=\"onProductUpdated($event)\"\n ></app-product-basic-info>\n\n <app-product-tax-list [product]=\"product\"></app-product-tax-list>\n </div>\n <div style=\"width: calc(75%)\" class=\"d-flex flex-column gap-3\">\n <app-stock-receipts-list-page\n [product]=\"product\"\n (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"\n ></app-stock-receipts-list-page>\n\n <app-stock-issuances-list\n [product]=\"product\"\n (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"\n ></app-stock-issuances-list>\n </div>\n</div>\n" }]
934
- }], ctorParameters: () => [{ type: ProductService }, { type: i2$1.ActivatedRoute }, { type: i4.Location }] });
935
-
936
- class ProductImportPageComponent {
937
- importConfig = {
938
- apiUrl: "api/products-import",
939
- title: "Products",
940
- importType: "product",
941
- properties: [
942
- {
943
- label: "Name",
944
- value: "name",
945
- type: "text",
946
- },
947
- {
948
- label: "SKU",
949
- value: "sku",
950
- type: "text",
951
- },
952
- {
953
- label: "Initial Quantity",
954
- value: "initial_quantity",
955
- type: "number",
956
- },
957
- {
958
- label: "Initial Quantity Date",
959
- value: "initial_quantity_date",
960
- type: "date",
961
- },
962
- {
963
- label: "Reorder Point",
964
- value: "reorder_point",
965
- type: "number",
966
- },
967
- {
968
- label: "Measure",
969
- value: "measure",
970
- type: "text",
971
- },
972
- {
973
- label: "Categories",
974
- value: "categories",
975
- type: "text",
976
- },
977
- ],
978
- sampleFile: {
979
- name: "Products Import",
980
- path: "assets/product/product-import-sample.csv",
981
- },
982
- importHistory: {
983
- isEnabled: true,
984
- type: "product",
985
- apiUrl: "api/import-histories",
986
- },
987
- viewRouterLink: "/inventory/products/",
988
- };
989
- constructor() { }
990
- ngOnInit() { }
991
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductImportPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
992
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductImportPageComponent, selector: "app-product-import-page", ngImport: i0, template: "<app-import-csv [config]=\"importConfig\"></app-import-csv>\n", styles: [""], dependencies: [{ kind: "component", type: i1$1.ImportCsvComponent, selector: "app-import-csv", inputs: ["config"] }], preserveWhitespaces: true });
993
- }
994
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductImportPageComponent, decorators: [{
995
- type: Component,
996
- args: [{ selector: "app-product-import-page", template: "<app-import-csv [config]=\"importConfig\"></app-import-csv>\n" }]
997
- }], ctorParameters: () => [] });
998
-
999
- const routes = [
1000
- {
1001
- path: "",
1002
- component: ProductNavBarComponent,
1003
- children: [
1004
- {
1005
- path: "",
1006
- component: ProductListComponent,
1007
- canLoad: [AuthenticationGuard],
1008
- },
1009
- {
1010
- path: "import",
1011
- component: ProductImportPageComponent,
1012
- canLoad: [AuthenticationGuard],
1013
- },
1014
- {
1015
- path: "measure",
1016
- component: ProductMeasuresListComponent,
1017
- canLoad: [AuthenticationGuard],
1018
- },
1019
- {
1020
- path: ":id/view",
1021
- component: ProductViewPageComponent,
1022
- canLoad: [AuthenticationGuard],
1023
- },
1024
- {
1025
- path: "**",
1026
- redirectTo: "",
1027
- pathMatch: "full",
1028
- canLoad: [AuthenticationGuard],
1029
- },
1030
- ],
1031
- },
1032
- ];
1033
- class ProductRoutingModule {
1034
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1035
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, imports: [i2$1.RouterModule], exports: [RouterModule] });
1036
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, imports: [RouterModule.forChild(routes), RouterModule] });
1037
- }
1038
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, decorators: [{
1039
- type: NgModule,
1040
- args: [{
1041
- imports: [RouterModule.forChild(routes)],
1042
- exports: [RouterModule],
1043
- }]
1044
- }] });
1045
-
1046
- class ProductTaxModule {
1047
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1048
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, declarations: [ProductTaxListComponent,
1049
- ProductTaxFormButtonComponent,
1050
- ProductTaxDeleteButtonComponent], imports: [CommonModule,
1051
- MaterialModule,
1052
- ReactiveFormsModule,
1053
- SearchableSelectorModule], exports: [ProductTaxListComponent] });
1054
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, imports: [CommonModule,
1055
- MaterialModule,
1056
- ReactiveFormsModule,
1057
- SearchableSelectorModule] });
1058
- }
1059
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, decorators: [{
1060
- type: NgModule,
1061
- args: [{
1062
- declarations: [
1063
- ProductTaxListComponent,
1064
- ProductTaxFormButtonComponent,
1065
- ProductTaxDeleteButtonComponent,
1066
- ],
1067
- imports: [
1068
- CommonModule,
1069
- MaterialModule,
1070
- ReactiveFormsModule,
1071
- SearchableSelectorModule,
1072
- ],
1073
- exports: [ProductTaxListComponent],
1074
- }]
1075
- }] });
1076
-
1077
- class ProductModule {
1078
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1079
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, declarations: [ProductListComponent,
1080
- ProductFormComponent,
1081
- ProductNavBarComponent,
1082
- ProductMeasuresListComponent,
1083
- ProductMeasureFormComponent,
1084
- ProductViewPageComponent,
1085
- ProductFormButtonComponent,
1086
- ProductDeleteButtonComponent,
1087
- ProductBasicInfoComponent,
1088
- ProductImportPageComponent], imports: [CommonModule,
1089
- ProductRoutingModule,
1090
- SearchableSelectorModule,
1091
- TimelineFilterModule,
1092
- StockReceiptFormModule,
1093
- StockIssueFormModule,
1094
- ImportCsvModule,
1095
- StockReceiptsModule,
1096
- StockIssuancesListModule,
1097
- ProductTaxModule,
1098
- MaterialModule,
1099
- MatProgressBarModule,
1100
- InfiniteScrollModule,
1101
- FlexModule,
1102
- ReactiveFormsModule,
1103
- FormsModule,
1104
- ColumnSelectorModule], exports: [ProductFormComponent,
1105
- ProductBasicInfoComponent,
1106
- ProductFormButtonComponent] });
1107
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, imports: [CommonModule,
1108
- ProductRoutingModule,
1109
- SearchableSelectorModule,
1110
- TimelineFilterModule,
1111
- StockReceiptFormModule,
1112
- StockIssueFormModule,
1113
- ImportCsvModule,
1114
- StockReceiptsModule,
1115
- StockIssuancesListModule,
1116
- ProductTaxModule,
1117
- MaterialModule,
1118
- MatProgressBarModule,
1119
- InfiniteScrollModule,
1120
- FlexModule,
1121
- ReactiveFormsModule,
1122
- FormsModule,
1123
- ColumnSelectorModule] });
1124
- }
1125
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, decorators: [{
1126
- type: NgModule,
1127
- args: [{
1128
- declarations: [
1129
- ProductListComponent,
1130
- ProductFormComponent,
1131
- ProductNavBarComponent,
1132
- ProductMeasuresListComponent,
1133
- ProductMeasureFormComponent,
1134
- ProductViewPageComponent,
1135
- ProductFormButtonComponent,
1136
- ProductDeleteButtonComponent,
1137
- ProductBasicInfoComponent,
1138
- ProductImportPageComponent,
1139
- ],
1140
- imports: [
1141
- CommonModule,
1142
- ProductRoutingModule,
1143
- SearchableSelectorModule,
1144
- TimelineFilterModule,
1145
- StockReceiptFormModule,
1146
- StockIssueFormModule,
1147
- ImportCsvModule,
1148
- StockReceiptsModule,
1149
- StockIssuancesListModule,
1150
- ProductTaxModule,
1151
- MaterialModule,
1152
- MatProgressBarModule,
1153
- InfiniteScrollModule,
1154
- FlexModule,
1155
- ReactiveFormsModule,
1156
- FormsModule,
1157
- ColumnSelectorModule,
1158
- ],
1159
- exports: [
1160
- ProductFormComponent,
1161
- ProductBasicInfoComponent,
1162
- ProductFormButtonComponent,
1163
- ],
1164
- }]
1165
- }] });
1166
-
1167
- export { ProductModule };
1168
- //# sourceMappingURL=techlify-inventory-common-product.module-BV9Cy88x.mjs.map