@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,106 @@
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
+ // P7.1 — ops console section pass (PRD 6.2, TRD 9.2). A standard list
12
+ // view on `x-webget-collection` over `apps/commerce/redirect`, matching the
13
+ // established admin pattern (users, routes, inbox). ops CRUD is covered
14
+ // by `admin:*:apps:commerce:*`.
15
+ class RedirectsComponent extends BaseDirective {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.pluralName = 'redirects';
19
+ this.dataSource = this.apiService.on('apps/commerce/redirect');
20
+ this.columns = [
21
+ { key: 'fromPath', value: 'From' },
22
+ { key: 'toPath', value: 'To' },
23
+ { key: 'statusCode', value: 'Code' },
24
+ { key: 'hitCount', value: 'Hits' },
25
+ ];
26
+ this.page = 1;
27
+ this.perPage = 25;
28
+ this.list$ = new BehaviorSubject(null);
29
+ this.init = () => {
30
+ this.list();
31
+ };
32
+ }
33
+ list(page = this.page, perPage = this.perPage) {
34
+ this.dataSource
35
+ .getMany({ page, perPage })
36
+ .pipe(takeUntil(this.$), map((response) => this.toCollection(response)))
37
+ .subscribe(using((data) => this.list$.next(data)));
38
+ }
39
+ toCollection(response) {
40
+ return {
41
+ title: titleCase(this.pluralName),
42
+ columns: this.columns,
43
+ rows: response?.data,
44
+ hasHeaders: true,
45
+ hasTextFilter: true,
46
+ page: response?.meta?.current_page,
47
+ perPage: response?.meta?.per_page,
48
+ total: response?.meta?.total,
49
+ onPage: (page) => this.list(page),
50
+ };
51
+ }
52
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RedirectsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
53
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: RedirectsComponent, isStandalone: false, selector: "x-redirects", usesInheritance: true, ngImport: i0, template: `
54
+ <div class="x-page-head">
55
+ <div class="x-page-title">Redirects</div>
56
+ <div class="x-page-subtitle">Stored 301/302 path redirects — auto-minted on slug changes (CMS-06).</div>
57
+ </div>
58
+
59
+ @if (list$ | async; as list) {
60
+ <x-webget-collection [data]="list"></x-webget-collection>
61
+ } @else {
62
+ <x-element-loader></x-element-loader>
63
+ }
64
+ `, 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" }] }); }
65
+ }
66
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RedirectsComponent, decorators: [{
67
+ type: Component,
68
+ args: [{ standalone: false, selector: 'x-redirects', template: `
69
+ <div class="x-page-head">
70
+ <div class="x-page-title">Redirects</div>
71
+ <div class="x-page-subtitle">Stored 301/302 path redirects — auto-minted on slug changes (CMS-06).</div>
72
+ </div>
73
+
74
+ @if (list$ | async; as list) {
75
+ <x-webget-collection [data]="list"></x-webget-collection>
76
+ } @else {
77
+ <x-element-loader></x-element-loader>
78
+ }
79
+ `, 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"] }]
80
+ }] });
81
+
82
+ class RedirectsModule {
83
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RedirectsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
84
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: RedirectsModule, declarations: [RedirectsComponent], imports: [SharedModule,
85
+ ElementsModule,
86
+ WebgetsModule, i1$1.RouterModule] }); }
87
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RedirectsModule, imports: [SharedModule,
88
+ ElementsModule,
89
+ WebgetsModule,
90
+ RouterModule.forChild([{ path: '', component: RedirectsComponent }])] }); }
91
+ }
92
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RedirectsModule, decorators: [{
93
+ type: NgModule,
94
+ args: [{
95
+ declarations: [RedirectsComponent],
96
+ imports: [
97
+ SharedModule,
98
+ ElementsModule,
99
+ WebgetsModule,
100
+ RouterModule.forChild([{ path: '', component: RedirectsComponent }]),
101
+ ],
102
+ }]
103
+ }] });
104
+
105
+ export { RedirectsModule };
106
+ //# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-redirects.module-Hm2dO_bC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-redirects.module-Hm2dO_bC.mjs","sources":["../../../projects/admin/src/lib/pages/redirects/redirects.component.ts","../../../projects/admin/src/lib/pages/redirects/redirects.module.ts"],"sourcesContent":["import { Component } from '@angular/core';\nimport { BaseDirective, titleCase, using } from '@thescaffold/ngx-core';\nimport { BehaviorSubject, map, takeUntil } from 'rxjs';\n\n// P7.1 — ops console section pass (PRD 6.2, TRD 9.2). A standard list\n// view on `x-webget-collection` over `apps/commerce/redirect`, matching the\n// established admin pattern (users, routes, inbox). ops CRUD is covered\n// by `admin:*:apps:commerce:*`.\n@Component({\n standalone: false,\n selector: 'x-redirects',\n template: `\n <div class=\"x-page-head\">\n <div class=\"x-page-title\">Redirects</div>\n <div class=\"x-page-subtitle\">Stored 301/302 path redirects — auto-minted on slug changes (CMS-06).</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 RedirectsComponent extends BaseDirective {\n pluralName = 'redirects';\n dataSource = this.apiService.on('apps/commerce/redirect');\n\n columns = [\n { key: 'fromPath', value: 'From' },\n { key: 'toPath', value: 'To' },\n { key: 'statusCode', value: 'Code' },\n { key: 'hitCount', value: 'Hits' },\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 { RedirectsComponent } from './redirects.component';\n\n@NgModule({\n declarations: [RedirectsComponent],\n imports: [\n SharedModule,\n ElementsModule,\n WebgetsModule,\n RouterModule.forChild([{ path: '', component: RedirectsComponent }]),\n ],\n})\nexport class RedirectsModule {}\n"],"names":["i1"],"mappings":"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"}
@@ -0,0 +1,106 @@
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
+ // Referral/reward view (docs/TRD.md §7).
12
+ class ReferralsComponent extends BaseDirective {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.name = 'referral';
16
+ this.pluralName = 'referrals';
17
+ // P5.14 — the commerce Referral (ACC-11); the Salama grocery route is gone.
18
+ this.dataSource = this.apiService.on('apps/commerce/referral');
19
+ this.columns = [
20
+ { key: 'code', value: 'Code' },
21
+ { key: 'referredContactPhone', value: 'Referred contact' },
22
+ { key: 'status', value: 'Status', type: 'class', class: 'badge text-bg-light border' },
23
+ { key: 'convertedAt', value: 'Converted', type: 'date' },
24
+ { key: 'createdAt', value: 'Referred on', type: 'date' },
25
+ ];
26
+ this.page = 1;
27
+ this.perPage = 25;
28
+ this.list$ = new BehaviorSubject(null);
29
+ this.init = () => {
30
+ this.list();
31
+ };
32
+ }
33
+ list(page = this.page, perPage = this.perPage) {
34
+ this.dataSource
35
+ .getMany({ page, perPage })
36
+ .pipe(takeUntil(this.$), map((response) => this.toCollection(response)))
37
+ .subscribe(using((data) => this.list$.next(data)));
38
+ }
39
+ toCollection(response) {
40
+ return {
41
+ title: titleCase(this.pluralName),
42
+ columns: this.columns,
43
+ rows: response?.data,
44
+ hasHeaders: true,
45
+ hasTextFilter: true,
46
+ page: response?.meta?.current_page,
47
+ perPage: response?.meta?.per_page,
48
+ total: response?.meta?.total,
49
+ onPage: (page) => this.list(page),
50
+ };
51
+ }
52
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReferralsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
53
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ReferralsComponent, isStandalone: false, selector: "x-referrals", usesInheritance: true, ngImport: i0, template: `
54
+ <div class="x-page-head">
55
+ <div class="x-page-title">Referrals</div>
56
+ <div class="x-page-subtitle">Who referred whom, and reward status.</div>
57
+ </div>
58
+
59
+ @if (list$ | async; as list) {
60
+ <x-webget-collection [data]="list"></x-webget-collection>
61
+ } @else {
62
+ <x-element-loader></x-element-loader>
63
+ }
64
+ `, 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" }] }); }
65
+ }
66
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReferralsComponent, decorators: [{
67
+ type: Component,
68
+ args: [{ standalone: false, selector: 'x-referrals', template: `
69
+ <div class="x-page-head">
70
+ <div class="x-page-title">Referrals</div>
71
+ <div class="x-page-subtitle">Who referred whom, and reward status.</div>
72
+ </div>
73
+
74
+ @if (list$ | async; as list) {
75
+ <x-webget-collection [data]="list"></x-webget-collection>
76
+ } @else {
77
+ <x-element-loader></x-element-loader>
78
+ }
79
+ `, 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"] }]
80
+ }] });
81
+
82
+ class ReferralsModule {
83
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReferralsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
84
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: ReferralsModule, declarations: [ReferralsComponent], imports: [SharedModule,
85
+ ElementsModule,
86
+ WebgetsModule, i1$1.RouterModule] }); }
87
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReferralsModule, imports: [SharedModule,
88
+ ElementsModule,
89
+ WebgetsModule,
90
+ RouterModule.forChild([{ path: '', component: ReferralsComponent }])] }); }
91
+ }
92
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReferralsModule, decorators: [{
93
+ type: NgModule,
94
+ args: [{
95
+ declarations: [ReferralsComponent],
96
+ imports: [
97
+ SharedModule,
98
+ ElementsModule,
99
+ WebgetsModule,
100
+ RouterModule.forChild([{ path: '', component: ReferralsComponent }]),
101
+ ],
102
+ }]
103
+ }] });
104
+
105
+ export { ReferralsModule };
106
+ //# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-referrals.module-QLNhuh7q.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-referrals.module-QLNhuh7q.mjs","sources":["../../../projects/admin/src/lib/pages/referrals/referrals.component.ts","../../../projects/admin/src/lib/pages/referrals/referrals.module.ts"],"sourcesContent":["import { Component } from '@angular/core';\nimport { BaseDirective, titleCase, using } from '@thescaffold/ngx-core';\nimport { BehaviorSubject, takeUntil, map } from 'rxjs';\n\n// Referral/reward view (docs/TRD.md §7).\n@Component({\n standalone: false,\n selector: 'x-referrals',\n template: `\n <div class=\"x-page-head\">\n <div class=\"x-page-title\">Referrals</div>\n <div class=\"x-page-subtitle\">Who referred whom, and reward status.</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 ReferralsComponent extends BaseDirective {\n name = 'referral';\n pluralName = 'referrals';\n // P5.14 — the commerce Referral (ACC-11); the Salama grocery route is gone.\n dataSource = this.apiService.on('apps/commerce/referral');\n\n columns = [\n { key: 'code', value: 'Code' },\n { key: 'referredContactPhone', value: 'Referred contact' },\n { key: 'status', value: 'Status', type: 'class', class: 'badge text-bg-light border' },\n { key: 'convertedAt', value: 'Converted', type: 'date' },\n { key: 'createdAt', value: 'Referred on', type: 'date' },\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 { ReferralsComponent } from './referrals.component';\n\n@NgModule({\n declarations: [ReferralsComponent],\n imports: [\n SharedModule,\n ElementsModule,\n WebgetsModule,\n RouterModule.forChild([{ path: '', component: ReferralsComponent }]),\n ],\n})\nexport class ReferralsModule {}\n"],"names":["i1"],"mappings":"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"}
@@ -0,0 +1,104 @@
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, SharedModule } from '@thescaffold/ngx-core';
6
+ import * as i1 from '@thescaffold/ngx-ui';
7
+ import { ElementsModule } from '@thescaffold/ngx-ui';
8
+ import { takeUntil } from 'rxjs';
9
+
10
+ const TABS = [
11
+ { key: 'commerce', label: 'Commerce', ana: 'ANA-01', hasRange: true },
12
+ { key: 'funnel', label: 'Funnel', ana: 'ANA-02', hasRange: true },
13
+ { key: 'search', label: 'Search', ana: 'ANA-03', hasRange: true },
14
+ { key: 'tools', label: 'Tools', ana: 'ANA-04', hasRange: true },
15
+ { key: 'inventory', label: 'Inventory', ana: 'ANA-05', hasRange: false },
16
+ { key: 'operations', label: 'Operations', ana: 'ANA-09', hasRange: true },
17
+ ];
18
+ // P7.4 — the ANA-* analytics dashboard. Each tab reads one
19
+ // `apps/admin/analytics/*` read model (raw SQL over the commerce tables,
20
+ // libs/admin). ANA-11 web analytics / campaign attribution lives in
21
+ // Countly, not here.
22
+ class ReportsComponent extends BaseDirective {
23
+ constructor() {
24
+ super(...arguments);
25
+ this.source = this.apiService.on('apps/admin/analytics');
26
+ this.tabs = TABS;
27
+ this.active = 'commerce';
28
+ this.days = 30;
29
+ this.loading = true;
30
+ this.data = null;
31
+ this.init = () => {
32
+ this.load();
33
+ };
34
+ }
35
+ get activeTab() {
36
+ return TABS.find((t) => t.key === this.active);
37
+ }
38
+ select(key) {
39
+ if (this.active === key)
40
+ return;
41
+ this.active = key;
42
+ this.load();
43
+ }
44
+ setDays(days) {
45
+ this.days = days;
46
+ this.load();
47
+ }
48
+ load() {
49
+ this.loading = true;
50
+ this.data = null;
51
+ const path = this.activeTab.hasRange
52
+ ? `${this.active}?days=${this.days}`
53
+ : this.active;
54
+ this.source
55
+ .getOne(path)
56
+ .pipe(takeUntil(this.$))
57
+ .subscribe(using((res) => {
58
+ this.data = res?.data ?? null;
59
+ this.loading = false;
60
+ }));
61
+ }
62
+ money(n) {
63
+ const v = Number(n) || 0;
64
+ return `₦${v.toLocaleString('en-NG', { maximumFractionDigits: 0 })}`;
65
+ }
66
+ num(n) {
67
+ return (Number(n) || 0).toLocaleString('en-NG');
68
+ }
69
+ keys(obj) {
70
+ return obj ? Object.keys(obj) : [];
71
+ }
72
+ humanize(key) {
73
+ return key.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
74
+ }
75
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReportsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
76
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ReportsComponent, isStandalone: false, selector: "x-reports", usesInheritance: true, ngImport: i0, template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">Reports</div>\n <div class=\"x-page-subtitle\">\n Analytics read models over the commerce tables. Web traffic, sessions and\n campaign attribution are in Countly (ANA-11).\n </div>\n</div>\n\n<nav class=\"x-rp-tabs\">\n @for (t of tabs; track t.key) {\n <button\n type=\"button\"\n class=\"x-rp-tab\"\n [class.is-active]=\"active === t.key\"\n (click)=\"select(t.key)\"\n >\n {{ t.label }} <span class=\"x-rp-ana\">{{ t.ana }}</span>\n </button>\n }\n</nav>\n\n@if (activeTab.hasRange) {\n <div class=\"x-rp-range\">\n @for (d of [7, 30, 90]; track d) {\n <button\n type=\"button\"\n class=\"x-rp-range-btn\"\n [class.is-active]=\"days === d\"\n (click)=\"setDays(d)\"\n >\n {{ d }}d\n </button>\n }\n </div>\n}\n\n@if (loading) {\n <x-element-loader></x-element-loader>\n} @else if (!data) {\n <p class=\"x-rp-empty\">No data.</p>\n} @else {\n <!-- summary blocks: any object of scalars renders as cards -->\n @for (block of ['summary', 'fulfilment', 'returns', 'support', 'toolRevenue', 'compatibilityChecks']; track block) {\n @if (data[block] && keys(data[block]).length) {\n <div class=\"x-rp-section-label\">{{ humanize(block) }}</div>\n <div class=\"x-rp-cards\">\n @for (k of keys(data[block]); track k) {\n <div class=\"x-rp-card\">\n <div class=\"x-rp-card-label\">{{ humanize(k) }}</div>\n <div class=\"x-rp-card-value\">\n @if (k.includes('revenue') || k.includes('value') || k.includes('aov') || k.includes('discount')) {\n {{ money(data[block][k]) }}\n } @else {\n {{ num(data[block][k]) }}\n }\n </div>\n </div>\n }\n </div>\n }\n }\n\n <!-- funnel -->\n @if (data.stages) {\n <div class=\"x-rp-section-label\">Checkout funnel</div>\n @if (data.note) { <p class=\"x-rp-note\">{{ data.note }}</p> }\n <table class=\"x-rp-table\">\n <thead><tr><th>Stage</th><th>Count</th><th>% of top</th><th>Drop from previous</th></tr></thead>\n <tbody>\n @for (s of data.stages; track s.key) {\n <tr>\n <td>{{ s.label }}</td>\n <td>{{ num(s.value) }}</td>\n <td>{{ s.conversionFromTop }}%</td>\n <td [class.x-rp-drop]=\"s.dropFromPrev > 0\">{{ s.dropFromPrev }}%</td>\n </tr>\n }\n </tbody>\n </table>\n }\n\n <!-- generic array tables -->\n @for (block of ['byDay', 'byChannel', 'byPaymentMethod', 'byCategory', 'byType', 'byMethod', 'topQueries', 'zeroResult', 'blockFrequency', 'worstStockouts']; track block) {\n @if (data[block] && data[block].length) {\n <div class=\"x-rp-section-label\">{{ humanize(block) }}</div>\n <div class=\"x-rp-table-wrap\">\n <table class=\"x-rp-table\">\n <thead>\n <tr>\n @for (col of keys(data[block][0]); track col) {\n <th>{{ humanize(col) }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of data[block]; track $index) {\n <tr>\n @for (col of keys(row); track col) {\n <td>\n @if (col.includes('revenue') || col.includes('amount')) {\n {{ money(row[col]) }}\n } @else {\n {{ row[col] }}\n }\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n}\n\n<style>\n .x-page-head { margin-bottom: 16px; }\n .x-page-title { font-size: 24px; font-weight: 800; color: var(--color-text); }\n .x-page-subtitle { font-size: 13.5px; color: var(--color-text-muted); margin-top: 2px; max-width: 640px; }\n\n .x-rp-tabs { display: flex; flex-wrap: wrap; gap: 4px; border-bottom: 1px solid var(--color-border); margin-bottom: 14px; }\n .x-rp-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; }\n .x-rp-tab.is-active { color: var(--color-text); border-bottom-color: var(--color-brand); }\n .x-rp-ana { font-size: 10px; opacity: 0.6; font-weight: 500; }\n\n .x-rp-range { display: flex; gap: 6px; margin-bottom: 18px; }\n .x-rp-range-btn { appearance: none; background: transparent; border: 1px solid var(--color-border); border-radius: 999px; padding: 3px 12px; font-size: 12px; font-weight: 600; color: var(--color-text-muted); cursor: pointer; }\n .x-rp-range-btn.is-active { background: var(--color-brand); color: #fff; border-color: var(--color-brand); }\n\n .x-rp-section-label { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; color: var(--color-text-muted); margin: 24px 0 10px; }\n .x-rp-note { font-size: 12.5px; color: var(--color-text-muted); margin: -4px 0 10px; }\n .x-rp-empty { font-size: 13px; color: var(--color-text-muted); }\n\n .x-rp-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 10px; }\n .x-rp-card { border: 1px solid var(--color-border); border-radius: 10px; padding: 10px 14px; }\n .x-rp-card-label { font-size: 11.5px; color: var(--color-text-muted); }\n .x-rp-card-value { font-size: 19px; font-weight: 800; color: var(--color-text); margin-top: 3px; }\n\n .x-rp-table-wrap { overflow-x: auto; }\n .x-rp-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n .x-rp-table th, .x-rp-table td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--color-border); white-space: nowrap; }\n .x-rp-table th { color: var(--color-text-muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; }\n .x-rp-drop { color: var(--color-danger, #c0392b); font-weight: 600; }\n</style>\n", 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;max-width:640px}.x-rp-tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--color-border);margin-bottom:14px}.x-rp-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-rp-tab.is-active{color:var(--color-text);border-bottom-color:var(--color-brand)}.x-rp-ana{font-size:10px;opacity:.6;font-weight:500}.x-rp-range{display:flex;gap:6px;margin-bottom:18px}.x-rp-range-btn{appearance:none;background:transparent;border:1px solid var(--color-border);border-radius:999px;padding:3px 12px;font-size:12px;font-weight:600;color:var(--color-text-muted);cursor:pointer}.x-rp-range-btn.is-active{background:var(--color-brand);color:#fff;border-color:var(--color-brand)}.x-rp-section-label{font-size:11.5px;text-transform:uppercase;letter-spacing:.04em;font-weight:700;color:var(--color-text-muted);margin:24px 0 10px}.x-rp-note{font-size:12.5px;color:var(--color-text-muted);margin:-4px 0 10px}.x-rp-empty{font-size:13px;color:var(--color-text-muted)}.x-rp-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:10px}.x-rp-card{border:1px solid var(--color-border);border-radius:10px;padding:10px 14px}.x-rp-card-label{font-size:11.5px;color:var(--color-text-muted)}.x-rp-card-value{font-size:19px;font-weight:800;color:var(--color-text);margin-top:3px}.x-rp-table-wrap{overflow-x:auto}.x-rp-table{width:100%;border-collapse:collapse;font-size:13px}.x-rp-table th,.x-rp-table td{text-align:left;padding:7px 10px;border-bottom:1px solid var(--color-border);white-space:nowrap}.x-rp-table th{color:var(--color-text-muted);font-size:11px;text-transform:uppercase;letter-spacing:.03em}.x-rp-drop{color:var(--color-danger, #c0392b);font-weight:600}\n"], dependencies: [{ kind: "component", type: i1.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }] }); }
77
+ }
78
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReportsComponent, decorators: [{
79
+ type: Component,
80
+ args: [{ standalone: false, selector: 'x-reports', template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">Reports</div>\n <div class=\"x-page-subtitle\">\n Analytics read models over the commerce tables. Web traffic, sessions and\n campaign attribution are in Countly (ANA-11).\n </div>\n</div>\n\n<nav class=\"x-rp-tabs\">\n @for (t of tabs; track t.key) {\n <button\n type=\"button\"\n class=\"x-rp-tab\"\n [class.is-active]=\"active === t.key\"\n (click)=\"select(t.key)\"\n >\n {{ t.label }} <span class=\"x-rp-ana\">{{ t.ana }}</span>\n </button>\n }\n</nav>\n\n@if (activeTab.hasRange) {\n <div class=\"x-rp-range\">\n @for (d of [7, 30, 90]; track d) {\n <button\n type=\"button\"\n class=\"x-rp-range-btn\"\n [class.is-active]=\"days === d\"\n (click)=\"setDays(d)\"\n >\n {{ d }}d\n </button>\n }\n </div>\n}\n\n@if (loading) {\n <x-element-loader></x-element-loader>\n} @else if (!data) {\n <p class=\"x-rp-empty\">No data.</p>\n} @else {\n <!-- summary blocks: any object of scalars renders as cards -->\n @for (block of ['summary', 'fulfilment', 'returns', 'support', 'toolRevenue', 'compatibilityChecks']; track block) {\n @if (data[block] && keys(data[block]).length) {\n <div class=\"x-rp-section-label\">{{ humanize(block) }}</div>\n <div class=\"x-rp-cards\">\n @for (k of keys(data[block]); track k) {\n <div class=\"x-rp-card\">\n <div class=\"x-rp-card-label\">{{ humanize(k) }}</div>\n <div class=\"x-rp-card-value\">\n @if (k.includes('revenue') || k.includes('value') || k.includes('aov') || k.includes('discount')) {\n {{ money(data[block][k]) }}\n } @else {\n {{ num(data[block][k]) }}\n }\n </div>\n </div>\n }\n </div>\n }\n }\n\n <!-- funnel -->\n @if (data.stages) {\n <div class=\"x-rp-section-label\">Checkout funnel</div>\n @if (data.note) { <p class=\"x-rp-note\">{{ data.note }}</p> }\n <table class=\"x-rp-table\">\n <thead><tr><th>Stage</th><th>Count</th><th>% of top</th><th>Drop from previous</th></tr></thead>\n <tbody>\n @for (s of data.stages; track s.key) {\n <tr>\n <td>{{ s.label }}</td>\n <td>{{ num(s.value) }}</td>\n <td>{{ s.conversionFromTop }}%</td>\n <td [class.x-rp-drop]=\"s.dropFromPrev > 0\">{{ s.dropFromPrev }}%</td>\n </tr>\n }\n </tbody>\n </table>\n }\n\n <!-- generic array tables -->\n @for (block of ['byDay', 'byChannel', 'byPaymentMethod', 'byCategory', 'byType', 'byMethod', 'topQueries', 'zeroResult', 'blockFrequency', 'worstStockouts']; track block) {\n @if (data[block] && data[block].length) {\n <div class=\"x-rp-section-label\">{{ humanize(block) }}</div>\n <div class=\"x-rp-table-wrap\">\n <table class=\"x-rp-table\">\n <thead>\n <tr>\n @for (col of keys(data[block][0]); track col) {\n <th>{{ humanize(col) }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of data[block]; track $index) {\n <tr>\n @for (col of keys(row); track col) {\n <td>\n @if (col.includes('revenue') || col.includes('amount')) {\n {{ money(row[col]) }}\n } @else {\n {{ row[col] }}\n }\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n}\n\n<style>\n .x-page-head { margin-bottom: 16px; }\n .x-page-title { font-size: 24px; font-weight: 800; color: var(--color-text); }\n .x-page-subtitle { font-size: 13.5px; color: var(--color-text-muted); margin-top: 2px; max-width: 640px; }\n\n .x-rp-tabs { display: flex; flex-wrap: wrap; gap: 4px; border-bottom: 1px solid var(--color-border); margin-bottom: 14px; }\n .x-rp-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; }\n .x-rp-tab.is-active { color: var(--color-text); border-bottom-color: var(--color-brand); }\n .x-rp-ana { font-size: 10px; opacity: 0.6; font-weight: 500; }\n\n .x-rp-range { display: flex; gap: 6px; margin-bottom: 18px; }\n .x-rp-range-btn { appearance: none; background: transparent; border: 1px solid var(--color-border); border-radius: 999px; padding: 3px 12px; font-size: 12px; font-weight: 600; color: var(--color-text-muted); cursor: pointer; }\n .x-rp-range-btn.is-active { background: var(--color-brand); color: #fff; border-color: var(--color-brand); }\n\n .x-rp-section-label { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; color: var(--color-text-muted); margin: 24px 0 10px; }\n .x-rp-note { font-size: 12.5px; color: var(--color-text-muted); margin: -4px 0 10px; }\n .x-rp-empty { font-size: 13px; color: var(--color-text-muted); }\n\n .x-rp-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 10px; }\n .x-rp-card { border: 1px solid var(--color-border); border-radius: 10px; padding: 10px 14px; }\n .x-rp-card-label { font-size: 11.5px; color: var(--color-text-muted); }\n .x-rp-card-value { font-size: 19px; font-weight: 800; color: var(--color-text); margin-top: 3px; }\n\n .x-rp-table-wrap { overflow-x: auto; }\n .x-rp-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n .x-rp-table th, .x-rp-table td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--color-border); white-space: nowrap; }\n .x-rp-table th { color: var(--color-text-muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; }\n .x-rp-drop { color: var(--color-danger, #c0392b); font-weight: 600; }\n</style>\n" }]
81
+ }] });
82
+
83
+ class ReportsModule {
84
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReportsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
85
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: ReportsModule, declarations: [ReportsComponent], imports: [SharedModule,
86
+ ElementsModule, i1$1.RouterModule] }); }
87
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReportsModule, imports: [SharedModule,
88
+ ElementsModule,
89
+ RouterModule.forChild([{ path: '', component: ReportsComponent }])] }); }
90
+ }
91
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReportsModule, decorators: [{
92
+ type: NgModule,
93
+ args: [{
94
+ declarations: [ReportsComponent],
95
+ imports: [
96
+ SharedModule,
97
+ ElementsModule,
98
+ RouterModule.forChild([{ path: '', component: ReportsComponent }]),
99
+ ],
100
+ }]
101
+ }] });
102
+
103
+ export { ReportsModule };
104
+ //# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-reports.module-DBZov0We.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-reports.module-DBZov0We.mjs","sources":["../../../projects/admin/src/lib/pages/reports/reports.component.ts","../../../projects/admin/src/lib/pages/reports/reports.component.html","../../../projects/admin/src/lib/pages/reports/reports.module.ts"],"sourcesContent":["import { Component } from '@angular/core';\nimport { BaseDirective, using } from '@thescaffold/ngx-core';\nimport { takeUntil } from 'rxjs';\n\ntype TabKey =\n | 'commerce'\n | 'funnel'\n | 'search'\n | 'tools'\n | 'inventory'\n | 'operations';\n\ninterface Tab {\n key: TabKey;\n label: string;\n ana: string;\n hasRange: boolean;\n}\n\nconst TABS: Tab[] = [\n { key: 'commerce', label: 'Commerce', ana: 'ANA-01', hasRange: true },\n { key: 'funnel', label: 'Funnel', ana: 'ANA-02', hasRange: true },\n { key: 'search', label: 'Search', ana: 'ANA-03', hasRange: true },\n { key: 'tools', label: 'Tools', ana: 'ANA-04', hasRange: true },\n { key: 'inventory', label: 'Inventory', ana: 'ANA-05', hasRange: false },\n { key: 'operations', label: 'Operations', ana: 'ANA-09', hasRange: true },\n];\n\n// P7.4 — the ANA-* analytics dashboard. Each tab reads one\n// `apps/admin/analytics/*` read model (raw SQL over the commerce tables,\n// libs/admin). ANA-11 web analytics / campaign attribution lives in\n// Countly, not here.\n@Component({\n standalone: false,\n selector: 'x-reports',\n templateUrl: './reports.component.html',\n})\nexport class ReportsComponent extends BaseDirective {\n private readonly source = this.apiService.on('apps/admin/analytics');\n\n readonly tabs = TABS;\n active: TabKey = 'commerce';\n days = 30;\n loading = true;\n data: any = null;\n\n override init = () => {\n this.load();\n };\n\n get activeTab(): Tab {\n return TABS.find((t) => t.key === this.active)!;\n }\n\n select(key: TabKey): void {\n if (this.active === key) return;\n this.active = key;\n this.load();\n }\n\n setDays(days: number): void {\n this.days = days;\n this.load();\n }\n\n load(): void {\n this.loading = true;\n this.data = null;\n const path = this.activeTab.hasRange\n ? `${this.active}?days=${this.days}`\n : this.active;\n this.source\n .getOne(path)\n .pipe(takeUntil(this.$))\n .subscribe(\n using((res: any) => {\n this.data = res?.data ?? null;\n this.loading = false;\n }),\n );\n }\n\n money(n: any): string {\n const v = Number(n) || 0;\n return `₦${v.toLocaleString('en-NG', { maximumFractionDigits: 0 })}`;\n }\n\n num(n: any): string {\n return (Number(n) || 0).toLocaleString('en-NG');\n }\n\n keys(obj: any): string[] {\n return obj ? Object.keys(obj) : [];\n }\n\n humanize(key: string): string {\n return key.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase());\n }\n}\n","<div class=\"x-page-head\">\n <div class=\"x-page-title\">Reports</div>\n <div class=\"x-page-subtitle\">\n Analytics read models over the commerce tables. Web traffic, sessions and\n campaign attribution are in Countly (ANA-11).\n </div>\n</div>\n\n<nav class=\"x-rp-tabs\">\n @for (t of tabs; track t.key) {\n <button\n type=\"button\"\n class=\"x-rp-tab\"\n [class.is-active]=\"active === t.key\"\n (click)=\"select(t.key)\"\n >\n {{ t.label }} <span class=\"x-rp-ana\">{{ t.ana }}</span>\n </button>\n }\n</nav>\n\n@if (activeTab.hasRange) {\n <div class=\"x-rp-range\">\n @for (d of [7, 30, 90]; track d) {\n <button\n type=\"button\"\n class=\"x-rp-range-btn\"\n [class.is-active]=\"days === d\"\n (click)=\"setDays(d)\"\n >\n {{ d }}d\n </button>\n }\n </div>\n}\n\n@if (loading) {\n <x-element-loader></x-element-loader>\n} @else if (!data) {\n <p class=\"x-rp-empty\">No data.</p>\n} @else {\n <!-- summary blocks: any object of scalars renders as cards -->\n @for (block of ['summary', 'fulfilment', 'returns', 'support', 'toolRevenue', 'compatibilityChecks']; track block) {\n @if (data[block] && keys(data[block]).length) {\n <div class=\"x-rp-section-label\">{{ humanize(block) }}</div>\n <div class=\"x-rp-cards\">\n @for (k of keys(data[block]); track k) {\n <div class=\"x-rp-card\">\n <div class=\"x-rp-card-label\">{{ humanize(k) }}</div>\n <div class=\"x-rp-card-value\">\n @if (k.includes('revenue') || k.includes('value') || k.includes('aov') || k.includes('discount')) {\n {{ money(data[block][k]) }}\n } @else {\n {{ num(data[block][k]) }}\n }\n </div>\n </div>\n }\n </div>\n }\n }\n\n <!-- funnel -->\n @if (data.stages) {\n <div class=\"x-rp-section-label\">Checkout funnel</div>\n @if (data.note) { <p class=\"x-rp-note\">{{ data.note }}</p> }\n <table class=\"x-rp-table\">\n <thead><tr><th>Stage</th><th>Count</th><th>% of top</th><th>Drop from previous</th></tr></thead>\n <tbody>\n @for (s of data.stages; track s.key) {\n <tr>\n <td>{{ s.label }}</td>\n <td>{{ num(s.value) }}</td>\n <td>{{ s.conversionFromTop }}%</td>\n <td [class.x-rp-drop]=\"s.dropFromPrev > 0\">{{ s.dropFromPrev }}%</td>\n </tr>\n }\n </tbody>\n </table>\n }\n\n <!-- generic array tables -->\n @for (block of ['byDay', 'byChannel', 'byPaymentMethod', 'byCategory', 'byType', 'byMethod', 'topQueries', 'zeroResult', 'blockFrequency', 'worstStockouts']; track block) {\n @if (data[block] && data[block].length) {\n <div class=\"x-rp-section-label\">{{ humanize(block) }}</div>\n <div class=\"x-rp-table-wrap\">\n <table class=\"x-rp-table\">\n <thead>\n <tr>\n @for (col of keys(data[block][0]); track col) {\n <th>{{ humanize(col) }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of data[block]; track $index) {\n <tr>\n @for (col of keys(row); track col) {\n <td>\n @if (col.includes('revenue') || col.includes('amount')) {\n {{ money(row[col]) }}\n } @else {\n {{ row[col] }}\n }\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n}\n\n<style>\n .x-page-head { margin-bottom: 16px; }\n .x-page-title { font-size: 24px; font-weight: 800; color: var(--color-text); }\n .x-page-subtitle { font-size: 13.5px; color: var(--color-text-muted); margin-top: 2px; max-width: 640px; }\n\n .x-rp-tabs { display: flex; flex-wrap: wrap; gap: 4px; border-bottom: 1px solid var(--color-border); margin-bottom: 14px; }\n .x-rp-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; }\n .x-rp-tab.is-active { color: var(--color-text); border-bottom-color: var(--color-brand); }\n .x-rp-ana { font-size: 10px; opacity: 0.6; font-weight: 500; }\n\n .x-rp-range { display: flex; gap: 6px; margin-bottom: 18px; }\n .x-rp-range-btn { appearance: none; background: transparent; border: 1px solid var(--color-border); border-radius: 999px; padding: 3px 12px; font-size: 12px; font-weight: 600; color: var(--color-text-muted); cursor: pointer; }\n .x-rp-range-btn.is-active { background: var(--color-brand); color: #fff; border-color: var(--color-brand); }\n\n .x-rp-section-label { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; color: var(--color-text-muted); margin: 24px 0 10px; }\n .x-rp-note { font-size: 12.5px; color: var(--color-text-muted); margin: -4px 0 10px; }\n .x-rp-empty { font-size: 13px; color: var(--color-text-muted); }\n\n .x-rp-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 10px; }\n .x-rp-card { border: 1px solid var(--color-border); border-radius: 10px; padding: 10px 14px; }\n .x-rp-card-label { font-size: 11.5px; color: var(--color-text-muted); }\n .x-rp-card-value { font-size: 19px; font-weight: 800; color: var(--color-text); margin-top: 3px; }\n\n .x-rp-table-wrap { overflow-x: auto; }\n .x-rp-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n .x-rp-table th, .x-rp-table td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--color-border); white-space: nowrap; }\n .x-rp-table th { color: var(--color-text-muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; }\n .x-rp-drop { color: var(--color-danger, #c0392b); font-weight: 600; }\n</style>\n","import { NgModule } from '@angular/core';\nimport { RouterModule } from '@angular/router';\nimport { SharedModule } from '@thescaffold/ngx-core';\nimport { ElementsModule } from '@thescaffold/ngx-ui';\nimport { ReportsComponent } from './reports.component';\n\n@NgModule({\n declarations: [ReportsComponent],\n imports: [\n SharedModule,\n ElementsModule,\n RouterModule.forChild([{ path: '', component: ReportsComponent }]),\n ],\n})\nexport class ReportsModule {}\n"],"names":["i1"],"mappings":"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"}
@@ -0,0 +1,106 @@
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
+ // P7.1 — ops console section pass (PRD 6.2, TRD 9.2). A standard list
12
+ // view on `x-webget-collection` over `apps/commerce/return-request`, matching the
13
+ // established admin pattern (users, routes, inbox). ops CRUD is covered
14
+ // by `admin:*:apps:commerce:*`.
15
+ class ReturnsComponent extends BaseDirective {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.pluralName = 'returns';
19
+ this.dataSource = this.apiService.on('apps/commerce/return-request');
20
+ this.columns = [
21
+ { key: 'rmaNumber', value: 'RMA' },
22
+ { key: 'orderId', value: 'Order' },
23
+ { key: 'status', value: 'Status', type: 'class', class: 'badge text-bg-light border' },
24
+ { key: 'createdAt', value: 'Opened', type: 'date' },
25
+ ];
26
+ this.page = 1;
27
+ this.perPage = 25;
28
+ this.list$ = new BehaviorSubject(null);
29
+ this.init = () => {
30
+ this.list();
31
+ };
32
+ }
33
+ list(page = this.page, perPage = this.perPage) {
34
+ this.dataSource
35
+ .getMany({ page, perPage })
36
+ .pipe(takeUntil(this.$), map((response) => this.toCollection(response)))
37
+ .subscribe(using((data) => this.list$.next(data)));
38
+ }
39
+ toCollection(response) {
40
+ return {
41
+ title: titleCase(this.pluralName),
42
+ columns: this.columns,
43
+ rows: response?.data,
44
+ hasHeaders: true,
45
+ hasTextFilter: true,
46
+ page: response?.meta?.current_page,
47
+ perPage: response?.meta?.per_page,
48
+ total: response?.meta?.total,
49
+ onPage: (page) => this.list(page),
50
+ };
51
+ }
52
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReturnsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
53
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ReturnsComponent, isStandalone: false, selector: "x-returns", usesInheritance: true, ngImport: i0, template: `
54
+ <div class="x-page-head">
55
+ <div class="x-page-title">Returns</div>
56
+ <div class="x-page-subtitle">RMA requests against delivered orders — triage, method and resolution.</div>
57
+ </div>
58
+
59
+ @if (list$ | async; as list) {
60
+ <x-webget-collection [data]="list"></x-webget-collection>
61
+ } @else {
62
+ <x-element-loader></x-element-loader>
63
+ }
64
+ `, 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" }] }); }
65
+ }
66
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReturnsComponent, decorators: [{
67
+ type: Component,
68
+ args: [{ standalone: false, selector: 'x-returns', template: `
69
+ <div class="x-page-head">
70
+ <div class="x-page-title">Returns</div>
71
+ <div class="x-page-subtitle">RMA requests against delivered orders — triage, method and resolution.</div>
72
+ </div>
73
+
74
+ @if (list$ | async; as list) {
75
+ <x-webget-collection [data]="list"></x-webget-collection>
76
+ } @else {
77
+ <x-element-loader></x-element-loader>
78
+ }
79
+ `, 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"] }]
80
+ }] });
81
+
82
+ class ReturnsModule {
83
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReturnsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
84
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: ReturnsModule, declarations: [ReturnsComponent], imports: [SharedModule,
85
+ ElementsModule,
86
+ WebgetsModule, i1$1.RouterModule] }); }
87
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReturnsModule, imports: [SharedModule,
88
+ ElementsModule,
89
+ WebgetsModule,
90
+ RouterModule.forChild([{ path: '', component: ReturnsComponent }])] }); }
91
+ }
92
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ReturnsModule, decorators: [{
93
+ type: NgModule,
94
+ args: [{
95
+ declarations: [ReturnsComponent],
96
+ imports: [
97
+ SharedModule,
98
+ ElementsModule,
99
+ WebgetsModule,
100
+ RouterModule.forChild([{ path: '', component: ReturnsComponent }]),
101
+ ],
102
+ }]
103
+ }] });
104
+
105
+ export { ReturnsModule };
106
+ //# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-returns.module-Bd2gdo6_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-returns.module-Bd2gdo6_.mjs","sources":["../../../projects/admin/src/lib/pages/returns/returns.component.ts","../../../projects/admin/src/lib/pages/returns/returns.module.ts"],"sourcesContent":["import { Component } from '@angular/core';\nimport { BaseDirective, titleCase, using } from '@thescaffold/ngx-core';\nimport { BehaviorSubject, map, takeUntil } from 'rxjs';\n\n// P7.1 — ops console section pass (PRD 6.2, TRD 9.2). A standard list\n// view on `x-webget-collection` over `apps/commerce/return-request`, matching the\n// established admin pattern (users, routes, inbox). ops CRUD is covered\n// by `admin:*:apps:commerce:*`.\n@Component({\n standalone: false,\n selector: 'x-returns',\n template: `\n <div class=\"x-page-head\">\n <div class=\"x-page-title\">Returns</div>\n <div class=\"x-page-subtitle\">RMA requests against delivered orders — triage, method and resolution.</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 ReturnsComponent extends BaseDirective {\n pluralName = 'returns';\n dataSource = this.apiService.on('apps/commerce/return-request');\n\n columns = [\n { key: 'rmaNumber', value: 'RMA' },\n { key: 'orderId', value: 'Order' },\n { key: 'status', value: 'Status', type: 'class', class: 'badge text-bg-light border' },\n { key: 'createdAt', value: 'Opened', type: 'date' },\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 { ReturnsComponent } from './returns.component';\n\n@NgModule({\n declarations: [ReturnsComponent],\n imports: [\n SharedModule,\n ElementsModule,\n WebgetsModule,\n RouterModule.forChild([{ path: '', component: ReturnsComponent }]),\n ],\n})\nexport class ReturnsModule {}\n"],"names":["i1"],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import * as i0 from '@angular/core';
2
+ import { EventEmitter, Output, Input, Component, NgModule } from '@angular/core';
3
+ import '@thescaffold/editor-core/define';
4
+
5
+ // P6.10 — a thin Angular host for `@thescaffold/editor-core`'s
6
+ // `<x-editor>` custom element. `@thescaffold/editor-angular` ships
7
+ // source-only (no build) so it can't be consumed as a package; this is
8
+ // the same handful of lines its `EditorComponent` uses. `content` is
9
+ // HTML in, HTML out via `contentChange`.
10
+ class RichEditorComponent {
11
+ constructor(host, zone) {
12
+ this.host = host;
13
+ this.zone = zone;
14
+ this.content = '';
15
+ this.contentChange = new EventEmitter();
16
+ this.el = null;
17
+ this.ctx = null;
18
+ }
19
+ ngAfterViewInit() {
20
+ this.zone.runOutsideAngular(() => {
21
+ const editor = document.createElement('x-editor');
22
+ editor.style.height = '100%';
23
+ this.host.nativeElement.appendChild(editor);
24
+ this.el = editor;
25
+ editor.addEventListener('xe:ready', (event) => {
26
+ this.ctx = event.detail?.editor ?? null;
27
+ if (this.content)
28
+ this.ctx?.setContent(this.content, 'html');
29
+ });
30
+ editor.addEventListener('xe:change', (event) => {
31
+ const next = event.detail?.content ?? '';
32
+ this.zone.run(() => this.contentChange.emit(next));
33
+ });
34
+ editor.config = {
35
+ mode: 'doc',
36
+ content: this.content,
37
+ editable: true,
38
+ theme: 'auto',
39
+ addons: [],
40
+ };
41
+ });
42
+ }
43
+ ngOnChanges(changes) {
44
+ if (changes['content'] && !changes['content'].firstChange && this.ctx) {
45
+ this.ctx.setContent(this.content ?? '', 'html');
46
+ }
47
+ }
48
+ ngOnDestroy() {
49
+ this.el?.remove();
50
+ this.el = null;
51
+ this.ctx = null;
52
+ }
53
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RichEditorComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
54
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: RichEditorComponent, isStandalone: false, selector: "x-rich-editor", inputs: { content: "content" }, outputs: { contentChange: "contentChange" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true, styles: [":host{display:block;min-height:160px}\n"] }); }
55
+ }
56
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RichEditorComponent, decorators: [{
57
+ type: Component,
58
+ args: [{ standalone: false, selector: 'x-rich-editor', template: '', styles: [":host{display:block;min-height:160px}\n"] }]
59
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }], propDecorators: { content: [{
60
+ type: Input
61
+ }], contentChange: [{
62
+ type: Output
63
+ }] } });
64
+
65
+ // P6.10 — shared WYSIWYG host, used by the CMS page builder (`content`)
66
+ // and the Learn-hub article editor (`articles`).
67
+ class RichEditorModule {
68
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RichEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
69
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: RichEditorModule, declarations: [RichEditorComponent], exports: [RichEditorComponent] }); }
70
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RichEditorModule }); }
71
+ }
72
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RichEditorModule, decorators: [{
73
+ type: NgModule,
74
+ args: [{
75
+ declarations: [RichEditorComponent],
76
+ exports: [RichEditorComponent],
77
+ }]
78
+ }] });
79
+
80
+ export { RichEditorComponent as R, RichEditorModule as a };
81
+ //# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-rich-editor.module-DW9Gy_QQ.mjs.map