@memberjunction/ng-explorer-settings 2.50.0 → 2.51.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 (66) hide show
  1. package/README.md +89 -1
  2. package/dist/lib/application-management/application-management.component.d.ts +59 -0
  3. package/dist/lib/application-management/application-management.component.d.ts.map +1 -0
  4. package/dist/lib/application-management/application-management.component.js +540 -0
  5. package/dist/lib/application-management/application-management.component.js.map +1 -0
  6. package/dist/lib/entity-permissions/entity-permissions.component.d.ts +71 -0
  7. package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -0
  8. package/dist/lib/entity-permissions/entity-permissions.component.js +667 -0
  9. package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -0
  10. package/dist/lib/module.d.ts +19 -23
  11. package/dist/lib/module.d.ts.map +1 -1
  12. package/dist/lib/module.js +13 -38
  13. package/dist/lib/module.js.map +1 -1
  14. package/dist/lib/role-management/role-management.component.d.ts +56 -0
  15. package/dist/lib/role-management/role-management.component.d.ts.map +1 -0
  16. package/dist/lib/role-management/role-management.component.js +464 -0
  17. package/dist/lib/role-management/role-management.component.js.map +1 -0
  18. package/dist/lib/settings/settings.component.d.ts +42 -51
  19. package/dist/lib/settings/settings.component.d.ts.map +1 -1
  20. package/dist/lib/settings/settings.component.js +432 -198
  21. package/dist/lib/settings/settings.component.js.map +1 -1
  22. package/dist/lib/shared/components/settings-card/settings-card.component.d.ts +27 -0
  23. package/dist/lib/shared/components/settings-card/settings-card.component.d.ts.map +1 -0
  24. package/dist/lib/shared/components/settings-card/settings-card.component.js +167 -0
  25. package/dist/lib/shared/components/settings-card/settings-card.component.js.map +1 -0
  26. package/dist/lib/shared/settings-card.component.d.ts +11 -0
  27. package/dist/lib/shared/settings-card.component.d.ts.map +1 -0
  28. package/dist/lib/shared/settings-card.component.js +73 -0
  29. package/dist/lib/shared/settings-card.component.js.map +1 -0
  30. package/dist/lib/shared/shared-settings.module.d.ts +9 -0
  31. package/dist/lib/shared/shared-settings.module.d.ts.map +1 -0
  32. package/dist/lib/shared/shared-settings.module.js +25 -0
  33. package/dist/lib/shared/shared-settings.module.js.map +1 -0
  34. package/dist/lib/sql-logging/sql-logging.component.d.ts +176 -0
  35. package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -0
  36. package/dist/lib/sql-logging/sql-logging.component.js +946 -0
  37. package/dist/lib/sql-logging/sql-logging.component.js.map +1 -0
  38. package/dist/lib/user-management/user-management.component.d.ts +65 -0
  39. package/dist/lib/user-management/user-management.component.d.ts.map +1 -0
  40. package/dist/lib/user-management/user-management.component.js +643 -0
  41. package/dist/lib/user-management/user-management.component.js.map +1 -0
  42. package/dist/public-api.d.ts +1 -5
  43. package/dist/public-api.d.ts.map +1 -1
  44. package/dist/public-api.js +1 -5
  45. package/dist/public-api.js.map +1 -1
  46. package/package.json +13 -13
  47. package/dist/lib/application-entities-grid/application-entities-grid.component.d.ts +0 -50
  48. package/dist/lib/application-entities-grid/application-entities-grid.component.d.ts.map +0 -1
  49. package/dist/lib/application-entities-grid/application-entities-grid.component.js +0 -342
  50. package/dist/lib/application-entities-grid/application-entities-grid.component.js.map +0 -1
  51. package/dist/lib/single-application/single-application.component.d.ts +0 -22
  52. package/dist/lib/single-application/single-application.component.d.ts.map +0 -1
  53. package/dist/lib/single-application/single-application.component.js +0 -130
  54. package/dist/lib/single-application/single-application.component.js.map +0 -1
  55. package/dist/lib/single-role/single-role.component.d.ts +0 -36
  56. package/dist/lib/single-role/single-role.component.d.ts.map +0 -1
  57. package/dist/lib/single-role/single-role.component.js +0 -188
  58. package/dist/lib/single-role/single-role.component.js.map +0 -1
  59. package/dist/lib/single-user/single-user.component.d.ts +0 -24
  60. package/dist/lib/single-user/single-user.component.d.ts.map +0 -1
  61. package/dist/lib/single-user/single-user.component.js +0 -176
  62. package/dist/lib/single-user/single-user.component.js.map +0 -1
  63. package/dist/lib/user-roles-grid/user-roles-grid.component.d.ts +0 -42
  64. package/dist/lib/user-roles-grid/user-roles-grid.component.d.ts.map +0 -1
  65. package/dist/lib/user-roles-grid/user-roles-grid.component.js +0 -326
  66. package/dist/lib/user-roles-grid/user-roles-grid.component.js.map +0 -1
@@ -0,0 +1,643 @@
1
+ import { Component } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { Subject, BehaviorSubject } from 'rxjs';
5
+ import { takeUntil, debounceTime, distinctUntilChanged } from 'rxjs/operators';
6
+ import { RunView } from '@memberjunction/core';
7
+ import { SharedSettingsModule } from '../shared/shared-settings.module';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@angular/common";
10
+ import * as i2 from "@angular/forms";
11
+ const _forTrack0 = ($index, $item) => $item.ID;
12
+ function UserManagementComponent_For_66_Template(rf, ctx) { if (rf & 1) {
13
+ i0.ɵɵelementStart(0, "option", 32);
14
+ i0.ɵɵtext(1);
15
+ i0.ɵɵelementEnd();
16
+ } if (rf & 2) {
17
+ const role_r1 = ctx.$implicit;
18
+ i0.ɵɵproperty("value", role_r1.ID);
19
+ i0.ɵɵadvance();
20
+ i0.ɵɵtextInterpolate(role_r1.Name);
21
+ } }
22
+ function UserManagementComponent_Conditional_72_Template(rf, ctx) { if (rf & 1) {
23
+ i0.ɵɵelementStart(0, "div", 38)(1, "div", 42);
24
+ i0.ɵɵelement(2, "div", 43)(3, "div", 43)(4, "div", 43);
25
+ i0.ɵɵelementEnd();
26
+ i0.ɵɵelementStart(5, "div", 44);
27
+ i0.ɵɵtext(6, "Loading users...");
28
+ i0.ɵɵelementEnd()();
29
+ } }
30
+ function UserManagementComponent_Conditional_73_Template(rf, ctx) { if (rf & 1) {
31
+ const _r2 = i0.ɵɵgetCurrentView();
32
+ i0.ɵɵelementStart(0, "div", 39)(1, "div", 45);
33
+ i0.ɵɵelement(2, "i", 46);
34
+ i0.ɵɵelementStart(3, "p", 47);
35
+ i0.ɵɵtext(4);
36
+ i0.ɵɵelementEnd();
37
+ i0.ɵɵelementStart(5, "button", 48);
38
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_73_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.loadInitialData()); });
39
+ i0.ɵɵelement(6, "i", 3);
40
+ i0.ɵɵtext(7, " Try Again ");
41
+ i0.ɵɵelementEnd()()();
42
+ } if (rf & 2) {
43
+ const ctx_r2 = i0.ɵɵnextContext();
44
+ i0.ɵɵadvance(4);
45
+ i0.ɵɵtextInterpolate(ctx_r2.error);
46
+ } }
47
+ function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template(rf, ctx) { if (rf & 1) {
48
+ const _r4 = i0.ɵɵgetCurrentView();
49
+ i0.ɵɵelementStart(0, "tr", 57);
50
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_tr_click_0_listener() { const user_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.selectUser(user_r5)); });
51
+ i0.ɵɵelementStart(1, "td", 58);
52
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_td_click_1_listener($event) { i0.ɵɵrestoreView(_r4); return i0.ɵɵresetView($event.stopPropagation()); });
53
+ i0.ɵɵelement(2, "input", 53);
54
+ i0.ɵɵelementEnd();
55
+ i0.ɵɵelementStart(3, "td")(4, "div", 59)(5, "div", 60);
56
+ i0.ɵɵtext(6);
57
+ i0.ɵɵelementEnd();
58
+ i0.ɵɵelementStart(7, "div", 61)(8, "div", 62);
59
+ i0.ɵɵtext(9);
60
+ i0.ɵɵelementEnd();
61
+ i0.ɵɵelementStart(10, "div", 63);
62
+ i0.ɵɵtext(11);
63
+ i0.ɵɵelementEnd()()()();
64
+ i0.ɵɵelementStart(12, "td");
65
+ i0.ɵɵtext(13);
66
+ i0.ɵɵelementEnd();
67
+ i0.ɵɵelementStart(14, "td")(15, "div", 64);
68
+ i0.ɵɵelement(16, "i");
69
+ i0.ɵɵtext(17);
70
+ i0.ɵɵelementEnd()();
71
+ i0.ɵɵelementStart(18, "td")(19, "span", 65);
72
+ i0.ɵɵelement(20, "i");
73
+ i0.ɵɵtext(21);
74
+ i0.ɵɵelementEnd()();
75
+ i0.ɵɵelementStart(22, "td")(23, "span", 66);
76
+ i0.ɵɵtext(24);
77
+ i0.ɵɵpipe(25, "date");
78
+ i0.ɵɵelementEnd()();
79
+ i0.ɵɵelementStart(26, "td", 67);
80
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_td_click_26_listener($event) { i0.ɵɵrestoreView(_r4); return i0.ɵɵresetView($event.stopPropagation()); });
81
+ i0.ɵɵelementStart(27, "button", 68);
82
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_button_click_27_listener() { const user_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.editUser(user_r5)); });
83
+ i0.ɵɵelement(28, "i", 69);
84
+ i0.ɵɵelementEnd();
85
+ i0.ɵɵelementStart(29, "button", 70);
86
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_button_click_29_listener() { const user_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.toggleUserStatus(user_r5)); });
87
+ i0.ɵɵelement(30, "i");
88
+ i0.ɵɵelementEnd();
89
+ i0.ɵɵelementStart(31, "button", 71);
90
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_button_click_31_listener() { const user_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.confirmDeleteUser(user_r5)); });
91
+ i0.ɵɵelement(32, "i", 72);
92
+ i0.ɵɵelementEnd()()();
93
+ } if (rf & 2) {
94
+ const user_r5 = ctx.$implicit;
95
+ const ctx_r2 = i0.ɵɵnextContext(3);
96
+ i0.ɵɵadvance(6);
97
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getUserInitials(user_r5), " ");
98
+ i0.ɵɵadvance(3);
99
+ i0.ɵɵtextInterpolate(user_r5.Name);
100
+ i0.ɵɵadvance(2);
101
+ i0.ɵɵtextInterpolate2(" ", user_r5.FirstName, " ", user_r5.LastName, " ");
102
+ i0.ɵɵadvance(2);
103
+ i0.ɵɵtextInterpolate(user_r5.Email);
104
+ i0.ɵɵadvance(3);
105
+ i0.ɵɵclassMap("fa-solid " + ctx_r2.getUserTypeIcon(user_r5));
106
+ i0.ɵɵadvance();
107
+ i0.ɵɵtextInterpolate1(" ", user_r5.Type, " ");
108
+ i0.ɵɵadvance(2);
109
+ i0.ɵɵclassMap(ctx_r2.getStatusClass(user_r5));
110
+ i0.ɵɵadvance();
111
+ i0.ɵɵclassMap("fa-solid " + ctx_r2.getStatusIcon(user_r5));
112
+ i0.ɵɵadvance();
113
+ i0.ɵɵtextInterpolate1(" ", user_r5.IsActive ? "Active" : "Inactive", " ");
114
+ i0.ɵɵadvance(3);
115
+ i0.ɵɵtextInterpolate1(" ", user_r5.__mj_UpdatedAt ? i0.ɵɵpipeBind2(25, 17, user_r5.__mj_UpdatedAt, "short") : "Never", " ");
116
+ i0.ɵɵadvance(5);
117
+ i0.ɵɵproperty("title", user_r5.IsActive ? "Deactivate" : "Activate");
118
+ i0.ɵɵadvance();
119
+ i0.ɵɵclassMap(user_r5.IsActive ? "fa-solid fa-toggle-on" : "fa-solid fa-toggle-off");
120
+ } }
121
+ function UserManagementComponent_Conditional_74_Conditional_1_Conditional_21_Template(rf, ctx) { if (rf & 1) {
122
+ i0.ɵɵelementStart(0, "div", 56);
123
+ i0.ɵɵelement(1, "i", 73);
124
+ i0.ɵɵelementStart(2, "p", 74);
125
+ i0.ɵɵtext(3, "No users found");
126
+ i0.ɵɵelementEnd();
127
+ i0.ɵɵelementStart(4, "p", 75);
128
+ i0.ɵɵtext(5, "Try adjusting your filters or add a new user");
129
+ i0.ɵɵelementEnd()();
130
+ } }
131
+ function UserManagementComponent_Conditional_74_Conditional_1_Template(rf, ctx) { if (rf & 1) {
132
+ i0.ɵɵelementStart(0, "div", 49)(1, "table", 51)(2, "thead")(3, "tr")(4, "th", 52);
133
+ i0.ɵɵelement(5, "input", 53);
134
+ i0.ɵɵelementEnd();
135
+ i0.ɵɵelementStart(6, "th");
136
+ i0.ɵɵtext(7, "User");
137
+ i0.ɵɵelementEnd();
138
+ i0.ɵɵelementStart(8, "th");
139
+ i0.ɵɵtext(9, "Email");
140
+ i0.ɵɵelementEnd();
141
+ i0.ɵɵelementStart(10, "th");
142
+ i0.ɵɵtext(11, "Type");
143
+ i0.ɵɵelementEnd();
144
+ i0.ɵɵelementStart(12, "th");
145
+ i0.ɵɵtext(13, "Status");
146
+ i0.ɵɵelementEnd();
147
+ i0.ɵɵelementStart(14, "th");
148
+ i0.ɵɵtext(15, "Last Updated");
149
+ i0.ɵɵelementEnd();
150
+ i0.ɵɵelementStart(16, "th", 54);
151
+ i0.ɵɵtext(17, "Actions");
152
+ i0.ɵɵelementEnd()()();
153
+ i0.ɵɵelementStart(18, "tbody");
154
+ i0.ɵɵrepeaterCreate(19, UserManagementComponent_Conditional_74_Conditional_1_For_20_Template, 33, 20, "tr", 55, _forTrack0);
155
+ i0.ɵɵelementEnd()();
156
+ i0.ɵɵtemplate(21, UserManagementComponent_Conditional_74_Conditional_1_Conditional_21_Template, 6, 0, "div", 56);
157
+ i0.ɵɵelementEnd();
158
+ } if (rf & 2) {
159
+ const ctx_r2 = i0.ɵɵnextContext(2);
160
+ i0.ɵɵadvance(19);
161
+ i0.ɵɵrepeater(ctx_r2.filteredUsers);
162
+ i0.ɵɵadvance(2);
163
+ i0.ɵɵconditional(ctx_r2.filteredUsers.length === 0 ? 21 : -1);
164
+ } }
165
+ function UserManagementComponent_Conditional_74_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) {
166
+ const _r6 = i0.ɵɵgetCurrentView();
167
+ i0.ɵɵelementStart(0, "div", 77);
168
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_2_For_2_Template_div_click_0_listener() { const user_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.selectUser(user_r7)); });
169
+ i0.ɵɵelementStart(1, "div", 78)(2, "div", 79);
170
+ i0.ɵɵtext(3);
171
+ i0.ɵɵelementEnd();
172
+ i0.ɵɵelementStart(4, "div", 80)(5, "button", 68);
173
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_2_For_2_Template_button_click_5_listener($event) { const user_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); ctx_r2.editUser(user_r7); return i0.ɵɵresetView($event.stopPropagation()); });
174
+ i0.ɵɵelement(6, "i", 69);
175
+ i0.ɵɵelementEnd();
176
+ i0.ɵɵelementStart(7, "button", 71);
177
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_2_For_2_Template_button_click_7_listener($event) { const user_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); ctx_r2.confirmDeleteUser(user_r7); return i0.ɵɵresetView($event.stopPropagation()); });
178
+ i0.ɵɵelement(8, "i", 72);
179
+ i0.ɵɵelementEnd()()();
180
+ i0.ɵɵelementStart(9, "div", 81)(10, "h3", 62);
181
+ i0.ɵɵtext(11);
182
+ i0.ɵɵelementEnd();
183
+ i0.ɵɵelementStart(12, "p", 63);
184
+ i0.ɵɵtext(13);
185
+ i0.ɵɵelementEnd();
186
+ i0.ɵɵelementStart(14, "p", 82);
187
+ i0.ɵɵelement(15, "i", 83);
188
+ i0.ɵɵtext(16);
189
+ i0.ɵɵelementEnd();
190
+ i0.ɵɵelementStart(17, "div", 84)(18, "div", 85);
191
+ i0.ɵɵelement(19, "i");
192
+ i0.ɵɵtext(20);
193
+ i0.ɵɵelementEnd();
194
+ i0.ɵɵelementStart(21, "span", 65);
195
+ i0.ɵɵelement(22, "i");
196
+ i0.ɵɵtext(23);
197
+ i0.ɵɵelementEnd()();
198
+ i0.ɵɵelementStart(24, "div", 86)(25, "div", 66);
199
+ i0.ɵɵelement(26, "i", 87);
200
+ i0.ɵɵtext(27);
201
+ i0.ɵɵpipe(28, "date");
202
+ i0.ɵɵelementEnd()()()();
203
+ } if (rf & 2) {
204
+ const user_r7 = ctx.$implicit;
205
+ const ctx_r2 = i0.ɵɵnextContext(3);
206
+ i0.ɵɵadvance(3);
207
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getUserInitials(user_r7), " ");
208
+ i0.ɵɵadvance(8);
209
+ i0.ɵɵtextInterpolate(user_r7.Name);
210
+ i0.ɵɵadvance(2);
211
+ i0.ɵɵtextInterpolate2("", user_r7.FirstName, " ", user_r7.LastName, "");
212
+ i0.ɵɵadvance(3);
213
+ i0.ɵɵtextInterpolate1(" ", user_r7.Email, " ");
214
+ i0.ɵɵadvance(3);
215
+ i0.ɵɵclassMap("fa-solid " + ctx_r2.getUserTypeIcon(user_r7));
216
+ i0.ɵɵadvance();
217
+ i0.ɵɵtextInterpolate1(" ", user_r7.Type, " ");
218
+ i0.ɵɵadvance();
219
+ i0.ɵɵclassMap(ctx_r2.getStatusClass(user_r7));
220
+ i0.ɵɵadvance();
221
+ i0.ɵɵclassMap("fa-solid " + ctx_r2.getStatusIcon(user_r7));
222
+ i0.ɵɵadvance();
223
+ i0.ɵɵtextInterpolate1(" ", user_r7.IsActive ? "Active" : "Inactive", " ");
224
+ i0.ɵɵadvance(4);
225
+ i0.ɵɵtextInterpolate1(" Last updated: ", user_r7.__mj_UpdatedAt ? i0.ɵɵpipeBind2(28, 14, user_r7.__mj_UpdatedAt, "short") : "Never", " ");
226
+ } }
227
+ function UserManagementComponent_Conditional_74_Conditional_2_Conditional_3_Template(rf, ctx) { if (rf & 1) {
228
+ i0.ɵɵelementStart(0, "div", 56);
229
+ i0.ɵɵelement(1, "i", 73);
230
+ i0.ɵɵelementStart(2, "p", 74);
231
+ i0.ɵɵtext(3, "No users found");
232
+ i0.ɵɵelementEnd();
233
+ i0.ɵɵelementStart(4, "p", 75);
234
+ i0.ɵɵtext(5, "Try adjusting your filters or add a new user");
235
+ i0.ɵɵelementEnd()();
236
+ } }
237
+ function UserManagementComponent_Conditional_74_Conditional_2_Template(rf, ctx) { if (rf & 1) {
238
+ i0.ɵɵelementStart(0, "div", 50);
239
+ i0.ɵɵrepeaterCreate(1, UserManagementComponent_Conditional_74_Conditional_2_For_2_Template, 29, 17, "div", 76, _forTrack0);
240
+ i0.ɵɵtemplate(3, UserManagementComponent_Conditional_74_Conditional_2_Conditional_3_Template, 6, 0, "div", 56);
241
+ i0.ɵɵelementEnd();
242
+ } if (rf & 2) {
243
+ const ctx_r2 = i0.ɵɵnextContext(2);
244
+ i0.ɵɵadvance();
245
+ i0.ɵɵrepeater(ctx_r2.filteredUsers);
246
+ i0.ɵɵadvance(2);
247
+ i0.ɵɵconditional(ctx_r2.filteredUsers.length === 0 ? 3 : -1);
248
+ } }
249
+ function UserManagementComponent_Conditional_74_Template(rf, ctx) { if (rf & 1) {
250
+ i0.ɵɵelementStart(0, "div", 40);
251
+ i0.ɵɵtemplate(1, UserManagementComponent_Conditional_74_Conditional_1_Template, 22, 1, "div", 49)(2, UserManagementComponent_Conditional_74_Conditional_2_Template, 4, 1, "div", 50);
252
+ i0.ɵɵelementEnd();
253
+ } if (rf & 2) {
254
+ const ctx_r2 = i0.ɵɵnextContext();
255
+ i0.ɵɵadvance();
256
+ i0.ɵɵconditional(ctx_r2.viewMode === "grid" ? 1 : -1);
257
+ i0.ɵɵadvance();
258
+ i0.ɵɵconditional(ctx_r2.viewMode === "cards" ? 2 : -1);
259
+ } }
260
+ function UserManagementComponent_Conditional_75_Template(rf, ctx) { if (rf & 1) {
261
+ const _r8 = i0.ɵɵgetCurrentView();
262
+ i0.ɵɵelementStart(0, "div", 88);
263
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_75_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showDeleteConfirm = false); });
264
+ i0.ɵɵelementStart(1, "div", 89);
265
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_75_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r8); return i0.ɵɵresetView($event.stopPropagation()); });
266
+ i0.ɵɵelementStart(2, "div", 90)(3, "h3", 91);
267
+ i0.ɵɵelement(4, "i", 92);
268
+ i0.ɵɵtext(5, " Confirm Delete ");
269
+ i0.ɵɵelementEnd();
270
+ i0.ɵɵelementStart(6, "button", 93);
271
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_75_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showDeleteConfirm = false); });
272
+ i0.ɵɵelement(7, "i", 94);
273
+ i0.ɵɵelementEnd()();
274
+ i0.ɵɵelementStart(8, "div", 95)(9, "p");
275
+ i0.ɵɵtext(10, "Are you sure you want to delete user ");
276
+ i0.ɵɵelementStart(11, "strong");
277
+ i0.ɵɵtext(12);
278
+ i0.ɵɵelementEnd();
279
+ i0.ɵɵtext(13, "?");
280
+ i0.ɵɵelementEnd();
281
+ i0.ɵɵelementStart(14, "p", 96);
282
+ i0.ɵɵtext(15, "This action cannot be undone.");
283
+ i0.ɵɵelementEnd()();
284
+ i0.ɵɵelementStart(16, "div", 97)(17, "button", 4);
285
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_75_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showDeleteConfirm = false); });
286
+ i0.ɵɵtext(18, "Cancel");
287
+ i0.ɵɵelementEnd();
288
+ i0.ɵɵelementStart(19, "button", 98);
289
+ i0.ɵɵlistener("click", function UserManagementComponent_Conditional_75_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.deleteUser()); });
290
+ i0.ɵɵelement(20, "i", 72);
291
+ i0.ɵɵtext(21, " Delete User ");
292
+ i0.ɵɵelementEnd()()()();
293
+ } if (rf & 2) {
294
+ const ctx_r2 = i0.ɵɵnextContext();
295
+ i0.ɵɵadvance(12);
296
+ i0.ɵɵtextInterpolate(ctx_r2.selectedUser.Name);
297
+ } }
298
+ export class UserManagementComponent {
299
+ // State management
300
+ users = [];
301
+ filteredUsers = [];
302
+ roles = [];
303
+ selectedUser = null;
304
+ isLoading = false;
305
+ error = null;
306
+ // Stats
307
+ stats = {
308
+ totalUsers: 0,
309
+ activeUsers: 0,
310
+ inactiveUsers: 0,
311
+ adminUsers: 0 // This will be based on roles, not Type
312
+ };
313
+ // Filters
314
+ filters$ = new BehaviorSubject({
315
+ status: 'all',
316
+ role: '',
317
+ search: ''
318
+ });
319
+ // UI State
320
+ showCreateDialog = false;
321
+ showEditDialog = false;
322
+ showDeleteConfirm = false;
323
+ viewMode = 'grid';
324
+ // Grid configuration
325
+ gridConfig = {
326
+ pageSize: 20,
327
+ sortField: 'Name',
328
+ sortDirection: 'asc'
329
+ };
330
+ destroy$ = new Subject();
331
+ constructor() { }
332
+ ngOnInit() {
333
+ this.loadInitialData();
334
+ this.setupFilterSubscription();
335
+ }
336
+ ngOnDestroy() {
337
+ this.destroy$.next();
338
+ this.destroy$.complete();
339
+ }
340
+ async loadInitialData() {
341
+ try {
342
+ this.isLoading = true;
343
+ this.error = null;
344
+ // Load users and roles in parallel
345
+ const [users, roles] = await Promise.all([
346
+ this.loadUsers(),
347
+ this.loadRoles()
348
+ ]);
349
+ this.users = users;
350
+ this.roles = roles;
351
+ this.calculateStats();
352
+ this.applyFilters();
353
+ }
354
+ catch (error) {
355
+ console.error('Error loading user data:', error);
356
+ this.error = 'Failed to load user data. Please try again.';
357
+ }
358
+ finally {
359
+ this.isLoading = false;
360
+ }
361
+ }
362
+ async loadUsers() {
363
+ const rv = new RunView();
364
+ const result = await rv.RunView({
365
+ EntityName: 'Users',
366
+ ResultType: 'entity_object'
367
+ });
368
+ return result.Success ? result.Results : [];
369
+ }
370
+ async loadRoles() {
371
+ const rv = new RunView();
372
+ const result = await rv.RunView({
373
+ EntityName: 'Roles',
374
+ ResultType: 'entity_object',
375
+ OrderBy: 'Name ASC'
376
+ });
377
+ return result.Success ? result.Results : [];
378
+ }
379
+ setupFilterSubscription() {
380
+ this.filters$
381
+ .pipe(debounceTime(300), distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), takeUntil(this.destroy$))
382
+ .subscribe(() => {
383
+ this.applyFilters();
384
+ });
385
+ }
386
+ applyFilters() {
387
+ const filters = this.filters$.value;
388
+ let filtered = [...this.users];
389
+ // Apply status filter
390
+ if (filters.status !== 'all') {
391
+ filtered = filtered.filter(user => filters.status === 'active' ? user.IsActive : !user.IsActive);
392
+ }
393
+ // Apply role filter
394
+ if (filters.role) {
395
+ // This would need to be implemented based on your user-role relationship
396
+ // For now, we'll skip this filter
397
+ }
398
+ // Apply search filter
399
+ if (filters.search) {
400
+ const searchLower = filters.search.toLowerCase();
401
+ filtered = filtered.filter(user => user.Name?.toLowerCase().includes(searchLower) ||
402
+ user.Email?.toLowerCase().includes(searchLower) ||
403
+ user.FirstName?.toLowerCase().includes(searchLower) ||
404
+ user.LastName?.toLowerCase().includes(searchLower));
405
+ }
406
+ this.filteredUsers = filtered;
407
+ }
408
+ calculateStats() {
409
+ this.stats = {
410
+ totalUsers: this.users.length,
411
+ activeUsers: this.users.filter(u => u.IsActive).length,
412
+ inactiveUsers: this.users.filter(u => !u.IsActive).length,
413
+ adminUsers: this.users.filter(u => u.Type === 'Owner').length // Using Owner as admin type
414
+ };
415
+ }
416
+ // Public methods for template
417
+ onSearchChange(event) {
418
+ const value = event.target.value;
419
+ this.updateFilter({ search: value });
420
+ }
421
+ onStatusFilterChange(status) {
422
+ this.updateFilter({ status });
423
+ }
424
+ onRoleFilterChange(role) {
425
+ this.updateFilter({ role });
426
+ }
427
+ updateFilter(partial) {
428
+ this.filters$.next({
429
+ ...this.filters$.value,
430
+ ...partial
431
+ });
432
+ }
433
+ selectUser(user) {
434
+ this.selectedUser = user;
435
+ this.showEditDialog = true;
436
+ }
437
+ createNewUser() {
438
+ this.selectedUser = null;
439
+ this.showCreateDialog = true;
440
+ }
441
+ editUser(user) {
442
+ this.selectedUser = user;
443
+ this.showEditDialog = true;
444
+ }
445
+ confirmDeleteUser(user) {
446
+ this.selectedUser = user;
447
+ this.showDeleteConfirm = true;
448
+ }
449
+ async deleteUser() {
450
+ if (!this.selectedUser)
451
+ return;
452
+ try {
453
+ // Implement user deletion logic
454
+ this.showDeleteConfirm = false;
455
+ await this.loadInitialData();
456
+ }
457
+ catch (error) {
458
+ console.error('Error deleting user:', error);
459
+ this.error = 'Failed to delete user';
460
+ }
461
+ }
462
+ async toggleUserStatus(user) {
463
+ try {
464
+ user.IsActive = !user.IsActive;
465
+ await user.Save();
466
+ this.calculateStats();
467
+ }
468
+ catch (error) {
469
+ console.error('Error updating user status:', error);
470
+ user.IsActive = !user.IsActive; // Revert on error
471
+ }
472
+ }
473
+ toggleViewMode() {
474
+ this.viewMode = this.viewMode === 'grid' ? 'cards' : 'grid';
475
+ }
476
+ exportUsers() {
477
+ // Implement export functionality
478
+ console.log('Export users');
479
+ }
480
+ refreshData() {
481
+ this.loadInitialData();
482
+ }
483
+ getStatusIcon(user) {
484
+ return user.IsActive ? 'fa-check-circle' : 'fa-times-circle';
485
+ }
486
+ getStatusClass(user) {
487
+ return user.IsActive ? 'status-active' : 'status-inactive';
488
+ }
489
+ getUserTypeIcon(user) {
490
+ switch (user.Type) {
491
+ case 'Owner':
492
+ return 'fa-shield-halved';
493
+ case 'User':
494
+ return 'fa-user';
495
+ default:
496
+ return 'fa-user';
497
+ }
498
+ }
499
+ getUserInitials(user) {
500
+ const first = user.FirstName?.charAt(0) || '';
501
+ const last = user.LastName?.charAt(0) || '';
502
+ return (first + last).toUpperCase() || user.Name?.charAt(0).toUpperCase() || 'U';
503
+ }
504
+ static ɵfac = function UserManagementComponent_Factory(t) { return new (t || UserManagementComponent)(); };
505
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserManagementComponent, selectors: [["mj-user-management"]], standalone: true, features: [i0.ɵɵStandaloneFeature], decls: 76, vars: 22, consts: [[1, "user-management-container"], [1, "action-buttons"], [1, "btn-secondary", 3, "click", "disabled"], [1, "fa-solid", "fa-refresh"], [1, "btn-secondary", 3, "click"], [1, "fa-solid", "fa-download"], [1, "btn-primary", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "stats-grid", 2, "display", "flex"], [1, "stat-card"], [1, "stat-icon", "stat-icon-total"], [1, "fa-solid", "fa-users"], [1, "stat-content"], [1, "stat-value"], [1, "stat-label"], [1, "stat-icon", "stat-icon-active"], [1, "fa-solid", "fa-user-check"], [1, "stat-icon", "stat-icon-inactive"], [1, "fa-solid", "fa-user-xmark"], [1, "stat-icon", "stat-icon-admin"], [1, "fa-solid", "fa-shield-halved"], [1, "filters-section"], [1, "filters-row"], [1, "search-container"], [1, "fa-solid", "fa-search", "search-icon"], ["type", "text", "placeholder", "Search users by name or email...", 1, "search-input", 3, "input", "value"], [1, "filter-group"], [1, "filter-label"], [1, "filter-buttons"], [1, "filter-btn", 3, "click"], [1, "filter-select", 3, "change"], ["value", ""], [3, "value"], [1, "view-toggle"], ["title", "Grid View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-table"], ["title", "Card View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-th-large"], [1, "loading-container"], [1, "error-container"], [1, "content-area"], [1, "modal-backdrop"], [1, "loading-spinner"], [1, "spinner-ring"], [1, "loading-text"], [1, "error-content"], [1, "fa-solid", "fa-exclamation-triangle", "error-icon"], [1, "error-message"], [1, "retry-button", 3, "click"], [1, "users-table"], [1, "users-grid"], [1, "modern-table"], [1, "th-checkbox"], ["type", "checkbox", 1, "checkbox"], [1, "th-actions"], [1, "table-row"], [1, "empty-state"], [1, "table-row", 3, "click"], [1, "td-checkbox", 3, "click"], [1, "user-cell"], [1, "user-avatar"], [1, "user-info"], [1, "user-name"], [1, "user-fullname"], [1, "user-type"], [1, "status-badge"], [1, "last-login"], [1, "td-actions", 3, "click"], ["title", "Edit", 1, "action-btn", 3, "click"], [1, "fa-solid", "fa-edit"], [1, "action-btn", 3, "click", "title"], ["title", "Delete", 1, "action-btn", "action-btn-danger", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "fa-solid", "fa-users-slash", "empty-icon"], [1, "empty-text"], [1, "empty-subtext"], [1, "user-card"], [1, "user-card", 3, "click"], [1, "card-header"], [1, "user-avatar-large"], [1, "card-actions"], [1, "card-body"], [1, "user-email"], [1, "fa-solid", "fa-envelope"], [1, "card-meta"], [1, "meta-item"], [1, "card-footer"], [1, "fa-solid", "fa-clock"], [1, "modal-backdrop", 3, "click"], [1, "modal-dialog", 3, "click"], [1, "modal-header"], [1, "modal-title"], [1, "fa-solid", "fa-exclamation-triangle", "text-danger"], [1, "modal-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "modal-body"], [1, "text-muted"], [1, "modal-footer"], [1, "btn-danger", 3, "click"]], template: function UserManagementComponent_Template(rf, ctx) { if (rf & 1) {
506
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "button", 2);
507
+ i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_2_listener() { return ctx.refreshData(); });
508
+ i0.ɵɵelement(3, "i", 3);
509
+ i0.ɵɵtext(4, " Refresh ");
510
+ i0.ɵɵelementEnd();
511
+ i0.ɵɵelementStart(5, "button", 4);
512
+ i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_5_listener() { return ctx.exportUsers(); });
513
+ i0.ɵɵelement(6, "i", 5);
514
+ i0.ɵɵtext(7, " Export ");
515
+ i0.ɵɵelementEnd();
516
+ i0.ɵɵelementStart(8, "button", 6);
517
+ i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_8_listener() { return ctx.createNewUser(); });
518
+ i0.ɵɵelement(9, "i", 7);
519
+ i0.ɵɵtext(10, " Add User ");
520
+ i0.ɵɵelementEnd()();
521
+ i0.ɵɵelementStart(11, "div", 8)(12, "div", 9)(13, "div", 10);
522
+ i0.ɵɵelement(14, "i", 11);
523
+ i0.ɵɵelementEnd();
524
+ i0.ɵɵelementStart(15, "div", 12)(16, "div", 13);
525
+ i0.ɵɵtext(17);
526
+ i0.ɵɵelementEnd();
527
+ i0.ɵɵelementStart(18, "div", 14);
528
+ i0.ɵɵtext(19, "Total Users");
529
+ i0.ɵɵelementEnd()()();
530
+ i0.ɵɵelementStart(20, "div", 9)(21, "div", 15);
531
+ i0.ɵɵelement(22, "i", 16);
532
+ i0.ɵɵelementEnd();
533
+ i0.ɵɵelementStart(23, "div", 12)(24, "div", 13);
534
+ i0.ɵɵtext(25);
535
+ i0.ɵɵelementEnd();
536
+ i0.ɵɵelementStart(26, "div", 14);
537
+ i0.ɵɵtext(27, "Active Users");
538
+ i0.ɵɵelementEnd()()();
539
+ i0.ɵɵelementStart(28, "div", 9)(29, "div", 17);
540
+ i0.ɵɵelement(30, "i", 18);
541
+ i0.ɵɵelementEnd();
542
+ i0.ɵɵelementStart(31, "div", 12)(32, "div", 13);
543
+ i0.ɵɵtext(33);
544
+ i0.ɵɵelementEnd();
545
+ i0.ɵɵelementStart(34, "div", 14);
546
+ i0.ɵɵtext(35, "Inactive Users");
547
+ i0.ɵɵelementEnd()()();
548
+ i0.ɵɵelementStart(36, "div", 9)(37, "div", 19);
549
+ i0.ɵɵelement(38, "i", 20);
550
+ i0.ɵɵelementEnd();
551
+ i0.ɵɵelementStart(39, "div", 12)(40, "div", 13);
552
+ i0.ɵɵtext(41);
553
+ i0.ɵɵelementEnd();
554
+ i0.ɵɵelementStart(42, "div", 14);
555
+ i0.ɵɵtext(43, "Owners");
556
+ i0.ɵɵelementEnd()()()();
557
+ i0.ɵɵelementStart(44, "div", 21)(45, "div", 22)(46, "div", 23);
558
+ i0.ɵɵelement(47, "i", 24);
559
+ i0.ɵɵelementStart(48, "input", 25);
560
+ i0.ɵɵlistener("input", function UserManagementComponent_Template_input_input_48_listener($event) { return ctx.onSearchChange($event); });
561
+ i0.ɵɵelementEnd()();
562
+ i0.ɵɵelementStart(49, "div", 26)(50, "label", 27);
563
+ i0.ɵɵtext(51, "Status");
564
+ i0.ɵɵelementEnd();
565
+ i0.ɵɵelementStart(52, "div", 28)(53, "button", 29);
566
+ i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_53_listener() { return ctx.onStatusFilterChange("all"); });
567
+ i0.ɵɵtext(54, " All ");
568
+ i0.ɵɵelementEnd();
569
+ i0.ɵɵelementStart(55, "button", 29);
570
+ i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_55_listener() { return ctx.onStatusFilterChange("active"); });
571
+ i0.ɵɵtext(56, " Active ");
572
+ i0.ɵɵelementEnd();
573
+ i0.ɵɵelementStart(57, "button", 29);
574
+ i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_57_listener() { return ctx.onStatusFilterChange("inactive"); });
575
+ i0.ɵɵtext(58, " Inactive ");
576
+ i0.ɵɵelementEnd()()();
577
+ i0.ɵɵelementStart(59, "div", 26)(60, "label", 27);
578
+ i0.ɵɵtext(61, "Role");
579
+ i0.ɵɵelementEnd();
580
+ i0.ɵɵelementStart(62, "select", 30);
581
+ i0.ɵɵlistener("change", function UserManagementComponent_Template_select_change_62_listener($event) { return ctx.onRoleFilterChange($event.target.value); });
582
+ i0.ɵɵelementStart(63, "option", 31);
583
+ i0.ɵɵtext(64, "All Roles");
584
+ i0.ɵɵelementEnd();
585
+ i0.ɵɵrepeaterCreate(65, UserManagementComponent_For_66_Template, 2, 2, "option", 32, _forTrack0);
586
+ i0.ɵɵelementEnd()();
587
+ i0.ɵɵelementStart(67, "div", 33)(68, "button", 34);
588
+ i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_68_listener() { return ctx.viewMode = "grid"; });
589
+ i0.ɵɵelement(69, "i", 35);
590
+ i0.ɵɵelementEnd();
591
+ i0.ɵɵelementStart(70, "button", 36);
592
+ i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_70_listener() { return ctx.viewMode = "cards"; });
593
+ i0.ɵɵelement(71, "i", 37);
594
+ i0.ɵɵelementEnd()()()();
595
+ i0.ɵɵtemplate(72, UserManagementComponent_Conditional_72_Template, 7, 0, "div", 38)(73, UserManagementComponent_Conditional_73_Template, 8, 1, "div", 39)(74, UserManagementComponent_Conditional_74_Template, 3, 2, "div", 40)(75, UserManagementComponent_Conditional_75_Template, 22, 1, "div", 41);
596
+ i0.ɵɵelementEnd();
597
+ } if (rf & 2) {
598
+ i0.ɵɵadvance(2);
599
+ i0.ɵɵproperty("disabled", ctx.isLoading);
600
+ i0.ɵɵadvance();
601
+ i0.ɵɵclassProp("fa-spin", ctx.isLoading);
602
+ i0.ɵɵadvance(14);
603
+ i0.ɵɵtextInterpolate(ctx.stats.totalUsers);
604
+ i0.ɵɵadvance(8);
605
+ i0.ɵɵtextInterpolate(ctx.stats.activeUsers);
606
+ i0.ɵɵadvance(8);
607
+ i0.ɵɵtextInterpolate(ctx.stats.inactiveUsers);
608
+ i0.ɵɵadvance(8);
609
+ i0.ɵɵtextInterpolate(ctx.stats.adminUsers);
610
+ i0.ɵɵadvance(7);
611
+ i0.ɵɵproperty("value", ctx.filters$.value.search);
612
+ i0.ɵɵadvance(5);
613
+ i0.ɵɵclassProp("active", ctx.filters$.value.status === "all");
614
+ i0.ɵɵadvance(2);
615
+ i0.ɵɵclassProp("active", ctx.filters$.value.status === "active");
616
+ i0.ɵɵadvance(2);
617
+ i0.ɵɵclassProp("active", ctx.filters$.value.status === "inactive");
618
+ i0.ɵɵadvance(8);
619
+ i0.ɵɵrepeater(ctx.roles);
620
+ i0.ɵɵadvance(3);
621
+ i0.ɵɵclassProp("active", ctx.viewMode === "grid");
622
+ i0.ɵɵadvance(2);
623
+ i0.ɵɵclassProp("active", ctx.viewMode === "cards");
624
+ i0.ɵɵadvance(2);
625
+ i0.ɵɵconditional(ctx.isLoading ? 72 : -1);
626
+ i0.ɵɵadvance();
627
+ i0.ɵɵconditional(ctx.error && !ctx.isLoading ? 73 : -1);
628
+ i0.ɵɵadvance();
629
+ i0.ɵɵconditional(!ctx.isLoading && !ctx.error ? 74 : -1);
630
+ i0.ɵɵadvance();
631
+ i0.ɵɵconditional(ctx.showDeleteConfirm && ctx.selectedUser ? 75 : -1);
632
+ } }, dependencies: [CommonModule, i1.DatePipe, FormsModule, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, SharedSettingsModule], styles: ["@import '../shared/styles/variables';\n@import '../shared/styles/mixins';\n\n.user-management-container[_ngcontent-%COMP%] {\n @include scrollable-container;\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n//[_ngcontent-%COMP%] Action[_ngcontent-%COMP%] Buttons\n.action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n margin-bottom: 1.5rem;\n\n @media (max-width: 768px) {\n justify-content: center;\n flex-wrap: wrap;\n }\n}\n\n//[_ngcontent-%COMP%] Buttons\n.btn-primary[_ngcontent-%COMP%] {\n @include button-base;\n background-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n }\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n @include button-base;\n background-color: #ffffff;\n color: #374151;\n border: 1px solid #e5e7eb;\n \n &:hover {\n background-color: #f9fafb;\n border-color: #2196f3;\n color: #2196f3;\n }\n}\n\n.btn-danger[_ngcontent-%COMP%] {\n @include button-base;\n background-color: #f44336;\n color: white;\n \n &:hover {\n background-color: #d32f2f;\n }\n}\n\n//[_ngcontent-%COMP%] Stats[_ngcontent-%COMP%] Grid\n.stats-grid[_ngcontent-%COMP%] {\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin-bottom: 2rem;\n width: 100%;\n\n @media (max-width: 768px) {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n.stat-card[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n display: flex;\n margin-right: 10px;\n align-items: center;\n gap: 1rem;\n transition: all 0.3s ease;\n min-width: 0; // Prevent grid blowout\n\n &:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n }\n}\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.5rem;\n\n &-total {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n &-active {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n &-inactive {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n }\n\n &-admin {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n }\n}\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n\n .stat-value {\n font-size: 2rem;\n font-weight: 700;\n color: #1f2937;\n line-height: 1;\n }\n\n .stat-label {\n color: #6b7280;\n font-size: 0.875rem;\n margin-top: 0.25rem;\n }\n}\n\n//[_ngcontent-%COMP%] Filters[_ngcontent-%COMP%] Section\n.filters-section[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n margin-bottom: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n}\n\n.filters-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 1.5rem;\n align-items: flex-end;\n flex-wrap: wrap;\n\n @media (max-width: 768px) {\n gap: 1rem;\n }\n}\n\n.search-container[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 250px;\n position: relative;\n\n .search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: #6b7280;\n font-size: 1rem;\n }\n\n .search-input {\n width: 100%;\n padding: 0.75rem 1rem 0.75rem 2.75rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n transition: all 0.2s;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n }\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n\n .filter-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: #374151;\n }\n\n .filter-buttons {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n }\n\n .filter-btn {\n padding: 0.5rem 1rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n color: #374151;\n }\n\n &.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n }\n\n .filter-select {\n padding: 0.625rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: white;\n font-size: 0.875rem;\n color: #374151;\n cursor: pointer;\n transition: all 0.2s;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n }\n}\n\n.view-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n\n .view-btn {\n padding: 0.5rem 0.75rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1rem;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n color: #374151;\n }\n\n &.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n }\n}\n\n//[_ngcontent-%COMP%] Content[_ngcontent-%COMP%] Area\n.content-area[_ngcontent-%COMP%] {\n @include scrollable-content;\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n}\n\n//[_ngcontent-%COMP%] Table[_ngcontent-%COMP%] View\n.users-table[_ngcontent-%COMP%] {\n overflow-x: auto;\n max-height: calc(100vh - 450px); // Dynamic height\n overflow-y: auto;\n}\n\n.modern-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n\n thead {\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n\n th {\n padding: 1rem;\n text-align: left;\n font-size: 0.875rem;\n font-weight: 600;\n color: #374151;\n white-space: nowrap;\n\n &.th-checkbox {\n width: 50px;\n }\n\n &.th-actions {\n text-align: center;\n width: 150px;\n }\n }\n }\n\n tbody {\n tr {\n border-bottom: 1px solid #f3f4f6;\n transition: background-color 0.2s;\n cursor: pointer;\n\n &:hover {\n background-color: #f9fafb;\n }\n }\n\n td {\n padding: 1rem;\n font-size: 0.875rem;\n color: #374151;\n\n &.td-checkbox {\n width: 50px;\n }\n\n &.td-actions {\n text-align: center;\n }\n }\n }\n}\n\n.checkbox[_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n}\n\n.user-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.user-avatar[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 0.875rem;\n}\n\n.user-avatar-large[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 1.5rem;\n margin: 0 auto 1rem;\n}\n\n.user-info[_ngcontent-%COMP%] {\n .user-name {\n font-weight: 600;\n color: #1f2937;\n }\n\n .user-fullname {\n font-size: 0.75rem;\n color: #6b7280;\n }\n}\n\n.user-type[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n color: #4b5563;\n\n i {\n font-size: 0.875rem;\n }\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.75rem;\n border-radius: 20px;\n font-size: 0.75rem;\n font-weight: 500;\n\n &.status-active {\n background: rgba(76, 175, 80, 0.1);\n color: #388e3c;\n }\n\n &.status-inactive {\n background: rgba(244, 67, 54, 0.1);\n color: #d32f2f;\n }\n\n i {\n font-size: 0.625rem;\n }\n}\n\n.last-login[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.875rem;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1rem;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n background: #f3f4f6;\n color: #2196f3;\n }\n\n &-danger:hover {\n color: #f44336;\n }\n}\n\n//[_ngcontent-%COMP%] Card[_ngcontent-%COMP%] View\n.users-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 1.5rem;\n padding: 1.5rem;\n\n @media (max-width: 768px) {\n grid-template-columns: 1fr;\n gap: 1rem;\n padding: 1rem;\n }\n}\n\n.user-card[_ngcontent-%COMP%] {\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 12px;\n padding: 1.5rem;\n cursor: pointer;\n transition: all 0.3s ease;\n\n &:hover {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n border-color: #2196f3;\n }\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 1rem;\n}\n\n.card-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n}\n\n.card-body[_ngcontent-%COMP%] {\n text-align: center;\n\n .user-name {\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.25rem 0;\n }\n\n .user-fullname {\n color: #6b7280;\n margin: 0 0 0.75rem 0;\n }\n\n .user-email {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n color: #4b5563;\n font-size: 0.875rem;\n margin-bottom: 1rem;\n\n i {\n color: #6b7280;\n }\n }\n}\n\n.card-meta[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 1rem;\n padding: 1rem 0;\n border-top: 1px solid #f3f4f6;\n border-bottom: 1px solid #f3f4f6;\n margin-bottom: 1rem;\n\n .meta-item {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n color: #4b5563;\n font-size: 0.875rem;\n }\n}\n\n.card-footer[_ngcontent-%COMP%] {\n .last-login {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n color: #6b7280;\n font-size: 0.75rem;\n\n i {\n font-size: 0.875rem;\n }\n }\n}\n\n//[_ngcontent-%COMP%] Empty[_ngcontent-%COMP%] State\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n\n .empty-icon {\n font-size: 4rem;\n color: #e5e7eb;\n margin-bottom: 1rem;\n }\n\n .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: #374151;\n margin: 0 0 0.5rem 0;\n }\n\n .empty-subtext {\n color: #6b7280;\n margin: 0;\n }\n}\n\n//[_ngcontent-%COMP%] Loading[_ngcontent-%COMP%] State\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n position: relative;\n width: 60px;\n height: 60px;\n margin-bottom: 1rem;\n\n .spinner-ring {\n position: absolute;\n width: 100%;\n height: 100%;\n border: 3px solid transparent;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_spin 1.5s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n\n &:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n }\n\n &:nth-child(2) {\n border-color: transparent #4caf50 transparent transparent;\n animation-delay: -0.3s;\n }\n\n &:nth-child(3) {\n border-color: transparent transparent #ff9800 transparent;\n animation-delay: -0.15s;\n }\n }\n}\n\n@keyframes _ngcontent-%COMP%_spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n.loading-text[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n//[_ngcontent-%COMP%] Error[_ngcontent-%COMP%] State\n.error-container[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n\n .error-icon {\n font-size: 3rem;\n color: #f44336;\n margin-bottom: 1rem;\n }\n\n .error-message {\n color: #374151;\n margin-bottom: 1.5rem;\n }\n\n .retry-button {\n @include button-base;\n background-color: #2196f3;\n color: white;\n }\n}\n\n//[_ngcontent-%COMP%] Modal[_ngcontent-%COMP%] Styles\n.modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s ease;\n}\n\n.modal-dialog[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideUp 0.3s ease;\n}\n\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.5rem;\n border-bottom: 1px solid #e5e7eb;\n\n .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0;\n }\n\n .modal-close {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n\n &:hover {\n background: #f3f4f6;\n color: #374151;\n }\n }\n}\n\n.modal-body[_ngcontent-%COMP%] {\n padding: 1.5rem;\n\n p {\n margin: 0 0 1rem 0;\n color: #374151;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n .text-muted {\n color: #6b7280;\n font-size: 0.875rem;\n }\n}\n\n.modal-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid #e5e7eb;\n background: #f9fafb;\n}\n\n//[_ngcontent-%COMP%] Animations\n@keyframes[_ngcontent-%COMP%] fadeIn[_ngcontent-%COMP%] {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n//[_ngcontent-%COMP%] Utility[_ngcontent-%COMP%] Classes\n.text-danger[_ngcontent-%COMP%] {\n color: #f44336;\n}"] });
633
+ }
634
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserManagementComponent, [{
635
+ type: Component,
636
+ args: [{ selector: 'mj-user-management', standalone: true, imports: [
637
+ CommonModule,
638
+ FormsModule,
639
+ SharedSettingsModule
640
+ ], template: "<div class=\"user-management-container\">\n <!-- Action Buttons -->\n <div class=\"action-buttons\">\n <button class=\"btn-secondary\" (click)=\"refreshData()\" [disabled]=\"isLoading\">\n <i class=\"fa-solid fa-refresh\" [class.fa-spin]=\"isLoading\"></i>\n Refresh\n </button>\n <button class=\"btn-secondary\" (click)=\"exportUsers()\">\n <i class=\"fa-solid fa-download\"></i>\n Export\n </button>\n <button class=\"btn-primary\" (click)=\"createNewUser()\">\n <i class=\"fa-solid fa-plus\"></i>\n Add User\n </button>\n </div>\n\n <!-- Stats Cards -->\n <div class=\"stats-grid\" style=\"display: flex\">\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-total\">\n <i class=\"fa-solid fa-users\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.totalUsers }}</div>\n <div class=\"stat-label\">Total Users</div>\n </div>\n </div>\n \n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-active\">\n <i class=\"fa-solid fa-user-check\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.activeUsers }}</div>\n <div class=\"stat-label\">Active Users</div>\n </div>\n </div>\n \n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-inactive\">\n <i class=\"fa-solid fa-user-xmark\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.inactiveUsers }}</div>\n <div class=\"stat-label\">Inactive Users</div>\n </div>\n </div>\n \n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-admin\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.adminUsers }}</div>\n <div class=\"stat-label\">Owners</div>\n </div>\n </div>\n </div>\n\n <!-- Filters Section -->\n <div class=\"filters-section\">\n <div class=\"filters-row\">\n <!-- Search -->\n <div class=\"search-container\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input \n type=\"text\" \n class=\"search-input\" \n placeholder=\"Search users by name or email...\"\n (input)=\"onSearchChange($event)\"\n [value]=\"filters$.value.search\"\n />\n </div>\n \n <!-- Status Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">Status</label>\n <div class=\"filter-buttons\">\n <button \n class=\"filter-btn\"\n [class.active]=\"filters$.value.status === 'all'\"\n (click)=\"onStatusFilterChange('all')\"\n >\n All\n </button>\n <button \n class=\"filter-btn\"\n [class.active]=\"filters$.value.status === 'active'\"\n (click)=\"onStatusFilterChange('active')\"\n >\n Active\n </button>\n <button \n class=\"filter-btn\"\n [class.active]=\"filters$.value.status === 'inactive'\"\n (click)=\"onStatusFilterChange('inactive')\"\n >\n Inactive\n </button>\n </div>\n </div>\n \n <!-- Role Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">Role</label>\n <select class=\"filter-select\" (change)=\"onRoleFilterChange($any($event.target).value)\">\n <option value=\"\">All Roles</option>\n @for (role of roles; track role.ID) {\n <option [value]=\"role.ID\">{{ role.Name }}</option>\n }\n </select>\n </div>\n \n <!-- View Toggle -->\n <div class=\"view-toggle\">\n <button \n class=\"view-btn\"\n [class.active]=\"viewMode === 'grid'\"\n (click)=\"viewMode = 'grid'\"\n title=\"Grid View\"\n >\n <i class=\"fa-solid fa-table\"></i>\n </button>\n <button \n class=\"view-btn\"\n [class.active]=\"viewMode === 'cards'\"\n (click)=\"viewMode = 'cards'\"\n title=\"Card View\"\n >\n <i class=\"fa-solid fa-th-large\"></i>\n </button>\n </div>\n </div>\n </div>\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\">\n <div class=\"loading-spinner\">\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n </div>\n <div class=\"loading-text\">Loading users...</div>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-container\">\n <div class=\"error-content\">\n <i class=\"fa-solid fa-exclamation-triangle error-icon\"></i>\n <p class=\"error-message\">{{ error }}</p>\n <button class=\"retry-button\" (click)=\"loadInitialData()\">\n <i class=\"fa-solid fa-refresh\"></i>\n Try Again\n </button>\n </div>\n </div>\n }\n\n <!-- Content Area -->\n @if (!isLoading && !error) {\n <div class=\"content-area\">\n <!-- Grid View -->\n @if (viewMode === 'grid') {\n <div class=\"users-table\">\n <table class=\"modern-table\">\n <thead>\n <tr>\n <th class=\"th-checkbox\">\n <input type=\"checkbox\" class=\"checkbox\" />\n </th>\n <th>User</th>\n <th>Email</th>\n <th>Type</th>\n <th>Status</th>\n <th>Last Updated</th>\n <th class=\"th-actions\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (user of filteredUsers; track user.ID) {\n <tr class=\"table-row\" (click)=\"selectUser(user)\">\n <td class=\"td-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" class=\"checkbox\" />\n </td>\n <td>\n <div class=\"user-cell\">\n <div class=\"user-avatar\">\n {{ getUserInitials(user) }}\n </div>\n <div class=\"user-info\">\n <div class=\"user-name\">{{ user.Name }}</div>\n <div class=\"user-fullname\">\n {{ user.FirstName }} {{ user.LastName }}\n </div>\n </div>\n </div>\n </td>\n <td>{{ user.Email }}</td>\n <td>\n <div class=\"user-type\">\n <i [class]=\"'fa-solid ' + getUserTypeIcon(user)\"></i>\n {{ user.Type }}\n </div>\n </td>\n <td>\n <span class=\"status-badge\" [class]=\"getStatusClass(user)\">\n <i [class]=\"'fa-solid ' + getStatusIcon(user)\"></i>\n {{ user.IsActive ? 'Active' : 'Inactive' }}\n </span>\n </td>\n <td>\n <span class=\"last-login\">\n {{ user.__mj_UpdatedAt ? (user.__mj_UpdatedAt | date:'short') : 'Never' }}\n </span>\n </td>\n <td class=\"td-actions\" (click)=\"$event.stopPropagation()\">\n <button class=\"action-btn\" (click)=\"editUser(user)\" title=\"Edit\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button \n class=\"action-btn\" \n (click)=\"toggleUserStatus(user)\"\n [title]=\"user.IsActive ? 'Deactivate' : 'Activate'\"\n >\n <i [class]=\"user.IsActive ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'\"></i>\n </button>\n <button class=\"action-btn action-btn-danger\" (click)=\"confirmDeleteUser(user)\" title=\"Delete\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n \n @if (filteredUsers.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-users-slash empty-icon\"></i>\n <p class=\"empty-text\">No users found</p>\n <p class=\"empty-subtext\">Try adjusting your filters or add a new user</p>\n </div>\n }\n </div>\n }\n\n <!-- Card View -->\n @if (viewMode === 'cards') {\n <div class=\"users-grid\">\n @for (user of filteredUsers; track user.ID) {\n <div class=\"user-card\" (click)=\"selectUser(user)\">\n <div class=\"card-header\">\n <div class=\"user-avatar-large\">\n {{ getUserInitials(user) }}\n </div>\n <div class=\"card-actions\">\n <button class=\"action-btn\" (click)=\"editUser(user); $event.stopPropagation()\" title=\"Edit\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"action-btn action-btn-danger\" (click)=\"confirmDeleteUser(user); $event.stopPropagation()\" title=\"Delete\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n </div>\n \n <div class=\"card-body\">\n <h3 class=\"user-name\">{{ user.Name }}</h3>\n <p class=\"user-fullname\">{{ user.FirstName }} {{ user.LastName }}</p>\n <p class=\"user-email\">\n <i class=\"fa-solid fa-envelope\"></i>\n {{ user.Email }}\n </p>\n \n <div class=\"card-meta\">\n <div class=\"meta-item\">\n <i [class]=\"'fa-solid ' + getUserTypeIcon(user)\"></i>\n {{ user.Type }}\n </div>\n <span class=\"status-badge\" [class]=\"getStatusClass(user)\">\n <i [class]=\"'fa-solid ' + getStatusIcon(user)\"></i>\n {{ user.IsActive ? 'Active' : 'Inactive' }}\n </span>\n </div>\n \n <div class=\"card-footer\">\n <div class=\"last-login\">\n <i class=\"fa-solid fa-clock\"></i>\n Last updated: {{ user.__mj_UpdatedAt ? (user.__mj_UpdatedAt | date:'short') : 'Never' }}\n </div>\n </div>\n </div>\n </div>\n }\n \n @if (filteredUsers.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-users-slash empty-icon\"></i>\n <p class=\"empty-text\">No users found</p>\n <p class=\"empty-subtext\">Try adjusting your filters or add a new user</p>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Delete Confirmation Dialog -->\n @if (showDeleteConfirm && selectedUser) {\n <div class=\"modal-backdrop\" (click)=\"showDeleteConfirm = false\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">\n <i class=\"fa-solid fa-exclamation-triangle text-danger\"></i>\n Confirm Delete\n </h3>\n <button class=\"modal-close\" (click)=\"showDeleteConfirm = false\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <p>Are you sure you want to delete user <strong>{{ selectedUser.Name }}</strong>?</p>\n <p class=\"text-muted\">This action cannot be undone.</p>\n </div>\n <div class=\"modal-footer\">\n <button class=\"btn-secondary\" (click)=\"showDeleteConfirm = false\">Cancel</button>\n <button class=\"btn-danger\" (click)=\"deleteUser()\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete User\n </button>\n </div>\n </div>\n </div>\n }\n</div>", styles: ["@import '../shared/styles/variables';\n@import '../shared/styles/mixins';\n\n.user-management-container {\n @include scrollable-container;\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n// Action Buttons\n.action-buttons {\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n margin-bottom: 1.5rem;\n\n @media (max-width: 768px) {\n justify-content: center;\n flex-wrap: wrap;\n }\n}\n\n// Buttons\n.btn-primary {\n @include button-base;\n background-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n }\n}\n\n.btn-secondary {\n @include button-base;\n background-color: #ffffff;\n color: #374151;\n border: 1px solid #e5e7eb;\n \n &:hover {\n background-color: #f9fafb;\n border-color: #2196f3;\n color: #2196f3;\n }\n}\n\n.btn-danger {\n @include button-base;\n background-color: #f44336;\n color: white;\n \n &:hover {\n background-color: #d32f2f;\n }\n}\n\n// Stats Grid\n.stats-grid {\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin-bottom: 2rem;\n width: 100%;\n\n @media (max-width: 768px) {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n.stat-card {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n display: flex;\n margin-right: 10px;\n align-items: center;\n gap: 1rem;\n transition: all 0.3s ease;\n min-width: 0; // Prevent grid blowout\n\n &:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n }\n}\n\n.stat-icon {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.5rem;\n\n &-total {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n &-active {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n &-inactive {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n }\n\n &-admin {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n }\n}\n\n.stat-content {\n flex: 1;\n\n .stat-value {\n font-size: 2rem;\n font-weight: 700;\n color: #1f2937;\n line-height: 1;\n }\n\n .stat-label {\n color: #6b7280;\n font-size: 0.875rem;\n margin-top: 0.25rem;\n }\n}\n\n// Filters Section\n.filters-section {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n margin-bottom: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n}\n\n.filters-row {\n display: flex;\n gap: 1.5rem;\n align-items: flex-end;\n flex-wrap: wrap;\n\n @media (max-width: 768px) {\n gap: 1rem;\n }\n}\n\n.search-container {\n flex: 1;\n min-width: 250px;\n position: relative;\n\n .search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: #6b7280;\n font-size: 1rem;\n }\n\n .search-input {\n width: 100%;\n padding: 0.75rem 1rem 0.75rem 2.75rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n transition: all 0.2s;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n }\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n\n .filter-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: #374151;\n }\n\n .filter-buttons {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n }\n\n .filter-btn {\n padding: 0.5rem 1rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n color: #374151;\n }\n\n &.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n }\n\n .filter-select {\n padding: 0.625rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: white;\n font-size: 0.875rem;\n color: #374151;\n cursor: pointer;\n transition: all 0.2s;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n }\n}\n\n.view-toggle {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n\n .view-btn {\n padding: 0.5rem 0.75rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1rem;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n color: #374151;\n }\n\n &.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n }\n}\n\n// Content Area\n.content-area {\n @include scrollable-content;\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n}\n\n// Table View\n.users-table {\n overflow-x: auto;\n max-height: calc(100vh - 450px); // Dynamic height\n overflow-y: auto;\n}\n\n.modern-table {\n width: 100%;\n border-collapse: collapse;\n\n thead {\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n\n th {\n padding: 1rem;\n text-align: left;\n font-size: 0.875rem;\n font-weight: 600;\n color: #374151;\n white-space: nowrap;\n\n &.th-checkbox {\n width: 50px;\n }\n\n &.th-actions {\n text-align: center;\n width: 150px;\n }\n }\n }\n\n tbody {\n tr {\n border-bottom: 1px solid #f3f4f6;\n transition: background-color 0.2s;\n cursor: pointer;\n\n &:hover {\n background-color: #f9fafb;\n }\n }\n\n td {\n padding: 1rem;\n font-size: 0.875rem;\n color: #374151;\n\n &.td-checkbox {\n width: 50px;\n }\n\n &.td-actions {\n text-align: center;\n }\n }\n }\n}\n\n.checkbox {\n width: 18px;\n height: 18px;\n cursor: pointer;\n}\n\n.user-cell {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.user-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 0.875rem;\n}\n\n.user-avatar-large {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 1.5rem;\n margin: 0 auto 1rem;\n}\n\n.user-info {\n .user-name {\n font-weight: 600;\n color: #1f2937;\n }\n\n .user-fullname {\n font-size: 0.75rem;\n color: #6b7280;\n }\n}\n\n.user-type {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n color: #4b5563;\n\n i {\n font-size: 0.875rem;\n }\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.75rem;\n border-radius: 20px;\n font-size: 0.75rem;\n font-weight: 500;\n\n &.status-active {\n background: rgba(76, 175, 80, 0.1);\n color: #388e3c;\n }\n\n &.status-inactive {\n background: rgba(244, 67, 54, 0.1);\n color: #d32f2f;\n }\n\n i {\n font-size: 0.625rem;\n }\n}\n\n.last-login {\n color: #6b7280;\n font-size: 0.875rem;\n}\n\n.action-btn {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1rem;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n background: #f3f4f6;\n color: #2196f3;\n }\n\n &-danger:hover {\n color: #f44336;\n }\n}\n\n// Card View\n.users-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 1.5rem;\n padding: 1.5rem;\n\n @media (max-width: 768px) {\n grid-template-columns: 1fr;\n gap: 1rem;\n padding: 1rem;\n }\n}\n\n.user-card {\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 12px;\n padding: 1.5rem;\n cursor: pointer;\n transition: all 0.3s ease;\n\n &:hover {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n border-color: #2196f3;\n }\n}\n\n.card-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 1rem;\n}\n\n.card-actions {\n display: flex;\n gap: 0.5rem;\n}\n\n.card-body {\n text-align: center;\n\n .user-name {\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.25rem 0;\n }\n\n .user-fullname {\n color: #6b7280;\n margin: 0 0 0.75rem 0;\n }\n\n .user-email {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n color: #4b5563;\n font-size: 0.875rem;\n margin-bottom: 1rem;\n\n i {\n color: #6b7280;\n }\n }\n}\n\n.card-meta {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 1rem;\n padding: 1rem 0;\n border-top: 1px solid #f3f4f6;\n border-bottom: 1px solid #f3f4f6;\n margin-bottom: 1rem;\n\n .meta-item {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n color: #4b5563;\n font-size: 0.875rem;\n }\n}\n\n.card-footer {\n .last-login {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n color: #6b7280;\n font-size: 0.75rem;\n\n i {\n font-size: 0.875rem;\n }\n }\n}\n\n// Empty State\n.empty-state {\n text-align: center;\n padding: 4rem 2rem;\n\n .empty-icon {\n font-size: 4rem;\n color: #e5e7eb;\n margin-bottom: 1rem;\n }\n\n .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: #374151;\n margin: 0 0 0.5rem 0;\n }\n\n .empty-subtext {\n color: #6b7280;\n margin: 0;\n }\n}\n\n// Loading State\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n}\n\n.loading-spinner {\n position: relative;\n width: 60px;\n height: 60px;\n margin-bottom: 1rem;\n\n .spinner-ring {\n position: absolute;\n width: 100%;\n height: 100%;\n border: 3px solid transparent;\n border-radius: 50%;\n animation: spin 1.5s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n\n &:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n }\n\n &:nth-child(2) {\n border-color: transparent #4caf50 transparent transparent;\n animation-delay: -0.3s;\n }\n\n &:nth-child(3) {\n border-color: transparent transparent #ff9800 transparent;\n animation-delay: -0.15s;\n }\n }\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n.loading-text {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n// Error State\n.error-container {\n text-align: center;\n padding: 4rem 2rem;\n\n .error-icon {\n font-size: 3rem;\n color: #f44336;\n margin-bottom: 1rem;\n }\n\n .error-message {\n color: #374151;\n margin-bottom: 1.5rem;\n }\n\n .retry-button {\n @include button-base;\n background-color: #2196f3;\n color: white;\n }\n}\n\n// Modal Styles\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s ease;\n}\n\n.modal-dialog {\n background: white;\n border-radius: 12px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n overflow: hidden;\n animation: slideUp 0.3s ease;\n}\n\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.5rem;\n border-bottom: 1px solid #e5e7eb;\n\n .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0;\n }\n\n .modal-close {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n\n &:hover {\n background: #f3f4f6;\n color: #374151;\n }\n }\n}\n\n.modal-body {\n padding: 1.5rem;\n\n p {\n margin: 0 0 1rem 0;\n color: #374151;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n .text-muted {\n color: #6b7280;\n font-size: 0.875rem;\n }\n}\n\n.modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid #e5e7eb;\n background: #f9fafb;\n}\n\n// Animations\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n// Utility Classes\n.text-danger {\n color: #f44336;\n}"] }]
641
+ }], () => [], null); })();
642
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserManagementComponent, { className: "UserManagementComponent", filePath: "src/lib/user-management/user-management.component.ts", lineNumber: 34 }); })();
643
+ //# sourceMappingURL=user-management.component.js.map