@isaiahiroko/tilmart-ngx-apps-admin 0.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 (75) hide show
  1. package/README.md +9 -0
  2. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-articles.module-OeLRnPwN.mjs +154 -0
  3. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-articles.module-OeLRnPwN.mjs.map +1 -0
  4. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-audit.module-C9gvw8X2.mjs +84 -0
  5. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-audit.module-C9gvw8X2.mjs.map +1 -0
  6. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-baskets.module-_lHPl1dT.mjs +294 -0
  7. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-baskets.module-_lHPl1dT.mjs.map +1 -0
  8. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-catalog.module-Bvx2tVOi.mjs +224 -0
  9. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-catalog.module-Bvx2tVOi.mjs.map +1 -0
  10. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-claims.module-Ccsd8Yx3.mjs +106 -0
  11. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-claims.module-Ccsd8Yx3.mjs.map +1 -0
  12. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-compatibility-rules.module-xN-JUWwp.mjs +261 -0
  13. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-compatibility-rules.module-xN-JUWwp.mjs.map +1 -0
  14. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-content.module-DLdKAUqc.mjs +365 -0
  15. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-content.module-DLdKAUqc.mjs.map +1 -0
  16. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-coupons.module-CQNCSlsd.mjs +106 -0
  17. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-coupons.module-CQNCSlsd.mjs.map +1 -0
  18. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-customers.module-12XdV9zo.mjs +106 -0
  19. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-customers.module-12XdV9zo.mjs.map +1 -0
  20. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-data-quality.module-Bfgh3zE5.mjs +286 -0
  21. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-data-quality.module-Bfgh3zE5.mjs.map +1 -0
  22. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-data-requests.module-C6tPNlup.mjs +104 -0
  23. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-data-requests.module-C6tPNlup.mjs.map +1 -0
  24. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-disputes.module-DmUoAS0Z.mjs +73 -0
  25. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-disputes.module-DmUoAS0Z.mjs.map +1 -0
  26. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-homepage.module-BZ3UmxE3.mjs +404 -0
  27. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-homepage.module-BZ3UmxE3.mjs.map +1 -0
  28. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-inbox.module-BZDTa1L-.mjs +290 -0
  29. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-inbox.module-BZDTa1L-.mjs.map +1 -0
  30. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-macros.module-BO4bdER2.mjs +112 -0
  31. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-macros.module-BO4bdER2.mjs.map +1 -0
  32. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-moderation.module-CZOCrias.mjs +116 -0
  33. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-moderation.module-CZOCrias.mjs.map +1 -0
  34. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-navigation.module-DoKzzRgn.mjs +281 -0
  35. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-navigation.module-DoKzzRgn.mjs.map +1 -0
  36. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-order-board.module-DIOjhptn.mjs +115 -0
  37. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-order-board.module-DIOjhptn.mjs.map +1 -0
  38. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-orders.module-Ddw49QW0.mjs +185 -0
  39. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-orders.module-Ddw49QW0.mjs.map +1 -0
  40. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-payments.module-BhqAtTZs.mjs +106 -0
  41. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-payments.module-BhqAtTZs.mjs.map +1 -0
  42. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-payouts.module-CoiscPIZ.mjs +70 -0
  43. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-payouts.module-CoiscPIZ.mjs.map +1 -0
  44. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-procurement.module-qXW-g0pf.mjs +274 -0
  45. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-procurement.module-qXW-g0pf.mjs.map +1 -0
  46. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-promotions.module-DG9uTDqX.mjs +106 -0
  47. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-promotions.module-DG9uTDqX.mjs.map +1 -0
  48. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-queues.module-K-zYYVFy.mjs +84 -0
  49. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-queues.module-K-zYYVFy.mjs.map +1 -0
  50. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-redirects.module-Hm2dO_bC.mjs +106 -0
  51. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-redirects.module-Hm2dO_bC.mjs.map +1 -0
  52. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-referrals.module-QLNhuh7q.mjs +106 -0
  53. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-referrals.module-QLNhuh7q.mjs.map +1 -0
  54. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-reports.module-DBZov0We.mjs +104 -0
  55. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-reports.module-DBZov0We.mjs.map +1 -0
  56. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-returns.module-Bd2gdo6_.mjs +106 -0
  57. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-returns.module-Bd2gdo6_.mjs.map +1 -0
  58. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-rich-editor.module-DW9Gy_QQ.mjs +81 -0
  59. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-rich-editor.module-DW9Gy_QQ.mjs.map +1 -0
  60. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-routes.module-BkVY06ci.mjs +105 -0
  61. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-routes.module-BkVY06ci.mjs.map +1 -0
  62. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-settings.module-DKeZTldO.mjs +222 -0
  63. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-settings.module-DKeZTldO.mjs.map +1 -0
  64. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-shipments.module-XuaOKr8v.mjs +150 -0
  65. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-shipments.module-XuaOKr8v.mjs.map +1 -0
  66. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-stock.module-DYiAkF7E.mjs +107 -0
  67. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-stock.module-DYiAkF7E.mjs.map +1 -0
  68. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-trace.module-Pwr-82Rc.mjs +92 -0
  69. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-trace.module-Pwr-82Rc.mjs.map +1 -0
  70. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-users.module-Bx_7fI2g.mjs +111 -0
  71. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-users.module-Bx_7fI2g.mjs.map +1 -0
  72. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin.mjs +475 -0
  73. package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin.mjs.map +1 -0
  74. package/package.json +34 -0
  75. package/types/isaiahiroko-tilmart-ngx-apps-admin.d.ts +32 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-rich-editor.module-DW9Gy_QQ.mjs","sources":["../../../projects/admin/src/lib/pages/_shared/rich-editor/rich-editor.component.ts","../../../projects/admin/src/lib/pages/_shared/rich-editor/rich-editor.module.ts"],"sourcesContent":["import '@thescaffold/editor-core/define';\n\nimport {\n AfterViewInit,\n Component,\n ElementRef,\n EventEmitter,\n Input,\n NgZone,\n OnChanges,\n OnDestroy,\n Output,\n SimpleChanges,\n} from '@angular/core';\n\n// P6.10 — a thin Angular host for `@thescaffold/editor-core`'s\n// `<x-editor>` custom element. `@thescaffold/editor-angular` ships\n// source-only (no build) so it can't be consumed as a package; this is\n// the same handful of lines its `EditorComponent` uses. `content` is\n// HTML in, HTML out via `contentChange`.\n@Component({\n standalone: false,\n selector: 'x-rich-editor',\n template: '',\n styles: [':host { display: block; min-height: 160px; }'],\n})\nexport class RichEditorComponent implements AfterViewInit, OnChanges, OnDestroy {\n @Input() content = '';\n @Output() contentChange = new EventEmitter<string>();\n\n private el: (HTMLElement & { config?: Record<string, unknown> }) | null = null;\n private ctx: { setContent(c: string, format?: string): void } | null = null;\n\n constructor(\n private readonly host: ElementRef<HTMLElement>,\n private readonly zone: NgZone,\n ) {}\n\n ngAfterViewInit(): void {\n this.zone.runOutsideAngular(() => {\n const editor = document.createElement('x-editor') as HTMLElement & {\n config?: Record<string, unknown>;\n };\n editor.style.height = '100%';\n this.host.nativeElement.appendChild(editor);\n this.el = editor;\n\n editor.addEventListener('xe:ready', (event: Event) => {\n this.ctx = (event as CustomEvent<{ editor: any }>).detail?.editor ?? null;\n if (this.content) this.ctx?.setContent(this.content, 'html');\n });\n editor.addEventListener('xe:change', (event: Event) => {\n const next = (event as CustomEvent<{ content: string }>).detail?.content ?? '';\n this.zone.run(() => this.contentChange.emit(next));\n });\n\n editor.config = {\n mode: 'doc',\n content: this.content,\n editable: true,\n theme: 'auto',\n addons: [],\n };\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['content'] && !changes['content'].firstChange && this.ctx) {\n this.ctx.setContent(this.content ?? '', 'html');\n }\n }\n\n ngOnDestroy(): void {\n this.el?.remove();\n this.el = null;\n this.ctx = null;\n }\n}\n","import { NgModule } from '@angular/core';\nimport { RichEditorComponent } from './rich-editor.component';\n\n// P6.10 — shared WYSIWYG host, used by the CMS page builder (`content`)\n// and the Learn-hub article editor (`articles`).\n@NgModule({\n declarations: [RichEditorComponent],\n exports: [RichEditorComponent],\n})\nexport class RichEditorModule {}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Component, NgModule } from '@angular/core';
3
+ import * as i1$1 from '@angular/router';
4
+ import { RouterModule } from '@angular/router';
5
+ import { BaseDirective, using, titleCase, SharedModule } from '@thescaffold/ngx-core';
6
+ import * as i1 from '@thescaffold/ngx-ui';
7
+ import { ElementsModule, WebgetsModule } from '@thescaffold/ngx-ui';
8
+ import { BehaviorSubject, takeUntil, map } from 'rxjs';
9
+ import * as i2 from '@angular/common';
10
+
11
+ // Route/cluster/day board (docs/TRD.md §7): a simple list, not a
12
+ // routing-optimization engine — matches the PRD's density model (which
13
+ // street/day, not turn-by-turn routing).
14
+ class RoutesComponent extends BaseDirective {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.name = 'route';
18
+ this.pluralName = 'routes';
19
+ this.dataSource = this.apiService.on('apps/grocery/route');
20
+ this.columns = [
21
+ { key: 'name', value: 'Name' },
22
+ { key: 'dayOfWeek', value: 'Day', type: 'class', class: 'badge text-bg-light border' },
23
+ { key: 'vanCapacityKg', value: 'Van capacity (kg)' },
24
+ ];
25
+ this.page = 1;
26
+ this.perPage = 25;
27
+ this.list$ = new BehaviorSubject(null);
28
+ this.init = () => {
29
+ this.list();
30
+ };
31
+ }
32
+ list(page = this.page, perPage = this.perPage) {
33
+ this.dataSource
34
+ .getMany({ page, perPage })
35
+ .pipe(takeUntil(this.$), map((response) => this.toCollection(response)))
36
+ .subscribe(using((data) => this.list$.next(data)));
37
+ }
38
+ toCollection(response) {
39
+ return {
40
+ title: titleCase(this.pluralName),
41
+ columns: this.columns,
42
+ rows: response?.data,
43
+ hasHeaders: true,
44
+ hasTextFilter: true,
45
+ page: response?.meta?.current_page,
46
+ perPage: response?.meta?.per_page,
47
+ total: response?.meta?.total,
48
+ onPage: (page) => this.list(page),
49
+ };
50
+ }
51
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RoutesComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
52
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: RoutesComponent, isStandalone: false, selector: "x-routes", usesInheritance: true, ngImport: i0, template: `
53
+ <div class="x-page-head">
54
+ <div class="x-page-title">Routes</div>
55
+ <div class="x-page-subtitle">Street/estate clusters, by delivery day.</div>
56
+ </div>
57
+
58
+ @if (list$ | async; as list) {
59
+ <x-webget-collection [data]="list"></x-webget-collection>
60
+ } @else {
61
+ <x-element-loader></x-element-loader>
62
+ }
63
+ `, isInline: true, styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}\n"], dependencies: [{ kind: "component", type: i1.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }, { kind: "component", type: i1.CollectionComponent, selector: "x-webget-collection", inputs: ["data"], outputs: ["search", "filter", "refresh", "select", "page", "show"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] }); }
64
+ }
65
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RoutesComponent, decorators: [{
66
+ type: Component,
67
+ args: [{ standalone: false, selector: 'x-routes', template: `
68
+ <div class="x-page-head">
69
+ <div class="x-page-title">Routes</div>
70
+ <div class="x-page-subtitle">Street/estate clusters, by delivery day.</div>
71
+ </div>
72
+
73
+ @if (list$ | async; as list) {
74
+ <x-webget-collection [data]="list"></x-webget-collection>
75
+ } @else {
76
+ <x-element-loader></x-element-loader>
77
+ }
78
+ `, styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}\n"] }]
79
+ }] });
80
+
81
+ class GroceryRoutesModule {
82
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: GroceryRoutesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
83
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: GroceryRoutesModule, declarations: [RoutesComponent], imports: [SharedModule,
84
+ ElementsModule,
85
+ WebgetsModule, i1$1.RouterModule] }); }
86
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: GroceryRoutesModule, imports: [SharedModule,
87
+ ElementsModule,
88
+ WebgetsModule,
89
+ RouterModule.forChild([{ path: '', component: RoutesComponent }])] }); }
90
+ }
91
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: GroceryRoutesModule, decorators: [{
92
+ type: NgModule,
93
+ args: [{
94
+ declarations: [RoutesComponent],
95
+ imports: [
96
+ SharedModule,
97
+ ElementsModule,
98
+ WebgetsModule,
99
+ RouterModule.forChild([{ path: '', component: RoutesComponent }]),
100
+ ],
101
+ }]
102
+ }] });
103
+
104
+ export { GroceryRoutesModule };
105
+ //# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-routes.module-BkVY06ci.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-routes.module-BkVY06ci.mjs","sources":["../../../projects/admin/src/lib/pages/routes/routes.component.ts","../../../projects/admin/src/lib/pages/routes/routes.module.ts"],"sourcesContent":["import { Component } from '@angular/core';\nimport { BaseDirective, titleCase, using } from '@thescaffold/ngx-core';\nimport { BehaviorSubject, takeUntil, map } from 'rxjs';\n\n// Route/cluster/day board (docs/TRD.md §7): a simple list, not a\n// routing-optimization engine — matches the PRD's density model (which\n// street/day, not turn-by-turn routing).\n@Component({\n standalone: false,\n selector: 'x-routes',\n template: `\n <div class=\"x-page-head\">\n <div class=\"x-page-title\">Routes</div>\n <div class=\"x-page-subtitle\">Street/estate clusters, by delivery day.</div>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n `,\n styles: [\n `\n .x-page-head {\n margin-bottom: 20px;\n }\n .x-page-title {\n font-size: 24px;\n font-weight: 800;\n color: var(--color-text);\n }\n .x-page-subtitle {\n font-size: 13.5px;\n color: var(--color-text-muted);\n margin-top: 2px;\n }\n `,\n ],\n})\nexport class RoutesComponent extends BaseDirective {\n name = 'route';\n pluralName = 'routes';\n dataSource = this.apiService.on('apps/grocery/route');\n\n columns = [\n { key: 'name', value: 'Name' },\n { key: 'dayOfWeek', value: 'Day', type: 'class', class: 'badge text-bg-light border' },\n { key: 'vanCapacityKg', value: 'Van capacity (kg)' },\n ];\n\n page = 1;\n perPage = 25;\n\n list$ = new BehaviorSubject<any>(null);\n\n override init = () => {\n this.list();\n };\n\n list(page = this.page, perPage = this.perPage) {\n this.dataSource\n .getMany({ page, perPage })\n .pipe(\n takeUntil(this.$),\n map((response) => this.toCollection(response)),\n )\n .subscribe(using((data) => this.list$.next(data)));\n }\n\n private toCollection(response: any) {\n return {\n title: titleCase(this.pluralName),\n columns: this.columns,\n rows: response?.data,\n hasHeaders: true,\n hasTextFilter: true,\n page: response?.meta?.current_page,\n perPage: response?.meta?.per_page,\n total: response?.meta?.total,\n onPage: (page: number) => this.list(page),\n };\n }\n}\n","import { NgModule } from '@angular/core';\nimport { RouterModule } from '@angular/router';\nimport { SharedModule } from '@thescaffold/ngx-core';\nimport { ElementsModule, WebgetsModule } from '@thescaffold/ngx-ui';\nimport { RoutesComponent } from './routes.component';\n\n@NgModule({\n declarations: [RoutesComponent],\n imports: [\n SharedModule,\n ElementsModule,\n WebgetsModule,\n RouterModule.forChild([{ path: '', component: RoutesComponent }]),\n ],\n})\nexport class GroceryRoutesModule {}\n"],"names":["i1"],"mappings":"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"}
@@ -0,0 +1,222 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Component, NgModule } from '@angular/core';
3
+ import * as i1 from '@angular/router';
4
+ import { RouterModule } from '@angular/router';
5
+ import { BaseDirective, titleCase, using, SharedModule } from '@thescaffold/ngx-core';
6
+ import * as i1$1 from '@thescaffold/ngx-ui';
7
+ import { ElementsModule, WebgetsModule } from '@thescaffold/ngx-ui';
8
+ import { BehaviorSubject, takeUntil, map } from 'rxjs';
9
+ import * as i2 from '@angular/common';
10
+
11
+ // P7.1 — ops console section pass (PRD 6.2, Settings). A single page that
12
+ // stacks the R1 configuration resources — channels, shipping zones,
13
+ // shipping methods, return policies — each as a standard
14
+ // `x-webget-collection` list. Users & roles is its own section
15
+ // (/admin/users); the audit log lands in P7.6. ops CRUD is covered by
16
+ // `admin:*:apps:commerce:*`.
17
+ class SettingsComponent extends BaseDirective {
18
+ constructor() {
19
+ super(...arguments);
20
+ this.sections = [
21
+ {
22
+ key: 'channels',
23
+ title: 'Channels',
24
+ mount: 'apps/commerce/channel',
25
+ columns: [
26
+ { key: 'name', value: 'Name' },
27
+ { key: 'code', value: 'Code' },
28
+ { key: 'currency', value: 'Currency' },
29
+ ],
30
+ data$: new BehaviorSubject(null),
31
+ },
32
+ {
33
+ key: 'zones',
34
+ title: 'Shipping zones',
35
+ mount: 'apps/commerce/delivery-zone',
36
+ columns: [
37
+ { key: 'name', value: 'Name' },
38
+ { key: 'state', value: 'State' },
39
+ { key: 'lga', value: 'LGA' },
40
+ ],
41
+ data$: new BehaviorSubject(null),
42
+ },
43
+ {
44
+ key: 'methods',
45
+ title: 'Shipping methods',
46
+ mount: 'apps/commerce/delivery-method',
47
+ columns: [
48
+ { key: 'name', value: 'Name' },
49
+ { key: 'flatFee', value: 'Flat fee' },
50
+ { key: 'perKg', value: 'Per kg' },
51
+ {
52
+ key: 'enabled',
53
+ value: 'Enabled',
54
+ type: 'class',
55
+ class: 'badge text-bg-light border',
56
+ },
57
+ ],
58
+ data$: new BehaviorSubject(null),
59
+ },
60
+ {
61
+ key: 'returns',
62
+ title: 'Return policies',
63
+ mount: 'apps/commerce/return-policy',
64
+ columns: [
65
+ { key: 'windowDays', value: 'Window (days)' },
66
+ { key: 'restockingFeePct', value: 'Restock fee %' },
67
+ { key: 'whoPaysReturn', value: 'Who pays' },
68
+ {
69
+ key: 'enabled',
70
+ value: 'Enabled',
71
+ type: 'class',
72
+ class: 'badge text-bg-light border',
73
+ },
74
+ ],
75
+ data$: new BehaviorSubject(null),
76
+ },
77
+ ];
78
+ this.active = this.sections[0].key;
79
+ this.init = () => {
80
+ for (const section of this.sections)
81
+ this.load(section);
82
+ };
83
+ }
84
+ load(section) {
85
+ this.apiService
86
+ .on(section.mount)
87
+ .getMany({ page: 1, perPage: 100 })
88
+ .pipe(takeUntil(this.$), map((response) => ({
89
+ title: titleCase(section.title),
90
+ columns: section.columns,
91
+ rows: response?.data,
92
+ hasHeaders: true,
93
+ hasTextFilter: true,
94
+ total: response?.meta?.total,
95
+ })))
96
+ .subscribe(using((data) => section.data$.next(data)));
97
+ }
98
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SettingsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
99
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: SettingsComponent, isStandalone: false, selector: "x-settings", usesInheritance: true, ngImport: i0, template: `
100
+ <div class="x-page-head">
101
+ <div class="x-page-title">Settings</div>
102
+ <div class="x-page-subtitle">
103
+ Channels, shipping, tax and returns configuration.
104
+ </div>
105
+ </div>
106
+
107
+ <nav class="x-settings-tabs">
108
+ @for (s of sections; track s.key) {
109
+ <button
110
+ type="button"
111
+ class="x-settings-tab"
112
+ [class.is-active]="active === s.key"
113
+ (click)="active = s.key"
114
+ >
115
+ {{ s.title }}
116
+ </button>
117
+ }
118
+ </nav>
119
+
120
+ @for (s of sections; track s.key) {
121
+ @if (active === s.key) {
122
+ @if (s.data$ | async; as list) {
123
+ <x-webget-collection [data]="list"></x-webget-collection>
124
+ } @else {
125
+ <x-element-loader></x-element-loader>
126
+ }
127
+ }
128
+ }
129
+
130
+ <div class="x-settings-more">
131
+ <p>
132
+ <strong>Users &amp; roles</strong> —
133
+ <a routerLink="/admin/users">manage accounts</a>.
134
+ </p>
135
+ <p>
136
+ <strong>Notifications</strong> — transactional and marketing templates
137
+ are seeded per environment (NotificationTemplates); per-customer
138
+ preferences are on the customer record.
139
+ </p>
140
+ <p class="x-settings-audit">
141
+ <strong>Audit log</strong> — every privileged action is recorded
142
+ (ntx-apps-audit); <a routerLink="/admin/audit">open the viewer</a>.
143
+ </p>
144
+ </div>
145
+ `, isInline: true, styles: [".x-page-head{margin-bottom:16px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-settings-tabs{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:18px;border-bottom:1px solid var(--color-border)}.x-settings-tab{appearance:none;background:transparent;border:0;border-bottom:2px solid transparent;padding:8px 12px;font-size:13.5px;font-weight:600;color:var(--color-text-muted);cursor:pointer}.x-settings-tab.is-active{color:var(--color-text);border-bottom-color:var(--color-brand)}.x-settings-more{margin-top:28px;padding-top:18px;border-top:1px solid var(--color-border);font-size:13px;line-height:1.6;color:var(--color-text-muted)}.x-settings-more a{color:var(--color-brand)}.x-settings-audit{margin-bottom:0}\n"], dependencies: [{ kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i1$1.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }, { kind: "component", type: i1$1.CollectionComponent, selector: "x-webget-collection", inputs: ["data"], outputs: ["search", "filter", "refresh", "select", "page", "show"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] }); }
146
+ }
147
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SettingsComponent, decorators: [{
148
+ type: Component,
149
+ args: [{ standalone: false, selector: 'x-settings', template: `
150
+ <div class="x-page-head">
151
+ <div class="x-page-title">Settings</div>
152
+ <div class="x-page-subtitle">
153
+ Channels, shipping, tax and returns configuration.
154
+ </div>
155
+ </div>
156
+
157
+ <nav class="x-settings-tabs">
158
+ @for (s of sections; track s.key) {
159
+ <button
160
+ type="button"
161
+ class="x-settings-tab"
162
+ [class.is-active]="active === s.key"
163
+ (click)="active = s.key"
164
+ >
165
+ {{ s.title }}
166
+ </button>
167
+ }
168
+ </nav>
169
+
170
+ @for (s of sections; track s.key) {
171
+ @if (active === s.key) {
172
+ @if (s.data$ | async; as list) {
173
+ <x-webget-collection [data]="list"></x-webget-collection>
174
+ } @else {
175
+ <x-element-loader></x-element-loader>
176
+ }
177
+ }
178
+ }
179
+
180
+ <div class="x-settings-more">
181
+ <p>
182
+ <strong>Users &amp; roles</strong> —
183
+ <a routerLink="/admin/users">manage accounts</a>.
184
+ </p>
185
+ <p>
186
+ <strong>Notifications</strong> — transactional and marketing templates
187
+ are seeded per environment (NotificationTemplates); per-customer
188
+ preferences are on the customer record.
189
+ </p>
190
+ <p class="x-settings-audit">
191
+ <strong>Audit log</strong> — every privileged action is recorded
192
+ (ntx-apps-audit); <a routerLink="/admin/audit">open the viewer</a>.
193
+ </p>
194
+ </div>
195
+ `, styles: [".x-page-head{margin-bottom:16px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-settings-tabs{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:18px;border-bottom:1px solid var(--color-border)}.x-settings-tab{appearance:none;background:transparent;border:0;border-bottom:2px solid transparent;padding:8px 12px;font-size:13.5px;font-weight:600;color:var(--color-text-muted);cursor:pointer}.x-settings-tab.is-active{color:var(--color-text);border-bottom-color:var(--color-brand)}.x-settings-more{margin-top:28px;padding-top:18px;border-top:1px solid var(--color-border);font-size:13px;line-height:1.6;color:var(--color-text-muted)}.x-settings-more a{color:var(--color-brand)}.x-settings-audit{margin-bottom:0}\n"] }]
196
+ }] });
197
+
198
+ class SettingsModule {
199
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SettingsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
200
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: SettingsModule, declarations: [SettingsComponent], imports: [SharedModule,
201
+ ElementsModule,
202
+ WebgetsModule, i1.RouterModule] }); }
203
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SettingsModule, imports: [SharedModule,
204
+ ElementsModule,
205
+ WebgetsModule,
206
+ RouterModule.forChild([{ path: '', component: SettingsComponent }])] }); }
207
+ }
208
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SettingsModule, decorators: [{
209
+ type: NgModule,
210
+ args: [{
211
+ declarations: [SettingsComponent],
212
+ imports: [
213
+ SharedModule,
214
+ ElementsModule,
215
+ WebgetsModule,
216
+ RouterModule.forChild([{ path: '', component: SettingsComponent }]),
217
+ ],
218
+ }]
219
+ }] });
220
+
221
+ export { SettingsModule };
222
+ //# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-settings.module-DKeZTldO.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-settings.module-DKeZTldO.mjs","sources":["../../../projects/admin/src/lib/pages/settings/settings.component.ts","../../../projects/admin/src/lib/pages/settings/settings.module.ts"],"sourcesContent":["import { Component } from '@angular/core';\nimport { BaseDirective, titleCase, using } from '@thescaffold/ngx-core';\nimport { BehaviorSubject, map, takeUntil } from 'rxjs';\n\ninterface Section {\n key: string;\n title: string;\n mount: string;\n columns: { key: string; value: string; type?: string; class?: string }[];\n data$: BehaviorSubject<any>;\n}\n\n// P7.1 — ops console section pass (PRD 6.2, Settings). A single page that\n// stacks the R1 configuration resources — channels, shipping zones,\n// shipping methods, return policies — each as a standard\n// `x-webget-collection` list. Users & roles is its own section\n// (/admin/users); the audit log lands in P7.6. ops CRUD is covered by\n// `admin:*:apps:commerce:*`.\n@Component({\n standalone: false,\n selector: 'x-settings',\n template: `\n <div class=\"x-page-head\">\n <div class=\"x-page-title\">Settings</div>\n <div class=\"x-page-subtitle\">\n Channels, shipping, tax and returns configuration.\n </div>\n </div>\n\n <nav class=\"x-settings-tabs\">\n @for (s of sections; track s.key) {\n <button\n type=\"button\"\n class=\"x-settings-tab\"\n [class.is-active]=\"active === s.key\"\n (click)=\"active = s.key\"\n >\n {{ s.title }}\n </button>\n }\n </nav>\n\n @for (s of sections; track s.key) {\n @if (active === s.key) {\n @if (s.data$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n }\n }\n\n <div class=\"x-settings-more\">\n <p>\n <strong>Users &amp; roles</strong> —\n <a routerLink=\"/admin/users\">manage accounts</a>.\n </p>\n <p>\n <strong>Notifications</strong> — transactional and marketing templates\n are seeded per environment (NotificationTemplates); per-customer\n preferences are on the customer record.\n </p>\n <p class=\"x-settings-audit\">\n <strong>Audit log</strong> — every privileged action is recorded\n (ntx-apps-audit); <a routerLink=\"/admin/audit\">open the viewer</a>.\n </p>\n </div>\n `,\n styles: [\n `\n .x-page-head {\n margin-bottom: 16px;\n }\n .x-page-title {\n font-size: 24px;\n font-weight: 800;\n color: var(--color-text);\n }\n .x-page-subtitle {\n font-size: 13.5px;\n color: var(--color-text-muted);\n margin-top: 2px;\n }\n .x-settings-tabs {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-bottom: 18px;\n border-bottom: 1px solid var(--color-border);\n }\n .x-settings-tab {\n appearance: none;\n background: transparent;\n border: 0;\n border-bottom: 2px solid transparent;\n padding: 8px 12px;\n font-size: 13.5px;\n font-weight: 600;\n color: var(--color-text-muted);\n cursor: pointer;\n }\n .x-settings-tab.is-active {\n color: var(--color-text);\n border-bottom-color: var(--color-brand);\n }\n .x-settings-more {\n margin-top: 28px;\n padding-top: 18px;\n border-top: 1px solid var(--color-border);\n font-size: 13px;\n line-height: 1.6;\n color: var(--color-text-muted);\n }\n .x-settings-more a {\n color: var(--color-brand);\n }\n .x-settings-audit {\n margin-bottom: 0;\n }\n `,\n ],\n})\nexport class SettingsComponent extends BaseDirective {\n readonly sections: Section[] = [\n {\n key: 'channels',\n title: 'Channels',\n mount: 'apps/commerce/channel',\n columns: [\n { key: 'name', value: 'Name' },\n { key: 'code', value: 'Code' },\n { key: 'currency', value: 'Currency' },\n ],\n data$: new BehaviorSubject<any>(null),\n },\n {\n key: 'zones',\n title: 'Shipping zones',\n mount: 'apps/commerce/delivery-zone',\n columns: [\n { key: 'name', value: 'Name' },\n { key: 'state', value: 'State' },\n { key: 'lga', value: 'LGA' },\n ],\n data$: new BehaviorSubject<any>(null),\n },\n {\n key: 'methods',\n title: 'Shipping methods',\n mount: 'apps/commerce/delivery-method',\n columns: [\n { key: 'name', value: 'Name' },\n { key: 'flatFee', value: 'Flat fee' },\n { key: 'perKg', value: 'Per kg' },\n {\n key: 'enabled',\n value: 'Enabled',\n type: 'class',\n class: 'badge text-bg-light border',\n },\n ],\n data$: new BehaviorSubject<any>(null),\n },\n {\n key: 'returns',\n title: 'Return policies',\n mount: 'apps/commerce/return-policy',\n columns: [\n { key: 'windowDays', value: 'Window (days)' },\n { key: 'restockingFeePct', value: 'Restock fee %' },\n { key: 'whoPaysReturn', value: 'Who pays' },\n {\n key: 'enabled',\n value: 'Enabled',\n type: 'class',\n class: 'badge text-bg-light border',\n },\n ],\n data$: new BehaviorSubject<any>(null),\n },\n ];\n\n active = this.sections[0].key;\n\n override init = () => {\n for (const section of this.sections) this.load(section);\n };\n\n private load(section: Section): void {\n this.apiService\n .on(section.mount)\n .getMany({ page: 1, perPage: 100 })\n .pipe(\n takeUntil(this.$),\n map((response: any) => ({\n title: titleCase(section.title),\n columns: section.columns,\n rows: response?.data,\n hasHeaders: true,\n hasTextFilter: true,\n total: response?.meta?.total,\n })),\n )\n .subscribe(using((data) => section.data$.next(data)));\n }\n}\n","import { NgModule } from '@angular/core';\nimport { RouterModule } from '@angular/router';\nimport { SharedModule } from '@thescaffold/ngx-core';\nimport { ElementsModule, WebgetsModule } from '@thescaffold/ngx-ui';\nimport { SettingsComponent } from './settings.component';\n\n@NgModule({\n declarations: [SettingsComponent],\n imports: [\n SharedModule,\n ElementsModule,\n WebgetsModule,\n RouterModule.forChild([{ path: '', component: SettingsComponent }]),\n ],\n})\nexport class SettingsModule {}\n"],"names":["i2","i3"],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, TemplateRef, ViewChild, Component, NgModule } from '@angular/core';
3
+ import * as i1$2 from '@angular/router';
4
+ import { RouterModule } from '@angular/router';
5
+ import { BaseDirective, using, notify, titleCase, SharedModule } from '@thescaffold/ngx-core';
6
+ import * as i1$1 from '@thescaffold/ngx-ui';
7
+ import { FlyoutService, ElementsModule, WebgetsModule } from '@thescaffold/ngx-ui';
8
+ import { BehaviorSubject, takeUntil, map } from 'rxjs';
9
+ import * as i1 from '@angular/forms';
10
+ import * as i2 from '@angular/common';
11
+
12
+ const EXCEPTION_REASONS = [
13
+ 'recipient_unavailable',
14
+ 'address_not_found',
15
+ 'recipient_refused',
16
+ 'damaged_in_transit',
17
+ 'access_blocked',
18
+ 'weather',
19
+ 'vehicle_issue',
20
+ 'security',
21
+ 'other',
22
+ ];
23
+ // ORD-08 / ORD-12 — the fulfilment queue. List every shipment; drill in
24
+ // to dispatch, mark delivered, or record a delivery exception (each
25
+ // calls `FulfilmentWorkflow` via the shipment controller).
26
+ class ShipmentsComponent extends BaseDirective {
27
+ constructor() {
28
+ super(...arguments);
29
+ this.flyoutService = inject(FlyoutService);
30
+ this.shipmentSource = this.apiService.on('apps/commerce/shipment');
31
+ this.lineSource = this.apiService.on('apps/commerce/shipment-line');
32
+ this.exceptionSource = this.apiService.on('apps/commerce/delivery-exception');
33
+ this.reasons = EXCEPTION_REASONS;
34
+ this.columns = [
35
+ { key: 'status', value: 'Status', type: 'class', class: 'badge text-bg-light border' },
36
+ { key: 'orderId', value: 'Order' },
37
+ { key: 'carrier', value: 'Carrier' },
38
+ { key: 'trackingRef', value: 'Tracking' },
39
+ { key: 'createdAt', value: 'Created', type: 'date' },
40
+ ];
41
+ this.page = 1;
42
+ this.perPage = 25;
43
+ this.list$ = new BehaviorSubject(null);
44
+ this.detail = null;
45
+ this.exceptionReason = 'recipient_unavailable';
46
+ this.exceptionNote = '';
47
+ this.init = () => {
48
+ this.list();
49
+ };
50
+ }
51
+ list(page = this.page, perPage = this.perPage) {
52
+ this.shipmentSource
53
+ .getMany({ page, perPage })
54
+ .pipe(takeUntil(this.$), map((response) => this.toCollection(response)))
55
+ .subscribe(using((data) => this.list$.next(data)));
56
+ }
57
+ view(item) {
58
+ this.detail = null;
59
+ this.exceptionReason = 'recipient_unavailable';
60
+ this.exceptionNote = '';
61
+ this.flyoutService.open(this.detailFlyout);
62
+ this.lineSource
63
+ .getMany({ shipmentId: item.id, page: 1, perPage: 100 })
64
+ .pipe(takeUntil(this.$))
65
+ .subscribe(using(({ data: lines }) => {
66
+ this.detail = { ...item, lines: lines ?? [], exceptions: [] };
67
+ this.exceptionSource
68
+ .getMany({ shipmentId: item.id, page: 1, perPage: 50 })
69
+ .pipe(takeUntil(this.$))
70
+ .subscribe(using(({ data }) => {
71
+ if (this.detail)
72
+ this.detail.exceptions = data ?? [];
73
+ }));
74
+ }));
75
+ }
76
+ act(path, body, okMsg) {
77
+ this.apiService
78
+ .post(`apps/commerce/shipment/${this.detail.id}/${path}`, body)
79
+ .pipe(takeUntil(this.$))
80
+ .subscribe(using((res) => {
81
+ if (res?.status === 'error') {
82
+ notify(res.message || 'That action failed.', undefined, 'error');
83
+ return;
84
+ }
85
+ notify(okMsg, undefined, 'success');
86
+ this.flyoutService.dismiss();
87
+ this.list();
88
+ }));
89
+ }
90
+ dispatch() {
91
+ this.act('dispatch', {}, 'Shipment dispatched.');
92
+ }
93
+ deliver() {
94
+ this.act('deliver', {}, 'Shipment marked delivered.');
95
+ }
96
+ recordException() {
97
+ this.act('exception', { reasonCode: this.exceptionReason, notes: this.exceptionNote || undefined }, 'Delivery exception recorded.');
98
+ }
99
+ toCollection(response) {
100
+ return {
101
+ title: titleCase('shipments'),
102
+ columns: this.columns,
103
+ rows: response?.data ?? [],
104
+ hasHeaders: true,
105
+ hasTextFilter: true,
106
+ page: response?.meta?.current_page,
107
+ perPage: response?.meta?.per_page,
108
+ total: response?.meta?.total,
109
+ onPage: (page) => this.list(page),
110
+ links: {
111
+ secondary: [{ title: 'View', fn: (_link, item) => this.view(item) }],
112
+ },
113
+ };
114
+ }
115
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ShipmentsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
116
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ShipmentsComponent, isStandalone: false, selector: "x-shipments", viewQueries: [{ propertyName: "detailFlyout", first: true, predicate: ["detailFlyout"], descendants: true, read: TemplateRef, static: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">Shipments</div>\n <div class=\"x-page-subtitle\">Dispatch, deliver, and record delivery exceptions (ORD-08).</div>\n</div>\n\n@if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n} @else {\n <x-element-loader></x-element-loader>\n}\n\n<ng-template #detailFlyout>\n <x-webget-flyout [data]=\"{ title: 'Shipment' }\">\n <div class=\"p-4 d-flex flex-column gap-3\">\n @if (detail) {\n <div>\n <span class=\"badge text-bg-light border\">{{ detail.status }}</span>\n @if (detail.trackingRef) {\n <div class=\"small text-secondary mt-1\">{{ detail.carrier }} \u00B7 {{ detail.trackingRef }}</div>\n }\n @if (detail.dispatchedAt) {\n <div class=\"small text-secondary\">Dispatched {{ detail.dispatchedAt | date: 'MMM d, h:mm a' }}</div>\n }\n @if (detail.deliveredAt) {\n <div class=\"small text-secondary\">Delivered {{ detail.deliveredAt | date: 'MMM d, h:mm a' }}</div>\n }\n </div>\n\n <div class=\"d-flex flex-wrap gap-2\">\n @if (detail.status === 'preparing' || detail.status === 'ready_for_dispatch') {\n <button type=\"button\" class=\"btn btn-sm btn-outline-dark\" (click)=\"dispatch()\">Dispatch</button>\n }\n @if (detail.status === 'dispatched' || detail.status === 'out_for_delivery' || detail.status === 'failed_delivery') {\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\" (click)=\"deliver()\">Mark delivered</button>\n }\n </div>\n\n <table class=\"table table-sm\">\n <thead><tr><th>Order line</th><th>Qty</th><th>Serials</th></tr></thead>\n <tbody>\n @for (line of detail.lines; track line.id) {\n <tr>\n <td class=\"font-monospace small\">{{ line.orderLineId }}</td>\n <td>{{ line.quantity }}</td>\n <td class=\"small\">{{ line.serialNumbers?.join(', ') || '\u2014' }}</td>\n </tr>\n } @empty {\n <tr><td colspan=\"3\" class=\"text-secondary\">No lines.</td></tr>\n }\n </tbody>\n </table>\n\n <div>\n <div class=\"fw-bold small mb-1\">Delivery exceptions</div>\n @for (ex of detail.exceptions; track ex.id) {\n <div class=\"small text-secondary\">\n Attempt {{ ex.attemptNumber }} \u00B7 {{ ex.reasonCode }}\n @if (ex.notes) { \u2014 {{ ex.notes }} }\n </div>\n } @empty {\n <div class=\"small text-secondary\">None.</div>\n }\n </div>\n\n <hr class=\"my-1\" />\n <div class=\"d-flex flex-column gap-2\">\n <div class=\"fw-bold small\">Record an exception</div>\n <select class=\"form-select form-select-sm\" [(ngModel)]=\"exceptionReason\">\n @for (reason of reasons; track reason) {\n <option [value]=\"reason\">{{ reason }}</option>\n }\n </select>\n <input class=\"form-control form-control-sm\" placeholder=\"Note (optional)\" [(ngModel)]=\"exceptionNote\" />\n <button type=\"button\" class=\"btn btn-sm btn-outline-warning align-self-start\" (click)=\"recordException()\">\n Record exception\n </button>\n </div>\n } @else {\n <x-element-loader></x-element-loader>\n }\n </div>\n </x-webget-flyout>\n</ng-template>\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}\n"], dependencies: [{ kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i1$1.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }, { kind: "component", type: i1$1.CollectionComponent, selector: "x-webget-collection", inputs: ["data"], outputs: ["search", "filter", "refresh", "select", "page", "show"] }, { kind: "component", type: i1$1.FlyoutComponent, selector: "x-webget-flyout", inputs: ["data"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.DatePipe, name: "date" }] }); }
117
+ }
118
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ShipmentsComponent, decorators: [{
119
+ type: Component,
120
+ args: [{ standalone: false, selector: 'x-shipments', template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">Shipments</div>\n <div class=\"x-page-subtitle\">Dispatch, deliver, and record delivery exceptions (ORD-08).</div>\n</div>\n\n@if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n} @else {\n <x-element-loader></x-element-loader>\n}\n\n<ng-template #detailFlyout>\n <x-webget-flyout [data]=\"{ title: 'Shipment' }\">\n <div class=\"p-4 d-flex flex-column gap-3\">\n @if (detail) {\n <div>\n <span class=\"badge text-bg-light border\">{{ detail.status }}</span>\n @if (detail.trackingRef) {\n <div class=\"small text-secondary mt-1\">{{ detail.carrier }} \u00B7 {{ detail.trackingRef }}</div>\n }\n @if (detail.dispatchedAt) {\n <div class=\"small text-secondary\">Dispatched {{ detail.dispatchedAt | date: 'MMM d, h:mm a' }}</div>\n }\n @if (detail.deliveredAt) {\n <div class=\"small text-secondary\">Delivered {{ detail.deliveredAt | date: 'MMM d, h:mm a' }}</div>\n }\n </div>\n\n <div class=\"d-flex flex-wrap gap-2\">\n @if (detail.status === 'preparing' || detail.status === 'ready_for_dispatch') {\n <button type=\"button\" class=\"btn btn-sm btn-outline-dark\" (click)=\"dispatch()\">Dispatch</button>\n }\n @if (detail.status === 'dispatched' || detail.status === 'out_for_delivery' || detail.status === 'failed_delivery') {\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\" (click)=\"deliver()\">Mark delivered</button>\n }\n </div>\n\n <table class=\"table table-sm\">\n <thead><tr><th>Order line</th><th>Qty</th><th>Serials</th></tr></thead>\n <tbody>\n @for (line of detail.lines; track line.id) {\n <tr>\n <td class=\"font-monospace small\">{{ line.orderLineId }}</td>\n <td>{{ line.quantity }}</td>\n <td class=\"small\">{{ line.serialNumbers?.join(', ') || '\u2014' }}</td>\n </tr>\n } @empty {\n <tr><td colspan=\"3\" class=\"text-secondary\">No lines.</td></tr>\n }\n </tbody>\n </table>\n\n <div>\n <div class=\"fw-bold small mb-1\">Delivery exceptions</div>\n @for (ex of detail.exceptions; track ex.id) {\n <div class=\"small text-secondary\">\n Attempt {{ ex.attemptNumber }} \u00B7 {{ ex.reasonCode }}\n @if (ex.notes) { \u2014 {{ ex.notes }} }\n </div>\n } @empty {\n <div class=\"small text-secondary\">None.</div>\n }\n </div>\n\n <hr class=\"my-1\" />\n <div class=\"d-flex flex-column gap-2\">\n <div class=\"fw-bold small\">Record an exception</div>\n <select class=\"form-select form-select-sm\" [(ngModel)]=\"exceptionReason\">\n @for (reason of reasons; track reason) {\n <option [value]=\"reason\">{{ reason }}</option>\n }\n </select>\n <input class=\"form-control form-control-sm\" placeholder=\"Note (optional)\" [(ngModel)]=\"exceptionNote\" />\n <button type=\"button\" class=\"btn btn-sm btn-outline-warning align-self-start\" (click)=\"recordException()\">\n Record exception\n </button>\n </div>\n } @else {\n <x-element-loader></x-element-loader>\n }\n </div>\n </x-webget-flyout>\n</ng-template>\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}\n"] }]
121
+ }], propDecorators: { detailFlyout: [{
122
+ type: ViewChild,
123
+ args: ['detailFlyout', { read: TemplateRef, static: true }]
124
+ }] } });
125
+
126
+ class ShipmentsModule {
127
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ShipmentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
128
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: ShipmentsModule, declarations: [ShipmentsComponent], imports: [SharedModule,
129
+ ElementsModule,
130
+ WebgetsModule, i1$2.RouterModule] }); }
131
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ShipmentsModule, imports: [SharedModule,
132
+ ElementsModule,
133
+ WebgetsModule,
134
+ RouterModule.forChild([{ path: '', component: ShipmentsComponent }])] }); }
135
+ }
136
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ShipmentsModule, decorators: [{
137
+ type: NgModule,
138
+ args: [{
139
+ declarations: [ShipmentsComponent],
140
+ imports: [
141
+ SharedModule,
142
+ ElementsModule,
143
+ WebgetsModule,
144
+ RouterModule.forChild([{ path: '', component: ShipmentsComponent }]),
145
+ ],
146
+ }]
147
+ }] });
148
+
149
+ export { ShipmentsModule };
150
+ //# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-shipments.module-XuaOKr8v.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-shipments.module-XuaOKr8v.mjs","sources":["../../../projects/admin/src/lib/pages/shipments/shipments.component.ts","../../../projects/admin/src/lib/pages/shipments/shipments.component.html","../../../projects/admin/src/lib/pages/shipments/shipments.module.ts"],"sourcesContent":["import { Component, TemplateRef, ViewChild, inject } from '@angular/core';\nimport { BaseDirective, notify, titleCase, using } from '@thescaffold/ngx-core';\nimport { FlyoutService } from '@thescaffold/ngx-ui';\nimport { BehaviorSubject, map, takeUntil } from 'rxjs';\n\nconst EXCEPTION_REASONS = [\n 'recipient_unavailable',\n 'address_not_found',\n 'recipient_refused',\n 'damaged_in_transit',\n 'access_blocked',\n 'weather',\n 'vehicle_issue',\n 'security',\n 'other',\n];\n\n// ORD-08 / ORD-12 — the fulfilment queue. List every shipment; drill in\n// to dispatch, mark delivered, or record a delivery exception (each\n// calls `FulfilmentWorkflow` via the shipment controller).\n@Component({\n standalone: false,\n selector: 'x-shipments',\n templateUrl: './shipments.component.html',\n styleUrl: './shipments.component.scss',\n})\nexport class ShipmentsComponent extends BaseDirective {\n private readonly flyoutService = inject(FlyoutService);\n\n private readonly shipmentSource = this.apiService.on('apps/commerce/shipment');\n private readonly lineSource = this.apiService.on('apps/commerce/shipment-line');\n private readonly exceptionSource = this.apiService.on('apps/commerce/delivery-exception');\n\n readonly reasons = EXCEPTION_REASONS;\n\n columns = [\n { key: 'status', value: 'Status', type: 'class', class: 'badge text-bg-light border' },\n { key: 'orderId', value: 'Order' },\n { key: 'carrier', value: 'Carrier' },\n { key: 'trackingRef', value: 'Tracking' },\n { key: 'createdAt', value: 'Created', type: 'date' },\n ];\n\n page = 1;\n perPage = 25;\n\n list$ = new BehaviorSubject<any>(null);\n detail: any = null;\n exceptionReason = 'recipient_unavailable';\n exceptionNote = '';\n\n @ViewChild('detailFlyout', { read: TemplateRef, static: true })\n detailFlyout!: TemplateRef<any>;\n\n override init = () => {\n this.list();\n };\n\n list(page = this.page, perPage = this.perPage) {\n this.shipmentSource\n .getMany({ page, perPage } as any)\n .pipe(\n takeUntil(this.$),\n map((response) => this.toCollection(response)),\n )\n .subscribe(using((data) => this.list$.next(data)));\n }\n\n view(item: any) {\n this.detail = null;\n this.exceptionReason = 'recipient_unavailable';\n this.exceptionNote = '';\n this.flyoutService.open(this.detailFlyout);\n\n this.lineSource\n .getMany({ shipmentId: item.id, page: 1, perPage: 100 } as any)\n .pipe(takeUntil(this.$))\n .subscribe(\n using(({ data: lines }: { data: any[] }) => {\n this.detail = { ...item, lines: lines ?? [], exceptions: [] };\n this.exceptionSource\n .getMany({ shipmentId: item.id, page: 1, perPage: 50 } as any)\n .pipe(takeUntil(this.$))\n .subscribe(using(({ data }: { data: any[] }) => {\n if (this.detail) this.detail.exceptions = data ?? [];\n }));\n }),\n );\n }\n\n private act(path: string, body: Record<string, unknown>, okMsg: string) {\n this.apiService\n .post(`apps/commerce/shipment/${this.detail.id}/${path}`, body)\n .pipe(takeUntil(this.$))\n .subscribe(\n using((res: any) => {\n if (res?.status === 'error') {\n notify(res.message || 'That action failed.', undefined, 'error');\n return;\n }\n notify(okMsg, undefined, 'success');\n this.flyoutService.dismiss();\n this.list();\n }),\n );\n }\n\n dispatch() {\n this.act('dispatch', {}, 'Shipment dispatched.');\n }\n\n deliver() {\n this.act('deliver', {}, 'Shipment marked delivered.');\n }\n\n recordException() {\n this.act(\n 'exception',\n { reasonCode: this.exceptionReason, notes: this.exceptionNote || undefined },\n 'Delivery exception recorded.',\n );\n }\n\n private toCollection(response: any) {\n return {\n title: titleCase('shipments'),\n columns: this.columns,\n rows: response?.data ?? [],\n hasHeaders: true,\n hasTextFilter: true,\n page: response?.meta?.current_page,\n perPage: response?.meta?.per_page,\n total: response?.meta?.total,\n onPage: (page: number) => this.list(page),\n links: {\n secondary: [{ title: 'View', fn: (_link: any, item: any) => this.view(item) }],\n },\n };\n }\n}\n","<div class=\"x-page-head\">\n <div class=\"x-page-title\">Shipments</div>\n <div class=\"x-page-subtitle\">Dispatch, deliver, and record delivery exceptions (ORD-08).</div>\n</div>\n\n@if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n} @else {\n <x-element-loader></x-element-loader>\n}\n\n<ng-template #detailFlyout>\n <x-webget-flyout [data]=\"{ title: 'Shipment' }\">\n <div class=\"p-4 d-flex flex-column gap-3\">\n @if (detail) {\n <div>\n <span class=\"badge text-bg-light border\">{{ detail.status }}</span>\n @if (detail.trackingRef) {\n <div class=\"small text-secondary mt-1\">{{ detail.carrier }} · {{ detail.trackingRef }}</div>\n }\n @if (detail.dispatchedAt) {\n <div class=\"small text-secondary\">Dispatched {{ detail.dispatchedAt | date: 'MMM d, h:mm a' }}</div>\n }\n @if (detail.deliveredAt) {\n <div class=\"small text-secondary\">Delivered {{ detail.deliveredAt | date: 'MMM d, h:mm a' }}</div>\n }\n </div>\n\n <div class=\"d-flex flex-wrap gap-2\">\n @if (detail.status === 'preparing' || detail.status === 'ready_for_dispatch') {\n <button type=\"button\" class=\"btn btn-sm btn-outline-dark\" (click)=\"dispatch()\">Dispatch</button>\n }\n @if (detail.status === 'dispatched' || detail.status === 'out_for_delivery' || detail.status === 'failed_delivery') {\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\" (click)=\"deliver()\">Mark delivered</button>\n }\n </div>\n\n <table class=\"table table-sm\">\n <thead><tr><th>Order line</th><th>Qty</th><th>Serials</th></tr></thead>\n <tbody>\n @for (line of detail.lines; track line.id) {\n <tr>\n <td class=\"font-monospace small\">{{ line.orderLineId }}</td>\n <td>{{ line.quantity }}</td>\n <td class=\"small\">{{ line.serialNumbers?.join(', ') || '—' }}</td>\n </tr>\n } @empty {\n <tr><td colspan=\"3\" class=\"text-secondary\">No lines.</td></tr>\n }\n </tbody>\n </table>\n\n <div>\n <div class=\"fw-bold small mb-1\">Delivery exceptions</div>\n @for (ex of detail.exceptions; track ex.id) {\n <div class=\"small text-secondary\">\n Attempt {{ ex.attemptNumber }} · {{ ex.reasonCode }}\n @if (ex.notes) { — {{ ex.notes }} }\n </div>\n } @empty {\n <div class=\"small text-secondary\">None.</div>\n }\n </div>\n\n <hr class=\"my-1\" />\n <div class=\"d-flex flex-column gap-2\">\n <div class=\"fw-bold small\">Record an exception</div>\n <select class=\"form-select form-select-sm\" [(ngModel)]=\"exceptionReason\">\n @for (reason of reasons; track reason) {\n <option [value]=\"reason\">{{ reason }}</option>\n }\n </select>\n <input class=\"form-control form-control-sm\" placeholder=\"Note (optional)\" [(ngModel)]=\"exceptionNote\" />\n <button type=\"button\" class=\"btn btn-sm btn-outline-warning align-self-start\" (click)=\"recordException()\">\n Record exception\n </button>\n </div>\n } @else {\n <x-element-loader></x-element-loader>\n }\n </div>\n </x-webget-flyout>\n</ng-template>\n","import { NgModule } from '@angular/core';\nimport { RouterModule } from '@angular/router';\nimport { SharedModule } from '@thescaffold/ngx-core';\nimport { ElementsModule, WebgetsModule } from '@thescaffold/ngx-ui';\nimport { ShipmentsComponent } from './shipments.component';\n\n@NgModule({\n declarations: [ShipmentsComponent],\n imports: [\n SharedModule,\n ElementsModule,\n WebgetsModule,\n RouterModule.forChild([{ path: '', component: ShipmentsComponent }]),\n ],\n})\nexport class ShipmentsModule {}\n"],"names":["i2","i3","i1"],"mappings":"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"}