invitation-code-lib 1.0.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.
@@ -0,0 +1,2532 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Component, Injectable, Inject, EventEmitter, Output, Input, InjectionToken, forwardRef, NgModule } from '@angular/core';
3
+ import * as i2 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i1$2 from '@angular/forms';
6
+ import { Validators, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
7
+ import * as i1 from '@angular/common/http';
8
+ import { HttpParams, HttpClientModule } from '@angular/common/http';
9
+ import { RouterModule } from '@angular/router';
10
+ import * as i1$1 from '@angular/material/dialog';
11
+ import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
12
+ import * as i4$1 from '@angular/material/button';
13
+ import { MatButtonModule } from '@angular/material/button';
14
+ import { MatInputModule } from '@angular/material/input';
15
+ import { MatFormFieldModule } from '@angular/material/form-field';
16
+ import { MatSelectModule } from '@angular/material/select';
17
+ import { MatTableModule } from '@angular/material/table';
18
+ import { MatPaginatorModule } from '@angular/material/paginator';
19
+ import { MatSortModule } from '@angular/material/sort';
20
+ import * as i5 from '@angular/material/icon';
21
+ import { MatIconModule } from '@angular/material/icon';
22
+ import { MatTooltipModule } from '@angular/material/tooltip';
23
+ import { MatCardModule } from '@angular/material/card';
24
+ import { MatDatepickerModule } from '@angular/material/datepicker';
25
+ import { MatNativeDateModule } from '@angular/material/core';
26
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
27
+ import { MatSnackBarModule } from '@angular/material/snack-bar';
28
+ import { MatRadioModule } from '@angular/material/radio';
29
+ import * as i4 from '@naniteninja/ionic-lib';
30
+ import { GridModule } from '@naniteninja/ionic-lib';
31
+ import { BehaviorSubject, Subject, Observable } from 'rxjs';
32
+ import { map, tap, takeUntil } from 'rxjs/operators';
33
+
34
+ function CodeManagementComponent_div_3_Template(rf, ctx) { if (rf & 1) {
35
+ i0.ɵɵelementStart(0, "div");
36
+ i0.ɵɵelement(1, "app-invitation-codes");
37
+ i0.ɵɵelementEnd();
38
+ } }
39
+ function CodeManagementComponent_div_4_Template(rf, ctx) { if (rf & 1) {
40
+ i0.ɵɵelementStart(0, "div");
41
+ i0.ɵɵelement(1, "app-waitlist");
42
+ i0.ɵɵelementEnd();
43
+ } }
44
+ class CodeManagementComponent {
45
+ activeTab = 'codes';
46
+ onTabChanged(tab) {
47
+ this.activeTab = tab;
48
+ }
49
+ static ɵfac = function CodeManagementComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CodeManagementComponent)(); };
50
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CodeManagementComponent, selectors: [["app-code-management"]], standalone: false, decls: 5, vars: 2, consts: [[1, "invitation-codes-page", "min-h-screen", "p-10"], [3, "tabChanged"], [4, "ngIf"]], template: function CodeManagementComponent_Template(rf, ctx) { if (rf & 1) {
51
+ i0.ɵɵelementStart(0, "div", 0);
52
+ i0.ɵɵelement(1, "app-stats-overview");
53
+ i0.ɵɵelementStart(2, "app-code-management-header", 1);
54
+ i0.ɵɵlistener("tabChanged", function CodeManagementComponent_Template_app_code_management_header_tabChanged_2_listener($event) { return ctx.onTabChanged($event); });
55
+ i0.ɵɵelementEnd();
56
+ i0.ɵɵtemplate(3, CodeManagementComponent_div_3_Template, 2, 0, "div", 2)(4, CodeManagementComponent_div_4_Template, 2, 0, "div", 2);
57
+ i0.ɵɵelementEnd();
58
+ } if (rf & 2) {
59
+ i0.ɵɵadvance(3);
60
+ i0.ɵɵproperty("ngIf", ctx.activeTab === "codes");
61
+ i0.ɵɵadvance();
62
+ i0.ɵɵproperty("ngIf", ctx.activeTab === "waitlist");
63
+ } }, encapsulation: 2 });
64
+ }
65
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CodeManagementComponent, [{
66
+ type: Component,
67
+ args: [{ selector: 'app-code-management', standalone: false, template: "<div class=\"invitation-codes-page min-h-screen p-10\">\r\n\r\n <app-stats-overview></app-stats-overview>\r\n\r\n <!-- Tab Navigation -->\r\n <app-code-management-header\r\n (tabChanged)=\"onTabChanged($event)\">\r\n </app-code-management-header>\r\n\r\n <!-- Tab Content -->\r\n <div *ngIf=\"activeTab === 'codes'\">\r\n <app-invitation-codes></app-invitation-codes>\r\n </div>\r\n\r\n <div *ngIf=\"activeTab === 'waitlist'\">\r\n <app-waitlist></app-waitlist>\r\n </div>\r\n</div>\r\n" }]
68
+ }], null, null); })();
69
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CodeManagementComponent, { className: "CodeManagementComponent", filePath: "lib/pages/code-management/code-management.component.ts", lineNumber: 9 }); })();
70
+
71
+ const invitationStatuses = [
72
+ { Key: 'account_created', Value: 'Account Created' },
73
+ { Key: 'registration_started', Value: 'Registration Started' },
74
+ { Key: 'pending', Value: 'Pending' },
75
+ { Key: 'revoked', Value: 'Revoked' },
76
+ { Key: 'expired', Value: 'Expired' },
77
+ { Key: 'completed', Value: 'Completed' }
78
+ ];
79
+ const userTypes = [
80
+ { Key: 'premium', Value: 'Premium Member' },
81
+ { Key: 'standard', Value: 'Standard Member' },
82
+ { Key: 'vip', Value: 'VIP Member' }
83
+ ];
84
+ const invitationGridColumns = [
85
+ {
86
+ name: 'code',
87
+ label: 'Code',
88
+ visible: true,
89
+ sortable: true,
90
+ width: 180,
91
+ controlType: 'Text',
92
+ editable: false
93
+ },
94
+ {
95
+ name: 'userType',
96
+ label: 'User Type',
97
+ visible: true,
98
+ sortable: true,
99
+ width: 150,
100
+ controlType: 'Text',
101
+ editable: false
102
+ },
103
+ {
104
+ name: 'status',
105
+ label: 'Status',
106
+ visible: true,
107
+ sortable: true,
108
+ width: 160,
109
+ controlType: 'Text',
110
+ editable: false
111
+ },
112
+ {
113
+ name: 'created',
114
+ label: 'Created',
115
+ visible: true,
116
+ sortable: true,
117
+ width: 180,
118
+ controlType: 'Text',
119
+ editable: false
120
+ },
121
+ {
122
+ name: 'expires',
123
+ label: 'Expires',
124
+ visible: true,
125
+ sortable: true,
126
+ width: 180,
127
+ controlType: 'Text',
128
+ editable: false
129
+ },
130
+ {
131
+ name: 'invitee',
132
+ label: 'Invitee',
133
+ visible: true,
134
+ sortable: true,
135
+ width: 200,
136
+ controlType: 'Text',
137
+ editable: false
138
+ },
139
+ {
140
+ name: 'progress',
141
+ label: 'Progress',
142
+ visible: true,
143
+ sortable: false,
144
+ width: 150,
145
+ controlType: 'Text',
146
+ editable: false
147
+ }
148
+ ];
149
+
150
+ class ApiUrlBuilder {
151
+ config;
152
+ constructor(config) {
153
+ this.config = config;
154
+ }
155
+ buildUrl(endpoint) {
156
+ const baseUrl = this.config.apiUrl.endsWith('/')
157
+ ? this.config.apiUrl.slice(0, -1)
158
+ : this.config.apiUrl;
159
+ const apiPrefix = this.config.apiSuffix
160
+ ? `/${this.config.apiSuffix}`
161
+ : '';
162
+ return `${baseUrl}${apiPrefix}/${endpoint}`;
163
+ }
164
+ static ɵfac = function ApiUrlBuilder_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ApiUrlBuilder)(i0.ɵɵinject(INVITATION_CODE_CONFIG)); };
165
+ static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ApiUrlBuilder, factory: ApiUrlBuilder.ɵfac, providedIn: 'root' });
166
+ }
167
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ApiUrlBuilder, [{
168
+ type: Injectable,
169
+ args: [{
170
+ providedIn: 'root'
171
+ }]
172
+ }], () => [{ type: undefined, decorators: [{
173
+ type: Inject,
174
+ args: [INVITATION_CODE_CONFIG]
175
+ }] }], null); })();
176
+
177
+ class InvitationCodeService {
178
+ http;
179
+ config;
180
+ apiUrlBuilder;
181
+ refreshGrid$ = new BehaviorSubject(undefined);
182
+ constructor(http, config) {
183
+ this.http = http;
184
+ this.config = config;
185
+ this.apiUrlBuilder = new ApiUrlBuilder(config);
186
+ }
187
+ get refreshTrigger$() {
188
+ return this.refreshGrid$.asObservable();
189
+ }
190
+ triggerRefresh() {
191
+ this.refreshGrid$.next();
192
+ }
193
+ getInvitationCodes(page = 1, limit = 10, filters, sortField, sortOrder, search) {
194
+ let params = new HttpParams()
195
+ .set('page', page.toString())
196
+ .set('limit', limit.toString());
197
+ if (filters && filters.length > 0) {
198
+ params = params.set('filters', JSON.stringify(filters));
199
+ }
200
+ if (sortField) {
201
+ params = params.set('sortField', sortField);
202
+ }
203
+ if (sortOrder) {
204
+ params = params.set('sortOrder', sortOrder);
205
+ }
206
+ if (search) {
207
+ params = params.set('search', search);
208
+ }
209
+ return this.http.get(this.apiUrlBuilder.buildUrl('invitation-codes'), { params });
210
+ }
211
+ getWaitlistMembers(page = 1, limit = 10, filters, sortField, sortOrder, search) {
212
+ let params = new HttpParams()
213
+ .set('page', page.toString())
214
+ .set('limit', limit.toString());
215
+ // Add search parameter
216
+ if (search) {
217
+ params = params.set('search', search);
218
+ }
219
+ // Handle user type filter
220
+ if (filters && filters.length > 0) {
221
+ const userTypeFilter = this.extractUserTypeFilter(filters);
222
+ if (userTypeFilter) {
223
+ params = params.set('userType', userTypeFilter);
224
+ }
225
+ }
226
+ // Handle status filter
227
+ if (filters && filters.length > 0) {
228
+ const statusFilter = this.extractStatusFilter(filters);
229
+ if (statusFilter) {
230
+ params = params.set('status', statusFilter);
231
+ }
232
+ }
233
+ return this.http.get(this.apiUrlBuilder.buildUrl('waitlisted-users'), { params }).pipe(map(response => {
234
+ if (!response.success) {
235
+ return { data: [], count: 0 };
236
+ }
237
+ // Transform response to match expected format
238
+ const mappedData = response.data.map((user) => ({
239
+ id: user.id,
240
+ name: user.name,
241
+ email: user.email,
242
+ userType: this.mapUserType(user.userType),
243
+ priority: 'normal',
244
+ joined: new Date(user.waitlistJoinedAt || user.createdAt),
245
+ waitTime: this.calculateWaitTime(user.waitlistJoinedAt),
246
+ notes: '',
247
+ status: user.status === 'waitlist_invited' ? 'invited' : user.status,
248
+ convertedAt: user.convertedAt,
249
+ convertedToCodeId: user.convertedToCodeId
250
+ }));
251
+ return {
252
+ data: mappedData,
253
+ count: response.meta?.total || response.data.length
254
+ };
255
+ }));
256
+ }
257
+ extractUserTypeFilter(filters) {
258
+ for (const filter of filters) {
259
+ if (filter.publicFieldName === 'userType') {
260
+ if (filter.operatorType === 'Equals' || filter.operatorType === 'AnyOf') {
261
+ const value = filter.values[0];
262
+ const typeMap = {
263
+ 'premium': 'matcher',
264
+ 'standard': 'unmatched',
265
+ 'vip': 'vip'
266
+ };
267
+ return typeMap[value] || value;
268
+ }
269
+ }
270
+ }
271
+ return null;
272
+ }
273
+ extractStatusFilter(filters) {
274
+ for (const filter of filters) {
275
+ if (filter.publicFieldName === 'status') {
276
+ if (filter.operatorType === 'Equals' || filter.operatorType === 'AnyOf') {
277
+ const value = filter.values[0];
278
+ if (value === 'invited') {
279
+ return 'waitlist_invited';
280
+ }
281
+ return value;
282
+ }
283
+ }
284
+ }
285
+ return null;
286
+ }
287
+ mapUserType(userType) {
288
+ const typeLower = userType.toLowerCase();
289
+ if (typeLower.includes('matcher') || typeLower.includes('premium')) {
290
+ return 'premium';
291
+ }
292
+ else if (typeLower.includes('vip')) {
293
+ return 'vip';
294
+ }
295
+ else {
296
+ return 'standard';
297
+ }
298
+ }
299
+ calculateWaitTime(joinedDate) {
300
+ if (!joinedDate)
301
+ return 0;
302
+ const joined = new Date(joinedDate);
303
+ const now = new Date();
304
+ const diffTime = Math.abs(now.getTime() - joined.getTime());
305
+ return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
306
+ }
307
+ getStats() {
308
+ return this.http.get(this.apiUrlBuilder.buildUrl('invitation-codes/stats')).pipe(map(stats => [
309
+ {
310
+ title: 'Total Codes',
311
+ value: stats.total || 0,
312
+ icon: 'qr_code',
313
+ color: 'bg-blue-500'
314
+ },
315
+ {
316
+ title: 'Pending',
317
+ value: stats.pending || 0,
318
+ icon: 'schedule',
319
+ color: 'bg-yellow-500'
320
+ },
321
+ {
322
+ title: 'Completed',
323
+ value: stats.completed || 0,
324
+ icon: 'check_circle',
325
+ color: 'bg-green-500'
326
+ },
327
+ {
328
+ title: 'Revoked',
329
+ value: stats.revoked || 0,
330
+ icon: 'cancel',
331
+ color: 'bg-red-500'
332
+ },
333
+ {
334
+ title: 'Active',
335
+ value: stats.active || 0,
336
+ icon: 'play_arrow',
337
+ color: 'bg-purple-500'
338
+ }
339
+ ]));
340
+ }
341
+ createInvitationCode(data) {
342
+ return this.http.post(this.apiUrlBuilder.buildUrl('invitation-codes'), data).pipe(tap(() => this.triggerRefresh()));
343
+ }
344
+ generateCode(data) {
345
+ const requestData = {
346
+ name: data.name,
347
+ maxUses: data.maxUses,
348
+ expiryDate: data.expiryDate || data.expires,
349
+ accessLevel: data.accessLevel,
350
+ userType: data.userType,
351
+ email: data.email
352
+ };
353
+ return this.http.post(this.apiUrlBuilder.buildUrl('invitation-codes/generate'), requestData).pipe(tap(() => this.triggerRefresh()));
354
+ }
355
+ revokeInvitationCode(codeId) {
356
+ return this.http.put(this.apiUrlBuilder.buildUrl(`invitation-codes/${codeId}/revoke`), {}).pipe(tap(() => this.triggerRefresh()));
357
+ }
358
+ deleteInvitationCode(codeId) {
359
+ return this.http.delete(this.apiUrlBuilder.buildUrl(`invitation-codes/${codeId}`)).pipe(tap(() => this.triggerRefresh()));
360
+ }
361
+ bulkGenerateFromWaitlist(data) {
362
+ return this.http.post(this.apiUrlBuilder.buildUrl('waitlisted-users/bulk-invite'), {
363
+ userIds: data.waitlistMemberIds,
364
+ expiryDays: data.expiryDays,
365
+ accessLevel: data.accessLevel
366
+ }).pipe(map(response => {
367
+ if (!response.success) {
368
+ throw new Error(response.error || 'Failed to create invitations');
369
+ }
370
+ const successfulResults = response.data?.results?.filter((r) => r.success) || [];
371
+ return successfulResults.map((r) => r.data?.invitation || {});
372
+ }), tap(() => this.triggerRefresh()));
373
+ }
374
+ static ɵfac = function InvitationCodeService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || InvitationCodeService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(INVITATION_CODE_CONFIG)); };
375
+ static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: InvitationCodeService, factory: InvitationCodeService.ɵfac, providedIn: 'root' });
376
+ }
377
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(InvitationCodeService, [{
378
+ type: Injectable,
379
+ args: [{
380
+ providedIn: 'root'
381
+ }]
382
+ }], () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
383
+ type: Inject,
384
+ args: [INVITATION_CODE_CONFIG]
385
+ }] }], null); })();
386
+
387
+ class InvitationGridService {
388
+ invitationCodeService;
389
+ destroy$ = new Subject();
390
+ constructor(invitationCodeService) {
391
+ this.invitationCodeService = invitationCodeService;
392
+ }
393
+ getInvitationCodes(event) {
394
+ const page = Math.floor(event.from / event.size) + 1;
395
+ const limit = event.size;
396
+ return this.invitationCodeService.getInvitationCodes(page, limit, event.userFilters, event.sortField, event.sortDirection === 'Ascending' ? 'asc' : 'desc', event.searchString).pipe(map(response => {
397
+ const gridRows = response.data.map(item => {
398
+ const gridItem = {
399
+ id: item.id,
400
+ code: item.code,
401
+ userType: item.userType,
402
+ status: item.status,
403
+ created: item.createdAt,
404
+ expires: item.expires || new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
405
+ invitee: item.email || 'Anyone',
406
+ progress: this.getProgressText(item),
407
+ name: item.name,
408
+ createdAt: item.createdAt,
409
+ updatedAt: item.updatedAt,
410
+ email: item.email,
411
+ usedBy: item.usedBy,
412
+ usedAt: item.usedAt,
413
+ revokedAt: item.revokedAt,
414
+ maxUses: item.maxUses,
415
+ currentUses: item.currentUses,
416
+ accessLevel: item.accessLevel,
417
+ notes: item.notes,
418
+ waitlistMemberId: item.waitlistMemberId
419
+ };
420
+ return {
421
+ id: item.id,
422
+ data: gridItem,
423
+ rowMenuItems: this.createActionMenu(gridItem),
424
+ hasEditPermissions: true,
425
+ hasDeletePermissions: true,
426
+ displayValues: this.createDisplayValues(gridItem)
427
+ };
428
+ });
429
+ return { data: gridRows, count: response.count };
430
+ }));
431
+ }
432
+ createDisplayValues(item) {
433
+ return {
434
+ code: item.code,
435
+ userType: this.getUserTypeDisplay(item.userType),
436
+ status: this.getStatusDisplay(item.status),
437
+ created: this.formatDate(item.created),
438
+ expires: item.expires ? this.formatDate(item.expires) : 'Never',
439
+ invitee: item.email || 'Anyone',
440
+ progress: item.progress
441
+ };
442
+ }
443
+ formatDate(date) {
444
+ if (!date)
445
+ return 'N/A';
446
+ const d = new Date(date);
447
+ return isNaN(d.getTime()) ? 'Invalid Date' : d.toLocaleDateString('en-US', {
448
+ year: 'numeric',
449
+ month: 'short',
450
+ day: 'numeric',
451
+ hour: '2-digit',
452
+ minute: '2-digit'
453
+ });
454
+ }
455
+ getUserTypeDisplay(userType) {
456
+ const userTypeMap = {
457
+ 'premium': 'Premium Member',
458
+ 'standard': 'Standard Member',
459
+ 'vip': 'VIP Member'
460
+ };
461
+ return userTypeMap[userType] || userType;
462
+ }
463
+ getStatusDisplay(status) {
464
+ const statusMap = {
465
+ 'account_created': 'Account Created',
466
+ 'registration_started': 'Registration Started',
467
+ 'pending': 'Pending',
468
+ 'revoked': 'Revoked',
469
+ 'expired': 'Expired',
470
+ 'completed': 'Completed',
471
+ 'deleted': 'Deleted'
472
+ };
473
+ return statusMap[status] || status;
474
+ }
475
+ getProgressText(item) {
476
+ if (item.status === 'account_created' || item.status === 'completed') {
477
+ return 'Account created\nSuccessfully onboarded';
478
+ }
479
+ else if (item.status === 'registration_started') {
480
+ return 'In progress...';
481
+ }
482
+ else if ('usedAt' in item && item.usedAt) {
483
+ return `Used on ${this.formatDate(item.usedAt)}`;
484
+ }
485
+ return '';
486
+ }
487
+ createActionMenu(item) {
488
+ const menuItems = [
489
+ {
490
+ label: 'Copy Code',
491
+ icon: 'pi pi-copy',
492
+ command: () => this.copyCode(item)
493
+ }
494
+ ];
495
+ if (item.status !== 'revoked' && item.status !== 'expired' && item.status !== 'completed') {
496
+ menuItems.push({
497
+ label: 'Revoke Code',
498
+ icon: 'pi pi-times',
499
+ command: () => this.revokeCode(item)
500
+ });
501
+ }
502
+ if (item.status !== 'deleted') {
503
+ menuItems.push({
504
+ label: 'Delete',
505
+ icon: 'pi pi-trash',
506
+ command: () => this.deleteCode(item)
507
+ });
508
+ }
509
+ else {
510
+ menuItems.push({
511
+ label: 'Restore',
512
+ icon: 'pi pi-refresh',
513
+ command: () => this.restoreCode(item)
514
+ });
515
+ }
516
+ return menuItems;
517
+ }
518
+ copyCode(item) {
519
+ navigator.clipboard.writeText(item.code).then(() => {
520
+ alert(`Code "${item.code}" copied to clipboard!`);
521
+ }).catch(err => {
522
+ const textArea = document.createElement('textarea');
523
+ textArea.value = item.code;
524
+ document.body.appendChild(textArea);
525
+ textArea.select();
526
+ document.execCommand('copy');
527
+ document.body.removeChild(textArea);
528
+ alert(`Code "${item.code}" copied to clipboard!`);
529
+ });
530
+ }
531
+ revokeCode(item) {
532
+ if (confirm(`Are you sure you want to revoke code "${item.code}"?`)) {
533
+ this.invitationCodeService.revokeInvitationCode(item.id).subscribe({
534
+ next: () => {
535
+ alert(`Code "${item.code}" has been revoked!`);
536
+ },
537
+ error: (error) => {
538
+ alert(`Failed to revoke code: ${error.message}`);
539
+ }
540
+ });
541
+ }
542
+ }
543
+ deleteCode(item) {
544
+ if (confirm(`Are you sure you want to delete code "${item.code}"? This will soft delete it (mark as deleted).`)) {
545
+ this.invitationCodeService.deleteInvitationCode(item.id).subscribe({
546
+ next: () => {
547
+ alert(`Code "${item.code}" has been deleted!`);
548
+ },
549
+ error: (error) => {
550
+ alert(`Failed to delete code: ${error.message}`);
551
+ }
552
+ });
553
+ }
554
+ }
555
+ restoreCode(item) {
556
+ if (confirm(`Are you sure you want to restore code "${item.code}"?`)) {
557
+ alert('Restore functionality to be implemented');
558
+ }
559
+ }
560
+ ngOnDestroy() {
561
+ this.destroy$.next();
562
+ this.destroy$.complete();
563
+ }
564
+ static ɵfac = function InvitationGridService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || InvitationGridService)(i0.ɵɵinject(InvitationCodeService)); };
565
+ static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: InvitationGridService, factory: InvitationGridService.ɵfac, providedIn: 'root' });
566
+ }
567
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(InvitationGridService, [{
568
+ type: Injectable,
569
+ args: [{
570
+ providedIn: 'root'
571
+ }]
572
+ }], () => [{ type: InvitationCodeService }], null); })();
573
+
574
+ function InvitationCodesComponent_button_11_Template(rf, ctx) { if (rf & 1) {
575
+ const _r1 = i0.ɵɵgetCurrentView();
576
+ i0.ɵɵelementStart(0, "button", 12);
577
+ i0.ɵɵlistener("click", function InvitationCodesComponent_button_11_Template_button_click_0_listener() { const filter_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.setFilter(filter_r2)); });
578
+ i0.ɵɵtext(1);
579
+ i0.ɵɵelementEnd();
580
+ } if (rf & 2) {
581
+ const filter_r2 = ctx.$implicit;
582
+ const ctx_r2 = i0.ɵɵnextContext();
583
+ i0.ɵɵclassMap(ctx_r2.activeFilter === filter_r2 ? "selected-filter px-4 py-2 text-sm font-medium transition-colors" : "unselected-filter px-4 py-2 text-sm font-medium transition-colors");
584
+ i0.ɵɵadvance();
585
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getFilterDisplayName(filter_r2), " ");
586
+ } }
587
+ class InvitationCodesComponent {
588
+ invitationGridService;
589
+ invitationCodeService;
590
+ gridData = [];
591
+ isLoading = false;
592
+ totalRecords = 0;
593
+ rowsPerPage = 10;
594
+ rowsPerPageOptions = [5, 10, 25, 50];
595
+ sortField = 'created';
596
+ sortOrder = 'Descending';
597
+ columns = invitationGridColumns;
598
+ activeFilter = 'all';
599
+ filters = ['all', 'pending', 'active', 'inactive', 'deleted'];
600
+ destroy$ = new Subject();
601
+ constructor(invitationGridService, invitationCodeService) {
602
+ this.invitationGridService = invitationGridService;
603
+ this.invitationCodeService = invitationCodeService;
604
+ }
605
+ ngOnInit() {
606
+ this.loadGridData();
607
+ this.subscribeToAutoRefresh();
608
+ }
609
+ ngOnDestroy() {
610
+ this.destroy$.next();
611
+ this.destroy$.complete();
612
+ }
613
+ subscribeToAutoRefresh() {
614
+ this.invitationCodeService.refreshTrigger$
615
+ .pipe(takeUntil(this.destroy$))
616
+ .subscribe(() => {
617
+ this.loadGridData();
618
+ });
619
+ }
620
+ loadGridData() {
621
+ const request = {
622
+ from: 0,
623
+ size: this.rowsPerPage,
624
+ sortField: this.sortField,
625
+ sortDirection: this.sortOrder,
626
+ searchString: '',
627
+ userFilters: this.getUserFiltersForActiveFilter()
628
+ };
629
+ this.isLoading = true;
630
+ this.invitationGridService.getInvitationCodes(request).subscribe({
631
+ next: (response) => {
632
+ this.gridData = response.data;
633
+ this.totalRecords = response.count;
634
+ this.isLoading = false;
635
+ },
636
+ error: (error) => {
637
+ this.isLoading = false;
638
+ }
639
+ });
640
+ }
641
+ onLazyLoad(event) {
642
+ this.isLoading = true;
643
+ this.invitationGridService.getInvitationCodes(event).subscribe({
644
+ next: (response) => {
645
+ this.gridData = response.data;
646
+ this.totalRecords = response.count;
647
+ this.isLoading = false;
648
+ },
649
+ error: (error) => {
650
+ this.isLoading = false;
651
+ }
652
+ });
653
+ }
654
+ setFilter(filter) {
655
+ this.activeFilter = filter;
656
+ this.applyFilter();
657
+ }
658
+ applyFilter() {
659
+ const request = {
660
+ from: 0,
661
+ size: this.rowsPerPage,
662
+ sortField: this.sortField,
663
+ sortDirection: this.sortOrder,
664
+ searchString: '',
665
+ userFilters: this.getUserFiltersForActiveFilter()
666
+ };
667
+ this.isLoading = true;
668
+ this.invitationGridService.getInvitationCodes(request).subscribe({
669
+ next: (response) => {
670
+ this.gridData = response.data;
671
+ this.totalRecords = response.count;
672
+ this.isLoading = false;
673
+ },
674
+ error: (error) => {
675
+ this.isLoading = false;
676
+ }
677
+ });
678
+ }
679
+ getUserFiltersForActiveFilter() {
680
+ switch (this.activeFilter) {
681
+ case 'pending':
682
+ return [{
683
+ publicFieldName: 'status',
684
+ operatorType: 'Equals',
685
+ values: ['pending']
686
+ }];
687
+ case 'active':
688
+ return [{
689
+ publicFieldName: 'status',
690
+ operatorType: 'AnyOf',
691
+ values: ['account_created', 'registration_started']
692
+ }];
693
+ case 'inactive':
694
+ return [{
695
+ publicFieldName: 'status',
696
+ operatorType: 'AnyOf',
697
+ values: ['revoked', 'expired']
698
+ }];
699
+ case 'deleted':
700
+ return [{
701
+ publicFieldName: 'status',
702
+ operatorType: 'Equals',
703
+ values: ['deleted']
704
+ }];
705
+ default:
706
+ return [];
707
+ }
708
+ }
709
+ getFilterDisplayName(filter) {
710
+ const displayNames = {
711
+ 'all': 'All Codes',
712
+ 'pending': 'Pending',
713
+ 'active': 'Active',
714
+ 'inactive': 'Inactive',
715
+ 'deleted': 'Deleted'
716
+ };
717
+ return displayNames[filter];
718
+ }
719
+ onActionButtonClicked(event) {
720
+ }
721
+ onCellClicked(event) {
722
+ }
723
+ static ɵfac = function InvitationCodesComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || InvitationCodesComponent)(i0.ɵɵdirectiveInject(InvitationGridService), i0.ɵɵdirectiveInject(InvitationCodeService)); };
724
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: InvitationCodesComponent, selectors: [["app-invitation-codes"]], standalone: false, decls: 14, vars: 17, consts: [[1, "main-grid-section", "p-6"], [1, "code-management-header", "mb-6", "p-3"], [1, "flex", "flex-col", "lg:flex-row", "lg:items-center", "lg:justify-between"], [1, "mb-4", "lg:mb-0"], [1, "text-xl", "font-semibold", "text-white", "mb-2"], [1, "text-gray-400", "text-sm"], [1, "filter-tabs", "mb-6"], [1, "filter-container", "p-1.5", "bg-gray-800", "border", "border-gray-700", "rounded-xl", "w-fit"], [1, "flex", "space-x-0.5"], [3, "class", "click", 4, "ngFor", "ngForOf"], [1, "grid-placeholder", "bg-gray-800", "rounded-lg", "border", "border-gray-700"], [1, "dark-theme-grid", "w-full", 3, "lazyLoad", "cellClicked", "data", "columns", "isLoading", "totalRecords", "rowsPerPage", "rowsPerPageOptions", "sortField", "sortOrder", "enableSelection", "enableCreate", "enableRefresh", "enableTrash", "enableGridFilters", "hideToolbar", "hideSettings", "hideRowMenu"], [3, "click"]], template: function InvitationCodesComponent_Template(rf, ctx) { if (rf & 1) {
725
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3)(4, "h3", 4);
726
+ i0.ɵɵtext(5, "Invitation Codes");
727
+ i0.ɵɵelementEnd();
728
+ i0.ɵɵelementStart(6, "p", 5);
729
+ i0.ɵɵtext(7, " View and manage all invitation codes. Codes are one-time use and bypass user type limits. ");
730
+ i0.ɵɵelementEnd()()()();
731
+ i0.ɵɵelementStart(8, "div", 6)(9, "div", 7)(10, "div", 8);
732
+ i0.ɵɵtemplate(11, InvitationCodesComponent_button_11_Template, 2, 3, "button", 9);
733
+ i0.ɵɵelementEnd()()();
734
+ i0.ɵɵelementStart(12, "div", 10)(13, "lib-grid", 11);
735
+ i0.ɵɵlistener("lazyLoad", function InvitationCodesComponent_Template_lib_grid_lazyLoad_13_listener($event) { return ctx.onLazyLoad($event); })("cellClicked", function InvitationCodesComponent_Template_lib_grid_cellClicked_13_listener($event) { return ctx.onCellClicked($event); });
736
+ i0.ɵɵelementEnd()()();
737
+ } if (rf & 2) {
738
+ i0.ɵɵadvance(11);
739
+ i0.ɵɵproperty("ngForOf", ctx.filters);
740
+ i0.ɵɵadvance(2);
741
+ i0.ɵɵproperty("data", ctx.gridData)("columns", ctx.columns)("isLoading", ctx.isLoading)("totalRecords", ctx.totalRecords)("rowsPerPage", ctx.rowsPerPage)("rowsPerPageOptions", ctx.rowsPerPageOptions)("sortField", ctx.sortField)("sortOrder", ctx.sortOrder)("enableSelection", false)("enableCreate", false)("enableRefresh", false)("enableTrash", false)("enableGridFilters", false)("hideToolbar", true)("hideSettings", true)("hideRowMenu", false);
742
+ } }, dependencies: [i2.NgForOf, i4.GridComponent], styles: [".main-grid-section[_ngcontent-%COMP%]{border:2px solid #423D48;border-radius:10px;margin-top:35px;background:#29252d}[_nghost-%COMP%] .grid-cell-text{position:relative!important;min-height:48px!important;display:flex!important;align-items:center!important;transition:all .2s ease!important}[_nghost-%COMP%] th.grid-cell:nth-of-type(2) .grid-cell-text:before{content:\"Code\"!important}[_nghost-%COMP%] th.grid-cell:nth-of-type(3) .grid-cell-text:before{content:\"User Type\"!important}[_nghost-%COMP%] th.grid-cell:nth-of-type(4) .grid-cell-text:before{content:\"Status\"!important}[_nghost-%COMP%] th.grid-cell:nth-of-type(5) .grid-cell-text:before{content:\"Created At\"!important}[_nghost-%COMP%] th.grid-cell:nth-of-type(6) .grid-cell-text:before{content:\"Expire\"!important}[_nghost-%COMP%] th.grid-cell:nth-of-type(7) .grid-cell-text:before{content:\"Invitee\"!important}[_nghost-%COMP%] th.grid-cell:nth-of-type(8) .grid-cell-text:before{content:\"Progress\"!important}[_nghost-%COMP%] .grid-cell-text:before{color:#fff!important;font-weight:400!important;font-size:14px!important;font-family:Roboto,sans-serif!important;z-index:10!important;transition:color .2s ease!important}[_nghost-%COMP%] th.grid-cell:hover .grid-cell-text:before{color:#000!important}[_nghost-%COMP%] th.grid-cell .p-datatable-column-sorted .grid-cell-text:before, [_nghost-%COMP%] th.grid-cell .grid-cell-text.p-datatable-column-sorted:before, [_nghost-%COMP%] th.grid-cell[aria-sort] .grid-cell-text:before{color:#000!important}[_nghost-%COMP%] th.grid-cell:hover{transition:background-color .2s ease!important}[_nghost-%COMP%] .grid-cell-text .ng-star-inserted{margin-left:auto!important;margin-right:8px!important;transition:filter .2s ease!important}[_nghost-%COMP%] .p-button-icon{display:none!important}[_nghost-%COMP%] .filter-toolbar-top-container{display:none!important;height:0!important;min-height:0!important;padding:0!important;margin:0!important;border:none!important;visibility:hidden!important;opacity:0!important}[_nghost-%COMP%] .grid-row-menu-button, [_nghost-%COMP%] [alignfrozen=left]{padding:0 40px 0 0!important;text-align:center!important;vertical-align:middle!important}[_nghost-%COMP%] .grid-row-menu-button button, [_nghost-%COMP%] [alignfrozen=left] button{all:initial!important;width:32px!important;height:32px!important;min-width:32px!important;min-height:32px!important;display:inline-block!important;position:relative!important;cursor:pointer!important;margin:0 auto!important;border:none!important;background:none!important;padding:0!important;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDQgMTYiIGZpbGw9IiM5Y2EzYWYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjIiLz48Y2lyY2xlIGN4PSIyIiBjeT0iOCIgcj0iMiIvPjxjaXJjbGUgY3g9IjIiIGN5PSIxNCIgcj0iMiIvPjwvc3ZnPg==)!important;background-repeat:no-repeat!important;background-position:center!important;background-size:4px 16px!important;border-radius:6px!important}[_nghost-%COMP%] .grid-row-menu-button button:hover, [_nghost-%COMP%] [alignfrozen=left] button:hover{background-color:#4b5563!important;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDQgMTYiIGZpbGw9IiM5Y2EzYWYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjIiLz48Y2lyY2xlIGN4PSIyIiBjeT0iOCIgcj0iMiIvPjxjaXJjbGUgY3g9IjIiIGN5PSIxNCIgcj0iMiIvPjwvc3ZnPg==)!important}[_nghost-%COMP%] .grid-row-menu-button button i, [_nghost-%COMP%] [alignfrozen=left] button i, [_nghost-%COMP%] .pi-ellipsis-v{display:none!important;width:0!important;height:0!important;font-size:0!important;visibility:hidden!important;opacity:0!important}.dark-theme-grid[_ngcontent-%COMP%] .p-datatable[_ngcontent-%COMP%]{justify-content:center;align-items:center}.dark-theme-grid[_ngcontent-%COMP%] .p-menu-list[_ngcontent-%COMP%]{background:#fff!important}.filter-container[_ngcontent-%COMP%]{position:relative;display:inline-block;border:2px solid #423D48;padding:3px;border-radius:20px}.filter-container[_ngcontent-%COMP%]:before{content:\"\";position:absolute;inset:1.5px;background:transparent;border-radius:20px;z-index:0;transition:all .2s ease}.filter-container[_ngcontent-%COMP%] .flex[_ngcontent-%COMP%]{position:relative;z-index:1}.filter-container[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{position:relative;z-index:2;min-width:80px;all:unset;cursor:pointer;text-align:center;padding:.5rem 1rem;border-radius:16px;font-size:.875rem;font-weight:500;transition:all .2s ease}.filter-container[_ngcontent-%COMP%] button.selected-filter[_ngcontent-%COMP%]{background-color:#374151;color:#fff;border:1px solid #4b5563;box-shadow:0 1px 2px #0000001a}.filter-container[_ngcontent-%COMP%] button.unselected-filter[_ngcontent-%COMP%]{background-color:transparent;color:#d1d5db;border:1px solid transparent}.filter-container[_ngcontent-%COMP%] button.unselected-filter[_ngcontent-%COMP%]:hover{background-color:#4b556333;color:#fff}"] });
743
+ }
744
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(InvitationCodesComponent, [{
745
+ type: Component,
746
+ args: [{ selector: 'app-invitation-codes', standalone: false, template: "\r\n <div class=\"main-grid-section p-6\">\r\n <!-- Header Section -->\r\n <div class=\"code-management-header mb-6 p-3\">\r\n <div class=\"flex flex-col lg:flex-row lg:items-center lg:justify-between\">\r\n <div class=\"mb-4 lg:mb-0\">\r\n <h3 class=\"text-xl font-semibold text-white mb-2\">Invitation Codes</h3>\r\n <p class=\"text-gray-400 text-sm\">\r\n View and manage all invitation codes. Codes are one-time use and bypass user type limits.\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filter Tabs -->\r\n <!-- Filter Tabs -->\r\n<div class=\"filter-tabs mb-6\">\r\n <div class=\"filter-container p-1.5 bg-gray-800 border border-gray-700 rounded-xl w-fit\">\r\n <div class=\"flex space-x-0.5\">\r\n <button\r\n *ngFor=\"let filter of filters\"\r\n (click)=\"setFilter(filter)\"\r\n [class]=\"activeFilter === filter\r\n ? 'selected-filter px-4 py-2 text-sm font-medium transition-colors'\r\n : 'unselected-filter px-4 py-2 text-sm font-medium transition-colors'\">\r\n {{ getFilterDisplayName(filter) }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n <!-- Grid Section -->\r\n <div class=\"grid-placeholder bg-gray-800 rounded-lg border border-gray-700\">\r\n <lib-grid\r\n [data]=\"gridData\"\r\n [columns]=\"columns\"\r\n [isLoading]=\"isLoading\"\r\n [totalRecords]=\"totalRecords\"\r\n [rowsPerPage]=\"rowsPerPage\"\r\n [rowsPerPageOptions]=\"rowsPerPageOptions\"\r\n [sortField]=\"sortField\"\r\n [sortOrder]=\"sortOrder\"\r\n [enableSelection]=\"false\"\r\n [enableCreate]=\"false\"\r\n [enableRefresh]=\"false\"\r\n [enableTrash]=\"false\"\r\n [enableGridFilters]=\"false\"\r\n [hideToolbar]=\"true\"\r\n [hideSettings]=\"true\"\r\n [hideRowMenu]=\"false\"\r\n (lazyLoad)=\"onLazyLoad($event)\"\r\n (cellClicked)=\"onCellClicked($event)\"\r\n class=\"dark-theme-grid w-full\">\r\n </lib-grid>\r\n </div>\r\n </div>\r\n\r\n", styles: [".main-grid-section{border:2px solid #423D48;border-radius:10px;margin-top:35px;background:#29252d}:host ::ng-deep .grid-cell-text{position:relative!important;min-height:48px!important;display:flex!important;align-items:center!important;transition:all .2s ease!important}:host ::ng-deep th.grid-cell:nth-of-type(2) .grid-cell-text:before{content:\"Code\"!important}:host ::ng-deep th.grid-cell:nth-of-type(3) .grid-cell-text:before{content:\"User Type\"!important}:host ::ng-deep th.grid-cell:nth-of-type(4) .grid-cell-text:before{content:\"Status\"!important}:host ::ng-deep th.grid-cell:nth-of-type(5) .grid-cell-text:before{content:\"Created At\"!important}:host ::ng-deep th.grid-cell:nth-of-type(6) .grid-cell-text:before{content:\"Expire\"!important}:host ::ng-deep th.grid-cell:nth-of-type(7) .grid-cell-text:before{content:\"Invitee\"!important}:host ::ng-deep th.grid-cell:nth-of-type(8) .grid-cell-text:before{content:\"Progress\"!important}:host ::ng-deep .grid-cell-text:before{color:#fff!important;font-weight:400!important;font-size:14px!important;font-family:Roboto,sans-serif!important;z-index:10!important;transition:color .2s ease!important}:host ::ng-deep th.grid-cell:hover .grid-cell-text:before{color:#000!important}:host ::ng-deep th.grid-cell .p-datatable-column-sorted .grid-cell-text:before,:host ::ng-deep th.grid-cell .grid-cell-text.p-datatable-column-sorted:before,:host ::ng-deep th.grid-cell[aria-sort] .grid-cell-text:before{color:#000!important}:host ::ng-deep th.grid-cell:hover{transition:background-color .2s ease!important}:host ::ng-deep .grid-cell-text .ng-star-inserted{margin-left:auto!important;margin-right:8px!important;transition:filter .2s ease!important}:host ::ng-deep .p-button-icon{display:none!important}:host ::ng-deep .filter-toolbar-top-container{display:none!important;height:0!important;min-height:0!important;padding:0!important;margin:0!important;border:none!important;visibility:hidden!important;opacity:0!important}:host ::ng-deep .grid-row-menu-button,:host ::ng-deep [alignfrozen=left]{padding:0 40px 0 0!important;text-align:center!important;vertical-align:middle!important}:host ::ng-deep .grid-row-menu-button button,:host ::ng-deep [alignfrozen=left] button{all:initial!important;width:32px!important;height:32px!important;min-width:32px!important;min-height:32px!important;display:inline-block!important;position:relative!important;cursor:pointer!important;margin:0 auto!important;border:none!important;background:none!important;padding:0!important;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDQgMTYiIGZpbGw9IiM5Y2EzYWYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjIiLz48Y2lyY2xlIGN4PSIyIiBjeT0iOCIgcj0iMiIvPjxjaXJjbGUgY3g9IjIiIGN5PSIxNCIgcj0iMiIvPjwvc3ZnPg==)!important;background-repeat:no-repeat!important;background-position:center!important;background-size:4px 16px!important;border-radius:6px!important}:host ::ng-deep .grid-row-menu-button button:hover,:host ::ng-deep [alignfrozen=left] button:hover{background-color:#4b5563!important;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDQgMTYiIGZpbGw9IiM5Y2EzYWYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjIiLz48Y2lyY2xlIGN4PSIyIiBjeT0iOCIgcj0iMiIvPjxjaXJjbGUgY3g9IjIiIGN5PSIxNCIgcj0iMiIvPjwvc3ZnPg==)!important}:host ::ng-deep .grid-row-menu-button button i,:host ::ng-deep [alignfrozen=left] button i,:host ::ng-deep .pi-ellipsis-v{display:none!important;width:0!important;height:0!important;font-size:0!important;visibility:hidden!important;opacity:0!important}.dark-theme-grid .p-datatable{justify-content:center;align-items:center}.dark-theme-grid .p-menu-list{background:#fff!important}.filter-container{position:relative;display:inline-block;border:2px solid #423D48;padding:3px;border-radius:20px}.filter-container:before{content:\"\";position:absolute;inset:1.5px;background:transparent;border-radius:20px;z-index:0;transition:all .2s ease}.filter-container .flex{position:relative;z-index:1}.filter-container button{position:relative;z-index:2;min-width:80px;all:unset;cursor:pointer;text-align:center;padding:.5rem 1rem;border-radius:16px;font-size:.875rem;font-weight:500;transition:all .2s ease}.filter-container button.selected-filter{background-color:#374151;color:#fff;border:1px solid #4b5563;box-shadow:0 1px 2px #0000001a}.filter-container button.unselected-filter{background-color:transparent;color:#d1d5db;border:1px solid transparent}.filter-container button.unselected-filter:hover{background-color:#4b556333;color:#fff}\n"] }]
747
+ }], () => [{ type: InvitationGridService }, { type: InvitationCodeService }], null); })();
748
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(InvitationCodesComponent, { className: "InvitationCodesComponent", filePath: "lib/pages/invitation-codes/invitation-codes.component.ts", lineNumber: 17 }); })();
749
+
750
+ const waitlistGridColumns = [
751
+ {
752
+ name: 'name',
753
+ label: 'Name',
754
+ visible: true,
755
+ sortable: true,
756
+ width: 200,
757
+ controlType: 'Text',
758
+ editable: false
759
+ },
760
+ {
761
+ name: 'email',
762
+ label: 'Email',
763
+ visible: true,
764
+ sortable: true,
765
+ width: 250,
766
+ controlType: 'Text',
767
+ editable: false
768
+ },
769
+ {
770
+ name: 'userType',
771
+ label: 'User Type',
772
+ visible: true,
773
+ sortable: true,
774
+ width: 150,
775
+ controlType: 'Text',
776
+ editable: false
777
+ },
778
+ {
779
+ name: 'priority',
780
+ label: 'Priority',
781
+ visible: true,
782
+ sortable: true,
783
+ width: 120,
784
+ controlType: 'Text',
785
+ editable: false
786
+ },
787
+ {
788
+ name: 'joined',
789
+ label: 'Joined',
790
+ visible: true,
791
+ sortable: true,
792
+ width: 120,
793
+ controlType: 'Text',
794
+ editable: false
795
+ },
796
+ {
797
+ name: 'waitTime',
798
+ label: 'Wait Time',
799
+ visible: true,
800
+ sortable: true,
801
+ width: 100,
802
+ controlType: 'Text',
803
+ editable: false
804
+ },
805
+ {
806
+ name: 'notes',
807
+ label: 'Notes',
808
+ visible: true,
809
+ sortable: false,
810
+ width: 200,
811
+ controlType: 'Text',
812
+ editable: false
813
+ }
814
+ ];
815
+
816
+ function ConvertToInvitationDialogComponent_option_37_Template(rf, ctx) { if (rf & 1) {
817
+ i0.ɵɵelementStart(0, "option", 29);
818
+ i0.ɵɵtext(1);
819
+ i0.ɵɵelementEnd();
820
+ } if (rf & 2) {
821
+ const days_r1 = ctx.$implicit;
822
+ i0.ɵɵproperty("value", days_r1)("selected", days_r1 === 30);
823
+ i0.ɵɵadvance();
824
+ i0.ɵɵtextInterpolate2(" ", days_r1, " day", days_r1 > 1 ? "s" : "", " ");
825
+ } }
826
+ function ConvertToInvitationDialogComponent_span_65_Template(rf, ctx) { if (rf & 1) {
827
+ i0.ɵɵelementStart(0, "span", 30)(1, "mat-icon", 31);
828
+ i0.ɵɵtext(2, "refresh");
829
+ i0.ɵɵelementEnd();
830
+ i0.ɵɵelementStart(3, "span");
831
+ i0.ɵɵtext(4, "Generating...");
832
+ i0.ɵɵelementEnd()();
833
+ } }
834
+ function ConvertToInvitationDialogComponent_span_66_Template(rf, ctx) { if (rf & 1) {
835
+ i0.ɵɵelementStart(0, "span", 30)(1, "mat-icon");
836
+ i0.ɵɵtext(2, "send");
837
+ i0.ɵɵelementEnd();
838
+ i0.ɵɵelementStart(3, "span");
839
+ i0.ɵɵtext(4);
840
+ i0.ɵɵelementEnd()();
841
+ } if (rf & 2) {
842
+ const ctx_r1 = i0.ɵɵnextContext();
843
+ i0.ɵɵadvance(4);
844
+ i0.ɵɵtextInterpolate2("Generate ", ctx_r1.data.selectedCount, " Invitation", ctx_r1.data.selectedCount > 1 ? "s" : "");
845
+ } }
846
+ class ConvertToInvitationDialogComponent {
847
+ dialogRef;
848
+ data;
849
+ expiryDays = 30;
850
+ isConverting = false;
851
+ expiryOptions = [7, 14, 30, 60, 90];
852
+ accessLevel = 'basic';
853
+ constructor(dialogRef, data) {
854
+ this.dialogRef = dialogRef;
855
+ this.data = data;
856
+ }
857
+ onCancel() {
858
+ this.dialogRef.close(false);
859
+ }
860
+ onConvert() {
861
+ this.isConverting = true;
862
+ const result = {
863
+ expiryDays: this.expiryDays,
864
+ accessLevel: this.accessLevel,
865
+ selectedMemberIds: this.data.selectedMembers.map(m => m.id),
866
+ selectedMembers: this.data.selectedMembers,
867
+ totalInvitations: this.data.selectedCount
868
+ };
869
+ this.dialogRef.close(result);
870
+ this.isConverting = false;
871
+ }
872
+ static ɵfac = function ConvertToInvitationDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ConvertToInvitationDialogComponent)(i0.ɵɵdirectiveInject(i1$1.MatDialogRef), i0.ɵɵdirectiveInject(MAT_DIALOG_DATA)); };
873
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ConvertToInvitationDialogComponent, selectors: [["app-convert-to-invitation-dialog"]], standalone: false, decls: 67, vars: 11, consts: [["mat-dialog-title", "", 1, "text-white", "!pb-2", "!text-xl", "font-semibold"], [1, "!pb-0", "!min-w-[500px]"], [1, "space-y-6"], [1, "text-md", "text-gray-300"], [1, "font-semibold", "text-white"], [1, "border-t", "border-gray-700"], [1, "mat-dialog-instructions"], [1, "text-md", "font-medium", "text-white", "mb-6"], [1, "bg-gray-800/30", "border", "border-gray-700", "rounded-lg", "p-4", "space-y-3"], [1, "dialog-instruction", "flex", "items-start"], [1, "bullet-point", "mr-3", "mt-2"], [1, "text-gray-300"], [1, "text-md", "font-medium", "text-white", "mb-2"], [1, "space-y-4"], [1, "w-full", "px-4", "py-3", "bg-gray-800", "border", "border-gray-700", "rounded-lg", "text-white", "focus:outline-none", "focus:ring-2", "focus:ring-blue-500", "focus:border-blue-500", "cursor-pointer", 3, "ngModelChange", "ngModel"], [3, "value", "selected", 4, "ngFor", "ngForOf"], [1, "flex", "items-start"], [1, "mat-dialog-message", "text-gray-300"], [1, "mb-6"], [1, "space-y-2"], [1, "flex", "items-center", "space-x-2", "cursor-pointer"], ["type", "radio", "value", "basic", 1, "text-blue-500", 3, "ngModelChange", "ngModel"], ["type", "radio", "value", "premium", 1, "text-blue-500", 3, "ngModelChange", "ngModel"], ["type", "radio", "value", "admin", 1, "text-blue-500", 3, "ngModelChange", "ngModel"], ["type", "radio", "value", "vip", 1, "text-blue-500", 3, "ngModelChange", "ngModel"], ["align", "end", 1, "!p-6", "!pt-4", "!border-t", "!border-gray-700"], ["mat-stroked-button", "", 1, "!border-gray-600", "!text-gray-300", "hover:!bg-gray-700", "hover:!border-gray-500", 3, "click"], ["mat-raised-button", "", "color", "primary", 1, "!bg-blue-600", "hover:!bg-blue-700", "disabled:!opacity-50", "disabled:!cursor-not-allowed", 3, "click", "disabled"], ["class", "flex items-center space-x-2", 4, "ngIf"], [3, "value", "selected"], [1, "flex", "items-center", "space-x-2"], [1, "animate-spin", "!text-lg"]], template: function ConvertToInvitationDialogComponent_Template(rf, ctx) { if (rf & 1) {
874
+ i0.ɵɵelementStart(0, "h2", 0);
875
+ i0.ɵɵtext(1, "Convert to Invitation Code");
876
+ i0.ɵɵelementEnd();
877
+ i0.ɵɵelementStart(2, "mat-dialog-content", 1)(3, "div", 2)(4, "div", 3);
878
+ i0.ɵɵtext(5, " Generate invitation codes for ");
879
+ i0.ɵɵelementStart(6, "span", 4);
880
+ i0.ɵɵtext(7);
881
+ i0.ɵɵelementEnd();
882
+ i0.ɵɵtext(8);
883
+ i0.ɵɵelementEnd();
884
+ i0.ɵɵelement(9, "div", 5);
885
+ i0.ɵɵelementStart(10, "div", 6)(11, "h3", 7);
886
+ i0.ɵɵtext(12, "What happens next?");
887
+ i0.ɵɵelementEnd();
888
+ i0.ɵɵelementStart(13, "div", 8)(14, "div", 9);
889
+ i0.ɵɵelement(15, "div", 10);
890
+ i0.ɵɵelementStart(16, "span", 11);
891
+ i0.ɵɵtext(17, "Invitation codes will be generated for each selected member");
892
+ i0.ɵɵelementEnd()();
893
+ i0.ɵɵelementStart(18, "div", 9);
894
+ i0.ɵɵelement(19, "div", 10);
895
+ i0.ɵɵelementStart(20, "span", 11);
896
+ i0.ɵɵtext(21, "Codes will be tied to their email addresses");
897
+ i0.ɵɵelementEnd()();
898
+ i0.ɵɵelementStart(22, "div", 9);
899
+ i0.ɵɵelement(23, "div", 10);
900
+ i0.ɵɵelementStart(24, "span", 11);
901
+ i0.ɵɵtext(25, "Members will be removed from the waitlist");
902
+ i0.ɵɵelementEnd()();
903
+ i0.ɵɵelementStart(26, "div", 9);
904
+ i0.ɵɵelement(27, "div", 10);
905
+ i0.ɵɵelementStart(28, "span", 11);
906
+ i0.ɵɵtext(29, "Codes bypass user type limits");
907
+ i0.ɵɵelementEnd()()()();
908
+ i0.ɵɵelement(30, "div", 5);
909
+ i0.ɵɵelementStart(31, "div")(32, "h3", 12);
910
+ i0.ɵɵtext(33, "Invitation Expiry Period");
911
+ i0.ɵɵelementEnd();
912
+ i0.ɵɵelementStart(34, "div", 13)(35, "div")(36, "select", 14);
913
+ i0.ɵɵtwoWayListener("ngModelChange", function ConvertToInvitationDialogComponent_Template_select_ngModelChange_36_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.expiryDays, $event) || (ctx.expiryDays = $event); return $event; });
914
+ i0.ɵɵtemplate(37, ConvertToInvitationDialogComponent_option_37_Template, 2, 4, "option", 15);
915
+ i0.ɵɵelementEnd()();
916
+ i0.ɵɵelementStart(38, "div", 16)(39, "span", 17);
917
+ i0.ɵɵtext(40, "Code will expire if account is not created within this period");
918
+ i0.ɵɵelementEnd()()()();
919
+ i0.ɵɵelementStart(41, "div", 18)(42, "h3", 12);
920
+ i0.ɵɵtext(43, "Access Level");
921
+ i0.ɵɵelementEnd();
922
+ i0.ɵɵelementStart(44, "div", 19)(45, "label", 20)(46, "input", 21);
923
+ i0.ɵɵtwoWayListener("ngModelChange", function ConvertToInvitationDialogComponent_Template_input_ngModelChange_46_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.accessLevel, $event) || (ctx.accessLevel = $event); return $event; });
924
+ i0.ɵɵelementEnd();
925
+ i0.ɵɵelementStart(47, "span", 11);
926
+ i0.ɵɵtext(48, "Basic Access");
927
+ i0.ɵɵelementEnd()();
928
+ i0.ɵɵelementStart(49, "label", 20)(50, "input", 22);
929
+ i0.ɵɵtwoWayListener("ngModelChange", function ConvertToInvitationDialogComponent_Template_input_ngModelChange_50_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.accessLevel, $event) || (ctx.accessLevel = $event); return $event; });
930
+ i0.ɵɵelementEnd();
931
+ i0.ɵɵelementStart(51, "span", 11);
932
+ i0.ɵɵtext(52, "Premium Access");
933
+ i0.ɵɵelementEnd()();
934
+ i0.ɵɵelementStart(53, "label", 20)(54, "input", 23);
935
+ i0.ɵɵtwoWayListener("ngModelChange", function ConvertToInvitationDialogComponent_Template_input_ngModelChange_54_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.accessLevel, $event) || (ctx.accessLevel = $event); return $event; });
936
+ i0.ɵɵelementEnd();
937
+ i0.ɵɵelementStart(55, "span", 11);
938
+ i0.ɵɵtext(56, "Admin Access");
939
+ i0.ɵɵelementEnd()();
940
+ i0.ɵɵelementStart(57, "label", 20)(58, "input", 24);
941
+ i0.ɵɵtwoWayListener("ngModelChange", function ConvertToInvitationDialogComponent_Template_input_ngModelChange_58_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.accessLevel, $event) || (ctx.accessLevel = $event); return $event; });
942
+ i0.ɵɵelementEnd();
943
+ i0.ɵɵelementStart(59, "span", 11);
944
+ i0.ɵɵtext(60, "VIP Access");
945
+ i0.ɵɵelementEnd()()()()()();
946
+ i0.ɵɵelementStart(61, "mat-dialog-actions", 25)(62, "button", 26);
947
+ i0.ɵɵlistener("click", function ConvertToInvitationDialogComponent_Template_button_click_62_listener() { return ctx.onCancel(); });
948
+ i0.ɵɵtext(63, " Cancel ");
949
+ i0.ɵɵelementEnd();
950
+ i0.ɵɵelementStart(64, "button", 27);
951
+ i0.ɵɵlistener("click", function ConvertToInvitationDialogComponent_Template_button_click_64_listener() { return ctx.onConvert(); });
952
+ i0.ɵɵtemplate(65, ConvertToInvitationDialogComponent_span_65_Template, 5, 0, "span", 28)(66, ConvertToInvitationDialogComponent_span_66_Template, 5, 2, "span", 28);
953
+ i0.ɵɵelementEnd()();
954
+ } if (rf & 2) {
955
+ i0.ɵɵadvance(7);
956
+ i0.ɵɵtextInterpolate(ctx.data.selectedCount);
957
+ i0.ɵɵadvance();
958
+ i0.ɵɵtextInterpolate1(" selected waitlist member", ctx.data.selectedCount > 1 ? "s" : "", " ");
959
+ i0.ɵɵadvance(28);
960
+ i0.ɵɵtwoWayProperty("ngModel", ctx.expiryDays);
961
+ i0.ɵɵadvance();
962
+ i0.ɵɵproperty("ngForOf", ctx.expiryOptions);
963
+ i0.ɵɵadvance(9);
964
+ i0.ɵɵtwoWayProperty("ngModel", ctx.accessLevel);
965
+ i0.ɵɵadvance(4);
966
+ i0.ɵɵtwoWayProperty("ngModel", ctx.accessLevel);
967
+ i0.ɵɵadvance(4);
968
+ i0.ɵɵtwoWayProperty("ngModel", ctx.accessLevel);
969
+ i0.ɵɵadvance(4);
970
+ i0.ɵɵtwoWayProperty("ngModel", ctx.accessLevel);
971
+ i0.ɵɵadvance(6);
972
+ i0.ɵɵproperty("disabled", ctx.isConverting);
973
+ i0.ɵɵadvance();
974
+ i0.ɵɵproperty("ngIf", ctx.isConverting);
975
+ i0.ɵɵadvance();
976
+ i0.ɵɵproperty("ngIf", !ctx.isConverting);
977
+ } }, dependencies: [i2.NgForOf, i2.NgIf, i1$2.NgSelectOption, i1$2.ɵNgSelectMultipleOption, i1$2.DefaultValueAccessor, i1$2.SelectControlValueAccessor, i1$2.RadioControlValueAccessor, i1$2.NgControlStatus, i1$2.NgModel, i1$1.MatDialogTitle, i1$1.MatDialogActions, i1$1.MatDialogContent, i4$1.MatButton, i5.MatIcon], styles: ["[_nghost-%COMP%] .mat-dialog-instructions[_ngcontent-%COMP%]{border:1px solid #423D48;padding:30px 20px;border-radius:10px;margin:22px 0}[_nghost-%COMP%] .mat-mdc-dialog-container[_ngcontent-%COMP%]{background-color:#1f2937!important;border:1px solid #374151}[_nghost-%COMP%] .mat-mdc-dialog-title[_ngcontent-%COMP%]{color:#fff!important;font-size:1.25rem!important;padding-bottom:.5rem!important}[_nghost-%COMP%] .mat-mdc-dialog-content[_ngcontent-%COMP%]{color:#d1d5db!important}[_nghost-%COMP%] .bullet-point[_ngcontent-%COMP%]{width:8px;height:8px;background-color:#fff;border-radius:50%;flex-shrink:0;margin-right:10px;position:relative;bottom:2px}[_nghost-%COMP%] .dialog-instruction[_ngcontent-%COMP%]{margin-top:5px}[_nghost-%COMP%] mat-icon.text-green-400[_ngcontent-%COMP%]{color:#34d399!important;font-size:20px!important;height:20px!important;width:20px!important}[_nghost-%COMP%] mat-icon.text-yellow-400[_ngcontent-%COMP%]{color:#fbbf24!important;font-size:20px!important;height:20px!important;width:20px!important}[_nghost-%COMP%] .mat-dialog-message[_ngcontent-%COMP%]{font-size:13px;margin-top:5px}[_nghost-%COMP%] select[_ngcontent-%COMP%]{width:100%;height:40px}"] });
978
+ }
979
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ConvertToInvitationDialogComponent, [{
980
+ type: Component,
981
+ args: [{ selector: 'app-convert-to-invitation-dialog', standalone: false, template: "<h2 mat-dialog-title class=\"text-white !pb-2 !text-xl font-semibold\">Convert to Invitation Code</h2>\r\n\r\n<mat-dialog-content class=\" !pb-0 !min-w-[500px]\">\r\n <div class=\" space-y-6\">\r\n <div class=\"text-md text-gray-300\">\r\n Generate invitation codes for <span class=\"font-semibold text-white\">{{data.selectedCount}}</span> selected waitlist member{{data.selectedCount > 1 ? 's' : ''}}\r\n </div>\r\n <div class=\"border-t border-gray-700\"></div>\r\n <div class=\"mat-dialog-instructions\">\r\n <h3 class=\"text-md font-medium text-white mb-6\">What happens next?</h3>\r\n <div class=\"bg-gray-800/30 border border-gray-700 rounded-lg p-4 space-y-3\">\r\n <div class=\"dialog-instruction flex items-start\">\r\n <div class=\"bullet-point mr-3 mt-2\"></div>\r\n <span class=\"text-gray-300\">Invitation codes will be generated for each selected member</span>\r\n </div>\r\n <div class=\"dialog-instruction flex items-start\">\r\n <div class=\"bullet-point mr-3 mt-2\"></div>\r\n <span class=\"text-gray-300\">Codes will be tied to their email addresses</span>\r\n </div>\r\n <div class=\"dialog-instruction flex items-start\">\r\n <div class=\"bullet-point mr-3 mt-2\"></div>\r\n <span class=\"text-gray-300\">Members will be removed from the waitlist</span>\r\n </div>\r\n <div class=\"dialog-instruction flex items-start\">\r\n <div class=\"bullet-point mr-3 mt-2\"></div>\r\n <span class=\"text-gray-300\">Codes bypass user type limits</span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"border-t border-gray-700\"></div>\r\n <div>\r\n <h3 class=\"text-md font-medium text-white mb-2\">Invitation Expiry Period</h3>\r\n <div class=\"space-y-4\">\r\n <div>\r\n <select\r\n [(ngModel)]=\"expiryDays\"\r\n class=\"w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 cursor-pointer\">\r\n <option *ngFor=\"let days of expiryOptions\" [value]=\"days\" [selected]=\"days === 30\">\r\n {{days}} day{{days > 1 ? 's' : ''}}\r\n </option>\r\n </select>\r\n </div>\r\n <div class=\"flex items-start\">\r\n <span class=\"mat-dialog-message text-gray-300\">Code will expire if account is not created within this period</span>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n<div class=\"mb-6\">\r\n <h3 class=\"text-md font-medium text-white mb-2\">Access Level</h3>\r\n <div class=\"space-y-2\">\r\n <label class=\"flex items-center space-x-2 cursor-pointer\">\r\n <input type=\"radio\" [(ngModel)]=\"accessLevel\" value=\"basic\" class=\"text-blue-500\">\r\n <span class=\"text-gray-300\">Basic Access</span>\r\n </label>\r\n <label class=\"flex items-center space-x-2 cursor-pointer\">\r\n <input type=\"radio\" [(ngModel)]=\"accessLevel\" value=\"premium\" class=\"text-blue-500\">\r\n <span class=\"text-gray-300\">Premium Access</span>\r\n </label>\r\n <label class=\"flex items-center space-x-2 cursor-pointer\">\r\n <input type=\"radio\" [(ngModel)]=\"accessLevel\" value=\"admin\" class=\"text-blue-500\">\r\n <span class=\"text-gray-300\">Admin Access</span>\r\n </label>\r\n <label class=\"flex items-center space-x-2 cursor-pointer\">\r\n <input type=\"radio\" [(ngModel)]=\"accessLevel\" value=\"vip\" class=\"text-blue-500\">\r\n <span class=\"text-gray-300\">VIP Access</span>\r\n </label>\r\n </div>\r\n</div>\r\n </div>\r\n</mat-dialog-content>\r\n\r\n<mat-dialog-actions align=\"end\" class=\"!p-6 !pt-4 !border-t !border-gray-700\">\r\n <button\r\n mat-stroked-button\r\n (click)=\"onCancel()\"\r\n class=\"!border-gray-600 !text-gray-300 hover:!bg-gray-700 hover:!border-gray-500\">\r\n Cancel\r\n </button>\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"onConvert()\"\r\n [disabled]=\"isConverting\"\r\n class=\"!bg-blue-600 hover:!bg-blue-700 disabled:!opacity-50 disabled:!cursor-not-allowed\">\r\n <span *ngIf=\"isConverting\" class=\"flex items-center space-x-2\">\r\n <mat-icon class=\"animate-spin !text-lg\">refresh</mat-icon>\r\n <span>Generating...</span>\r\n </span>\r\n <span *ngIf=\"!isConverting\" class=\"flex items-center space-x-2\">\r\n <mat-icon>send</mat-icon>\r\n <span>Generate {{data.selectedCount}} Invitation{{data.selectedCount > 1 ? 's' : ''}}</span>\r\n </span>\r\n </button>\r\n</mat-dialog-actions>\r\n", styles: [":host .mat-dialog-instructions{border:1px solid #423D48;padding:30px 20px;border-radius:10px;margin:22px 0}:host .mat-mdc-dialog-container{background-color:#1f2937!important;border:1px solid #374151}:host .mat-mdc-dialog-title{color:#fff!important;font-size:1.25rem!important;padding-bottom:.5rem!important}:host .mat-mdc-dialog-content{color:#d1d5db!important}:host .bullet-point{width:8px;height:8px;background-color:#fff;border-radius:50%;flex-shrink:0;margin-right:10px;position:relative;bottom:2px}:host .dialog-instruction{margin-top:5px}:host mat-icon.text-green-400{color:#34d399!important;font-size:20px!important;height:20px!important;width:20px!important}:host mat-icon.text-yellow-400{color:#fbbf24!important;font-size:20px!important;height:20px!important;width:20px!important}:host .mat-dialog-message{font-size:13px;margin-top:5px}:host select{width:100%;height:40px}\n"] }]
982
+ }], () => [{ type: i1$1.MatDialogRef }, { type: undefined, decorators: [{
983
+ type: Inject,
984
+ args: [MAT_DIALOG_DATA]
985
+ }] }], null); })();
986
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ConvertToInvitationDialogComponent, { className: "ConvertToInvitationDialogComponent", filePath: "lib/components/modal/convert-to-invitation-dialog/convert-to-invitation-dialog.component.ts", lineNumber: 16 }); })();
987
+
988
+ class WaitlistCodeService {
989
+ http;
990
+ config;
991
+ apiUrlBuilder;
992
+ constructor(http, config) {
993
+ this.http = http;
994
+ this.config = config;
995
+ this.apiUrlBuilder = new ApiUrlBuilder(config);
996
+ }
997
+ getWaitlistStats() {
998
+ return this.http.get(this.apiUrlBuilder.buildUrl('waitlisted-users/stats')).pipe(map(stats => {
999
+ if (!stats.success) {
1000
+ return this.getDefaultStats();
1001
+ }
1002
+ const totalStats = stats.total || stats;
1003
+ return [
1004
+ {
1005
+ title: 'Waitlisted',
1006
+ value: totalStats.waitlisted || 0,
1007
+ description: 'Members waiting for access',
1008
+ icon: 'schedule',
1009
+ color: 'bg-yellow-500'
1010
+ },
1011
+ {
1012
+ title: 'Invited',
1013
+ value: totalStats.invited || 0,
1014
+ description: 'Invitations sent',
1015
+ icon: 'send',
1016
+ color: 'bg-blue-500'
1017
+ },
1018
+ {
1019
+ title: 'Active Users',
1020
+ value: totalStats.currentUsers || 0,
1021
+ description: 'Currently active users',
1022
+ icon: 'people',
1023
+ color: 'bg-green-500'
1024
+ },
1025
+ {
1026
+ title: 'User Limit',
1027
+ value: totalStats.userLimit || 0,
1028
+ description: 'Maximum allowed users',
1029
+ icon: 'security',
1030
+ color: 'bg-purple-500'
1031
+ }
1032
+ ];
1033
+ }));
1034
+ }
1035
+ getDefaultStats() {
1036
+ return [
1037
+ {
1038
+ title: 'Waitlisted',
1039
+ value: 0,
1040
+ description: 'Members waiting for access',
1041
+ icon: 'schedule',
1042
+ color: 'bg-yellow-500'
1043
+ },
1044
+ {
1045
+ title: 'Invited',
1046
+ value: 0,
1047
+ description: 'Invitations sent',
1048
+ icon: 'send',
1049
+ color: 'bg-blue-500'
1050
+ },
1051
+ {
1052
+ title: 'Active Users',
1053
+ value: 0,
1054
+ description: 'Currently active users',
1055
+ icon: 'people',
1056
+ color: 'bg-green-500'
1057
+ }
1058
+ ];
1059
+ }
1060
+ updatePriority(memberId, priority) {
1061
+ return this.http.put(this.apiUrlBuilder.buildUrl(`waitlisted-users/${memberId}/invite`), {});
1062
+ }
1063
+ removeFromWaitlist(memberId) {
1064
+ return this.http.delete(this.apiUrlBuilder.buildUrl(`waitlisted-users/${memberId}`));
1065
+ }
1066
+ restoreToWaitlist(memberId) {
1067
+ return new Observable();
1068
+ }
1069
+ updateStatus(memberId, status) {
1070
+ return this.http.post(this.apiUrlBuilder.buildUrl(`waitlisted-users/${memberId}/invite`), {
1071
+ accessLevel: 'basic'
1072
+ });
1073
+ }
1074
+ static ɵfac = function WaitlistCodeService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WaitlistCodeService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(INVITATION_CODE_CONFIG)); };
1075
+ static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: WaitlistCodeService, factory: WaitlistCodeService.ɵfac, providedIn: 'root' });
1076
+ }
1077
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WaitlistCodeService, [{
1078
+ type: Injectable,
1079
+ args: [{
1080
+ providedIn: 'root'
1081
+ }]
1082
+ }], () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
1083
+ type: Inject,
1084
+ args: [INVITATION_CODE_CONFIG]
1085
+ }] }], null); })();
1086
+
1087
+ class WaitlistGridService {
1088
+ invitationCodeService;
1089
+ waitlistCodeService;
1090
+ http;
1091
+ config;
1092
+ refreshGrid$ = new BehaviorSubject(undefined);
1093
+ destroy$ = new Subject();
1094
+ apiUrlBuilder;
1095
+ constructor(invitationCodeService, waitlistCodeService, http, config) {
1096
+ this.invitationCodeService = invitationCodeService;
1097
+ this.waitlistCodeService = waitlistCodeService;
1098
+ this.http = http;
1099
+ this.config = config;
1100
+ this.apiUrlBuilder = new ApiUrlBuilder(config);
1101
+ }
1102
+ get refreshTrigger$() {
1103
+ return this.refreshGrid$.asObservable();
1104
+ }
1105
+ triggerRefresh() {
1106
+ this.refreshGrid$.next();
1107
+ }
1108
+ ngOnDestroy() {
1109
+ this.destroy$.next();
1110
+ this.destroy$.complete();
1111
+ }
1112
+ getWaitlistMembers(event) {
1113
+ const page = Math.floor(event.from / event.size) + 1;
1114
+ const limit = event.size;
1115
+ return this.invitationCodeService.getWaitlistMembers(page, limit, event.userFilters, event.sortField, event.sortDirection === 'Ascending' ? 'asc' : 'desc', event.searchString).pipe(map(response => {
1116
+ const gridRows = response.data.map(item => {
1117
+ const gridItem = {
1118
+ id: item.id,
1119
+ name: item.name,
1120
+ email: item.email,
1121
+ userType: item.userType,
1122
+ priority: item.priority,
1123
+ joined: item.joined,
1124
+ waitTime: item.waitTime,
1125
+ notes: item.notes,
1126
+ status: item.status,
1127
+ convertedAt: item.convertedAt,
1128
+ convertedToCodeId: item.convertedToCodeId
1129
+ };
1130
+ return {
1131
+ id: item.id,
1132
+ data: gridItem,
1133
+ rowMenuItems: this.createActionMenu(gridItem),
1134
+ hasEditPermissions: true,
1135
+ hasDeletePermissions: true,
1136
+ displayValues: this.createDisplayValues(gridItem)
1137
+ };
1138
+ });
1139
+ return { data: gridRows, count: response.count };
1140
+ }));
1141
+ }
1142
+ createDisplayValues(item) {
1143
+ return {
1144
+ name: item.name,
1145
+ email: item.email,
1146
+ userType: this.getUserTypeDisplay(item.userType),
1147
+ priority: this.getPriorityDisplay(item.priority),
1148
+ joined: this.formatDate(item.joined),
1149
+ waitTime: `${item.waitTime} days`,
1150
+ notes: item.notes,
1151
+ status: this.getStatusDisplay(item.status || 'pending'),
1152
+ id: item.id
1153
+ };
1154
+ }
1155
+ formatDate(date) {
1156
+ if (!date)
1157
+ return 'N/A';
1158
+ const d = new Date(date);
1159
+ return isNaN(d.getTime()) ? 'Invalid Date' : d.toLocaleDateString('en-US', {
1160
+ year: 'numeric',
1161
+ month: 'short',
1162
+ day: 'numeric'
1163
+ });
1164
+ }
1165
+ getUserTypeDisplay(userType) {
1166
+ const userTypeMap = {
1167
+ 'premium': 'Premium Member',
1168
+ 'standard': 'Standard Member',
1169
+ 'vip': 'VIP Member'
1170
+ };
1171
+ return userTypeMap[userType] || userType;
1172
+ }
1173
+ getPriorityDisplay(priority) {
1174
+ const priorityMap = {
1175
+ 'high': 'High Priority',
1176
+ 'normal': 'Normal'
1177
+ };
1178
+ return priorityMap[priority] || priority;
1179
+ }
1180
+ getStatusDisplay(status) {
1181
+ const statusMap = {
1182
+ 'pending': 'Pending',
1183
+ 'converted': 'Converted',
1184
+ 'removed': 'Removed',
1185
+ 'invited': 'Invited'
1186
+ };
1187
+ return statusMap[status] || status || 'Pending';
1188
+ }
1189
+ createActionMenu(item) {
1190
+ const menuItems = [
1191
+ {
1192
+ label: 'Action',
1193
+ disabled: true,
1194
+ styleClass: 'menu-header'
1195
+ },
1196
+ {
1197
+ separator: true
1198
+ }
1199
+ ];
1200
+ if (item.status === 'pending' || item.status === 'waitlisted') {
1201
+ menuItems.push({
1202
+ label: 'Send Invitation',
1203
+ icon: 'pi pi-send',
1204
+ command: () => this.sendInvitation(item)
1205
+ });
1206
+ menuItems.push({
1207
+ label: 'Remove from Waitlist',
1208
+ icon: 'pi pi-trash',
1209
+ command: () => this.removeFromWaitlist(item)
1210
+ });
1211
+ }
1212
+ else if (item.status === 'invited' || item.status === 'waitlist_invited') {
1213
+ menuItems.push({
1214
+ label: 'View Invitation',
1215
+ icon: 'pi pi-eye',
1216
+ command: () => this.viewInvitation(item)
1217
+ });
1218
+ menuItems.push({
1219
+ label: 'Remove Invitation',
1220
+ icon: 'pi pi-times',
1221
+ command: () => this.removeFromWaitlist(item)
1222
+ });
1223
+ }
1224
+ else if (item.status === 'converted') {
1225
+ menuItems.push({
1226
+ label: 'View Invitation Code',
1227
+ icon: 'pi pi-eye',
1228
+ command: () => this.viewInvitation(item)
1229
+ });
1230
+ }
1231
+ return menuItems;
1232
+ }
1233
+ sendInvitation(item) {
1234
+ if (confirm(`Send invitation to "${item.name}"?`)) {
1235
+ this.http.post(this.apiUrlBuilder.buildUrl(`waitlisted-users/${item.id}/invite`), {
1236
+ accessLevel: 'basic',
1237
+ expiryDays: 30
1238
+ }).subscribe({
1239
+ next: (response) => {
1240
+ if (response.success) {
1241
+ alert(`Invitation sent to "${item.name}"!`);
1242
+ this.triggerRefresh();
1243
+ }
1244
+ else {
1245
+ alert(`Failed to send invitation: ${response.error || 'Unknown error'}`);
1246
+ }
1247
+ },
1248
+ error: (error) => {
1249
+ alert(`Failed to send invitation: ${error.message}`);
1250
+ }
1251
+ });
1252
+ }
1253
+ }
1254
+ updatePriority(item) {
1255
+ const newPriority = item.priority === 'high' ? 'normal' : 'high';
1256
+ if (confirm(`Are you sure you want to change priority of "${item.name}" to ${newPriority}?`)) {
1257
+ this.waitlistCodeService.updatePriority(item.id, newPriority).subscribe({
1258
+ next: () => {
1259
+ alert(`Priority for "${item.name}" has been updated to ${newPriority}!`);
1260
+ this.triggerRefresh();
1261
+ },
1262
+ error: (error) => {
1263
+ alert(`Failed to update priority: ${error.message}`);
1264
+ }
1265
+ });
1266
+ }
1267
+ }
1268
+ removeFromWaitlist(item) {
1269
+ if (confirm(`Are you sure you want to remove "${item.name}" from the waitlist?`)) {
1270
+ this.waitlistCodeService.removeFromWaitlist(item.id).subscribe({
1271
+ next: () => {
1272
+ alert(`"${item.name}" has been removed from the waitlist!`);
1273
+ this.triggerRefresh();
1274
+ },
1275
+ error: (error) => {
1276
+ alert(`Failed to remove from waitlist: ${error.message}`);
1277
+ }
1278
+ });
1279
+ }
1280
+ }
1281
+ restoreToWaitlist(item) {
1282
+ if (confirm(`Are you sure you want to restore "${item.name}" to the waitlist?`)) {
1283
+ this.waitlistCodeService.restoreToWaitlist(item.id).subscribe({
1284
+ next: () => {
1285
+ alert(`"${item.name}" has been restored to the waitlist!`);
1286
+ this.triggerRefresh();
1287
+ },
1288
+ error: (error) => {
1289
+ alert(`Failed to restore: ${error.message}`);
1290
+ }
1291
+ });
1292
+ }
1293
+ }
1294
+ viewInvitation(item) {
1295
+ if (item.convertedToCodeId) {
1296
+ this.http.get(this.apiUrlBuilder.buildUrl(`invitation-codes/${item.convertedToCodeId}`)).subscribe({
1297
+ next: (invitation) => {
1298
+ alert(`Invitation Details:\n\n` +
1299
+ `Code: ${invitation.code}\n` +
1300
+ `Status: ${invitation.status}\n` +
1301
+ `User Type: ${invitation.userType}\n` +
1302
+ `Access Level: ${invitation.accessLevel}\n` +
1303
+ `Expires: ${new Date(invitation.expires).toLocaleDateString()}\n` +
1304
+ `Created: ${new Date(invitation.createdAt).toLocaleDateString()}`);
1305
+ },
1306
+ error: () => {
1307
+ alert(`This member was converted to invitation code: ${item.convertedToCodeId}\nYou can view it in the invitation codes grid.`);
1308
+ }
1309
+ });
1310
+ }
1311
+ else if (item.status === 'invited' || item.status === 'waitlist_invited') {
1312
+ this.http.get(this.apiUrlBuilder.buildUrl(`waitlisted-users/${item.id}`)).subscribe({
1313
+ next: (userDetails) => {
1314
+ if (userDetails.data?.invitationCode) {
1315
+ alert(`Invitation Code: ${userDetails.data.invitationCode}\n` +
1316
+ `Status: Invited\n` +
1317
+ `Invited On: ${new Date(userDetails.data.waitlistInvitedAt).toLocaleDateString()}\n` +
1318
+ `Expires: ${new Date(userDetails.data.waitlistInvitationExpiry).toLocaleDateString()}`);
1319
+ }
1320
+ else {
1321
+ alert('No invitation code found for this member.');
1322
+ }
1323
+ },
1324
+ error: () => {
1325
+ alert('No invitation code found for this member.');
1326
+ }
1327
+ });
1328
+ }
1329
+ else {
1330
+ alert('No invitation code found for this member.');
1331
+ }
1332
+ }
1333
+ bulkConvertToInvitations(data) {
1334
+ return this.invitationCodeService.bulkGenerateFromWaitlist(data).pipe(map(response => {
1335
+ this.triggerRefresh();
1336
+ return response;
1337
+ }));
1338
+ }
1339
+ static ɵfac = function WaitlistGridService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WaitlistGridService)(i0.ɵɵinject(InvitationCodeService), i0.ɵɵinject(WaitlistCodeService), i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(INVITATION_CODE_CONFIG)); };
1340
+ static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: WaitlistGridService, factory: WaitlistGridService.ɵfac, providedIn: 'root' });
1341
+ }
1342
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WaitlistGridService, [{
1343
+ type: Injectable,
1344
+ args: [{
1345
+ providedIn: 'root'
1346
+ }]
1347
+ }], () => [{ type: InvitationCodeService }, { type: WaitlistCodeService }, { type: i1.HttpClient }, { type: undefined, decorators: [{
1348
+ type: Inject,
1349
+ args: [INVITATION_CODE_CONFIG]
1350
+ }] }], null); })();
1351
+
1352
+ function WaitlistComponent_div_11_Template(rf, ctx) { if (rf & 1) {
1353
+ const _r1 = i0.ɵɵgetCurrentView();
1354
+ i0.ɵɵelementStart(0, "div", 15)(1, "button", 16);
1355
+ i0.ɵɵlistener("click", function WaitlistComponent_div_11_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openConvertModal()); });
1356
+ i0.ɵɵelementStart(2, "mat-icon", 17);
1357
+ i0.ɵɵtext(3, "send");
1358
+ i0.ɵɵelementEnd();
1359
+ i0.ɵɵtext(4);
1360
+ i0.ɵɵelementEnd()();
1361
+ } if (rf & 2) {
1362
+ const ctx_r1 = i0.ɵɵnextContext();
1363
+ i0.ɵɵadvance(4);
1364
+ i0.ɵɵtextInterpolate1(" Convert ", ctx_r1.checkedRows.size, " to Invite ");
1365
+ } }
1366
+ function WaitlistComponent_button_15_Template(rf, ctx) { if (rf & 1) {
1367
+ const _r3 = i0.ɵɵgetCurrentView();
1368
+ i0.ɵɵelementStart(0, "button", 18);
1369
+ i0.ɵɵlistener("click", function WaitlistComponent_button_15_Template_button_click_0_listener() { const filter_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setFilter(filter_r4)); });
1370
+ i0.ɵɵtext(1);
1371
+ i0.ɵɵelementEnd();
1372
+ } if (rf & 2) {
1373
+ const filter_r4 = ctx.$implicit;
1374
+ const ctx_r1 = i0.ɵɵnextContext();
1375
+ i0.ɵɵclassMap(ctx_r1.activeFilter === filter_r4 ? "selected-filter px-4 py-2 text-sm font-medium transition-colors" : "unselected-filter px-4 py-2 text-sm font-medium transition-colors");
1376
+ i0.ɵɵadvance();
1377
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getFilterDisplayName(filter_r4), " ");
1378
+ } }
1379
+ class WaitlistComponent {
1380
+ waitlistGridService;
1381
+ cdr;
1382
+ dialog;
1383
+ gridData = [];
1384
+ columns = [];
1385
+ isConverting = false;
1386
+ isLoading = false;
1387
+ totalRecords = 0;
1388
+ rowsPerPage = 10;
1389
+ rowsPerPageOptions = [5, 10, 25, 50];
1390
+ sortField = 'joined';
1391
+ sortOrder = 'Descending';
1392
+ checkedRows = new Set();
1393
+ activeFilter = 'all';
1394
+ filters = ['all', 'high', 'standard', 'premium', 'vip'];
1395
+ checkboxHtmlCache = new Map();
1396
+ destroy$ = new Subject();
1397
+ constructor(waitlistGridService, cdr, dialog) {
1398
+ this.waitlistGridService = waitlistGridService;
1399
+ this.cdr = cdr;
1400
+ this.dialog = dialog;
1401
+ }
1402
+ ngOnInit() {
1403
+ this.initializeColumns();
1404
+ this.loadGridData();
1405
+ this.subscribeToAutoRefresh();
1406
+ }
1407
+ ngOnDestroy() {
1408
+ this.destroy$.next();
1409
+ this.destroy$.complete();
1410
+ }
1411
+ subscribeToAutoRefresh() {
1412
+ this.waitlistGridService.refreshTrigger$
1413
+ .pipe(takeUntil(this.destroy$))
1414
+ .subscribe(() => {
1415
+ this.loadGridData();
1416
+ });
1417
+ }
1418
+ initializeColumns() {
1419
+ const checkboxColumn = {
1420
+ name: 'checkbox',
1421
+ label: '',
1422
+ visible: true,
1423
+ sortable: false,
1424
+ width: 60,
1425
+ controlType: 'Text',
1426
+ editable: false
1427
+ };
1428
+ this.columns = [...waitlistGridColumns, checkboxColumn];
1429
+ }
1430
+ createCheckboxHtml(memberId) {
1431
+ const cacheKey = `${memberId}-${this.checkedRows.has(memberId)}`;
1432
+ if (this.checkboxHtmlCache.has(cacheKey)) {
1433
+ return this.checkboxHtmlCache.get(cacheKey);
1434
+ }
1435
+ const isChecked = this.checkedRows.has(memberId);
1436
+ const checkboxHtml = isChecked ? this.createCheckedHtml(memberId) : this.createUncheckedHtml(memberId);
1437
+ this.checkboxHtmlCache.set(cacheKey, checkboxHtml);
1438
+ return checkboxHtml;
1439
+ }
1440
+ createCheckedHtml(memberId) {
1441
+ return `
1442
+ <div class="custom-grid-checkbox checked"
1443
+ data-member-id="${memberId}"
1444
+ style="
1445
+ width: 20px;
1446
+ height: 20px;
1447
+ border: 2px solid #3b82f6;
1448
+ border-radius: 4px;
1449
+ background: #3b82f6;
1450
+ cursor: pointer;
1451
+ position: relative;
1452
+ display: inline-block;
1453
+ margin: 0 auto;
1454
+ ">
1455
+ <span style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-size: 12px; font-weight: bold;">✓</span>
1456
+ </div>
1457
+ `;
1458
+ }
1459
+ createUncheckedHtml(memberId) {
1460
+ return `
1461
+ <div class="custom-grid-checkbox"
1462
+ data-member-id="${memberId}"
1463
+ style="
1464
+ width: 20px;
1465
+ height: 20px;
1466
+ border: 2px solid #9ca3af;
1467
+ border-radius: 4px;
1468
+ background: transparent;
1469
+ cursor: pointer;
1470
+ position: relative;
1471
+ display: inline-block;
1472
+ margin: 0 auto;
1473
+ "></div>
1474
+ `;
1475
+ }
1476
+ clearCheckboxCache() {
1477
+ this.checkboxHtmlCache.clear();
1478
+ }
1479
+ enhanceGridData(data) {
1480
+ return data.map((row) => {
1481
+ const enhancedData = {
1482
+ ...row.data,
1483
+ checkbox: this.createCheckboxHtml(row.data.id)
1484
+ };
1485
+ return {
1486
+ ...row,
1487
+ data: enhancedData
1488
+ };
1489
+ });
1490
+ }
1491
+ onCellClicked(event) {
1492
+ if (event.colName === 'checkbox' && event.data?.id) {
1493
+ const memberId = event.data.id;
1494
+ this.toggleCheckbox(memberId);
1495
+ }
1496
+ }
1497
+ toggleCheckbox(memberId) {
1498
+ const wasChecked = this.checkedRows.has(memberId);
1499
+ if (wasChecked) {
1500
+ this.checkedRows.delete(memberId);
1501
+ }
1502
+ else {
1503
+ this.checkedRows.add(memberId);
1504
+ }
1505
+ this.checkboxHtmlCache.delete(`${memberId}-${wasChecked}`);
1506
+ this.checkboxHtmlCache.delete(`${memberId}-${!wasChecked}`);
1507
+ this.updateSingleRow(memberId);
1508
+ }
1509
+ updateSingleRow(memberId) {
1510
+ const rowIndex = this.gridData.findIndex(row => row.data.id === memberId);
1511
+ if (rowIndex !== -1) {
1512
+ const newCheckboxHtml = this.createCheckboxHtml(memberId);
1513
+ const updatedGridData = [...this.gridData];
1514
+ updatedGridData[rowIndex] = {
1515
+ ...updatedGridData[rowIndex],
1516
+ data: {
1517
+ ...updatedGridData[rowIndex].data,
1518
+ checkbox: newCheckboxHtml
1519
+ }
1520
+ };
1521
+ this.gridData = updatedGridData;
1522
+ this.cdr.markForCheck();
1523
+ }
1524
+ }
1525
+ updateGridData() {
1526
+ this.clearCheckboxCache();
1527
+ const newGridData = this.gridData.map((row) => {
1528
+ const enhancedData = {
1529
+ ...row.data,
1530
+ checkbox: this.createCheckboxHtml(row.data.id)
1531
+ };
1532
+ return {
1533
+ ...row,
1534
+ data: enhancedData
1535
+ };
1536
+ });
1537
+ this.gridData = [...newGridData];
1538
+ this.cdr.markForCheck();
1539
+ }
1540
+ loadGridData() {
1541
+ const request = {
1542
+ from: 0,
1543
+ size: this.rowsPerPage,
1544
+ sortField: this.sortField,
1545
+ sortDirection: this.sortOrder,
1546
+ searchString: ''
1547
+ };
1548
+ this.isLoading = true;
1549
+ this.waitlistGridService.getWaitlistMembers(request)
1550
+ .pipe(takeUntil(this.destroy$))
1551
+ .subscribe({
1552
+ next: (response) => {
1553
+ this.clearCheckboxCache();
1554
+ this.gridData = this.enhanceGridData(response.data);
1555
+ this.totalRecords = response.count;
1556
+ this.isLoading = false;
1557
+ this.cdr.markForCheck();
1558
+ },
1559
+ error: (error) => {
1560
+ this.isLoading = false;
1561
+ this.cdr.markForCheck();
1562
+ }
1563
+ });
1564
+ }
1565
+ onLazyLoad(event) {
1566
+ this.isLoading = true;
1567
+ this.waitlistGridService.getWaitlistMembers(event)
1568
+ .pipe(takeUntil(this.destroy$))
1569
+ .subscribe({
1570
+ next: (response) => {
1571
+ this.clearCheckboxCache();
1572
+ this.gridData = this.enhanceGridData(response.data);
1573
+ this.totalRecords = response.count;
1574
+ this.isLoading = false;
1575
+ this.cdr.markForCheck();
1576
+ },
1577
+ error: (error) => {
1578
+ this.isLoading = false;
1579
+ this.cdr.markForCheck();
1580
+ }
1581
+ });
1582
+ }
1583
+ setFilter(filter) {
1584
+ this.activeFilter = filter;
1585
+ this.applyFilter();
1586
+ }
1587
+ applyFilter() {
1588
+ const request = {
1589
+ from: 0,
1590
+ size: this.rowsPerPage,
1591
+ sortField: this.sortField,
1592
+ sortDirection: this.sortOrder,
1593
+ searchString: '',
1594
+ userFilters: this.getUserFilters()
1595
+ };
1596
+ this.isLoading = true;
1597
+ this.waitlistGridService.getWaitlistMembers(request)
1598
+ .pipe(takeUntil(this.destroy$))
1599
+ .subscribe({
1600
+ next: (response) => {
1601
+ this.clearCheckboxCache();
1602
+ this.gridData = this.enhanceGridData(response.data);
1603
+ this.totalRecords = response.count;
1604
+ this.isLoading = false;
1605
+ this.cdr.markForCheck();
1606
+ },
1607
+ error: (error) => {
1608
+ this.isLoading = false;
1609
+ this.cdr.markForCheck();
1610
+ }
1611
+ });
1612
+ }
1613
+ getUserFilters() {
1614
+ switch (this.activeFilter) {
1615
+ case 'high': return [{ publicFieldName: 'priority', operatorType: 'Equals', values: ['high'] }];
1616
+ case 'standard': return [{ publicFieldName: 'userType', operatorType: 'Equals', values: ['standard'] }];
1617
+ case 'premium': return [{ publicFieldName: 'userType', operatorType: 'Equals', values: ['premium'] }];
1618
+ case 'vip': return [{ publicFieldName: 'userType', operatorType: 'Equals', values: ['vip'] }];
1619
+ default: return [];
1620
+ }
1621
+ }
1622
+ getFilterDisplayName(filter) {
1623
+ const names = { 'all': 'All Members', 'high': 'High Priority', 'standard': 'Standard', 'premium': 'Premium', 'vip': 'VIP' };
1624
+ return names[filter];
1625
+ }
1626
+ selectAll() {
1627
+ this.clearCheckboxCache();
1628
+ this.gridData.forEach(row => this.checkedRows.add(row.data.id));
1629
+ this.updateGridData();
1630
+ }
1631
+ clearAll() {
1632
+ this.clearCheckboxCache();
1633
+ this.checkedRows.clear();
1634
+ this.updateGridData();
1635
+ }
1636
+ openConvertModal() {
1637
+ if (this.checkedRows.size === 0) {
1638
+ return;
1639
+ }
1640
+ const selectedMembers = this.getSelectedMembers();
1641
+ const dialogRef = this.dialog.open(ConvertToInvitationDialogComponent, {
1642
+ width: 'auto',
1643
+ maxWidth: '500px',
1644
+ maxHeight: '85vh',
1645
+ panelClass: 'convert-to-invitation-dialog',
1646
+ autoFocus: false,
1647
+ disableClose: true,
1648
+ data: {
1649
+ selectedMembers: selectedMembers,
1650
+ selectedCount: this.checkedRows.size
1651
+ }
1652
+ });
1653
+ dialogRef.afterClosed().subscribe((result) => {
1654
+ if (result) {
1655
+ this.convertToInvitations(result);
1656
+ }
1657
+ });
1658
+ }
1659
+ convertToInvitations(data) {
1660
+ const conversionData = {
1661
+ waitlistMemberIds: data.selectedMemberIds,
1662
+ expiryDays: data.expiryDays,
1663
+ accessLevel: data.accessLevel || 'basic'
1664
+ };
1665
+ this.isConverting = true;
1666
+ this.waitlistGridService.bulkConvertToInvitations(conversionData).subscribe({
1667
+ next: (response) => {
1668
+ this.checkedRows.clear();
1669
+ this.clearCheckboxCache();
1670
+ this.isConverting = false;
1671
+ },
1672
+ error: (error) => {
1673
+ this.isConverting = false;
1674
+ }
1675
+ });
1676
+ }
1677
+ getSelectedMembers() {
1678
+ return this.gridData
1679
+ .filter(row => this.checkedRows.has(row.data.id))
1680
+ .map(row => {
1681
+ const { checkbox, ...memberData } = row.data;
1682
+ return memberData;
1683
+ });
1684
+ }
1685
+ static ɵfac = function WaitlistComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WaitlistComponent)(i0.ɵɵdirectiveInject(WaitlistGridService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1$1.MatDialog)); };
1686
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: WaitlistComponent, selectors: [["app-waitlist"]], standalone: false, decls: 18, vars: 18, consts: [[1, "waitlist-page", "min-h-screen"], [1, "waitlist-container"], [1, "main-grid-section", "p-6"], [1, "code-management-header", "mb-6", "p-3"], [1, "flex", "flex-col", "lg:flex-row", "lg:items-center", "lg:justify-between"], [1, "mb-4", "lg:mb-0"], [1, "text-xl", "font-semibold", "text-white", "mb-2"], [1, "text-gray-400", "text-sm"], ["class", "flex space-x-2", 4, "ngIf"], [1, "filter-tabs", "mb-6"], [1, "filter-container", "p-1.5", "bg-gray-800", "border", "border-gray-700", "rounded-xl", "w-fit"], [1, "flex", "space-x-0.5"], [3, "class", "click", 4, "ngFor", "ngForOf"], [1, "grid-placeholder", "bg-gray-800", "rounded-lg", "border", "border-gray-700"], [1, "dark-theme-grid", "w-full", 3, "lazyLoad", "cellClicked", "data", "columns", "isLoading", "totalRecords", "rowsPerPage", "rowsPerPageOptions", "sortField", "sortOrder", "enableSelection", "enableCreate", "enableRefresh", "enableTrash", "enableGridFilters", "hideToolbar", "hideSettings", "hideRowMenu"], [1, "flex", "space-x-2"], ["mat-raised-button", "", "color", "primary", 1, "!bg-blue-600", "hover:!bg-blue-700", "flex", "items-center", "gap-2", 3, "click"], [1, "!text-lg"], [3, "click"]], template: function WaitlistComponent_Template(rf, ctx) { if (rf & 1) {
1687
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1);
1688
+ i0.ɵɵelement(2, "app-waitlist-stats-overview");
1689
+ i0.ɵɵelementEnd();
1690
+ i0.ɵɵelementStart(3, "div", 2)(4, "div", 3)(5, "div", 4)(6, "div", 5)(7, "h3", 6);
1691
+ i0.ɵɵtext(8, "Waitlist Members");
1692
+ i0.ɵɵelementEnd();
1693
+ i0.ɵɵelementStart(9, "p", 7);
1694
+ i0.ɵɵtext(10, " Manage waitlist and convert members to invitation codes ");
1695
+ i0.ɵɵelementEnd()();
1696
+ i0.ɵɵtemplate(11, WaitlistComponent_div_11_Template, 5, 1, "div", 8);
1697
+ i0.ɵɵelementEnd()();
1698
+ i0.ɵɵelementStart(12, "div", 9)(13, "div", 10)(14, "div", 11);
1699
+ i0.ɵɵtemplate(15, WaitlistComponent_button_15_Template, 2, 3, "button", 12);
1700
+ i0.ɵɵelementEnd()()();
1701
+ i0.ɵɵelementStart(16, "div", 13)(17, "lib-grid", 14);
1702
+ i0.ɵɵlistener("lazyLoad", function WaitlistComponent_Template_lib_grid_lazyLoad_17_listener($event) { return ctx.onLazyLoad($event); })("cellClicked", function WaitlistComponent_Template_lib_grid_cellClicked_17_listener($event) { return ctx.onCellClicked($event); });
1703
+ i0.ɵɵelementEnd()()()();
1704
+ } if (rf & 2) {
1705
+ i0.ɵɵadvance(11);
1706
+ i0.ɵɵproperty("ngIf", ctx.checkedRows.size > 0);
1707
+ i0.ɵɵadvance(4);
1708
+ i0.ɵɵproperty("ngForOf", ctx.filters);
1709
+ i0.ɵɵadvance(2);
1710
+ i0.ɵɵproperty("data", ctx.gridData)("columns", ctx.columns)("isLoading", ctx.isLoading)("totalRecords", ctx.totalRecords)("rowsPerPage", ctx.rowsPerPage)("rowsPerPageOptions", ctx.rowsPerPageOptions)("sortField", ctx.sortField)("sortOrder", ctx.sortOrder)("enableSelection", false)("enableCreate", false)("enableRefresh", false)("enableTrash", false)("enableGridFilters", false)("hideToolbar", true)("hideSettings", true)("hideRowMenu", false);
1711
+ } }, styles: [".main-grid-section[_ngcontent-%COMP%]{border:2px solid #423D48;border-radius:10px;margin-top:35px;background:#29252d}[_nghost-%COMP%] lib-grid.dark-theme-grid .grid-cell-text{position:relative!important;min-height:48px!important;display:flex!important;align-items:center!important;transition:all .2s ease!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell:nth-of-type(2) .grid-cell-text:before{content:\"Name\"!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell:nth-of-type(3) .grid-cell-text:before{content:\"Email\"!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell:nth-of-type(4) .grid-cell-text:before{content:\"User Type\"!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell:nth-of-type(5) .grid-cell-text:before{content:\"Priority\"!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell:nth-of-type(6) .grid-cell-text:before{content:\"Joined\"!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell:nth-of-type(7) .grid-cell-text:before{content:\"Wait Time\"!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell:nth-of-type(8) .grid-cell-text:before{content:\"Notes\"!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .grid-cell-text:before{color:#fff!important;font-weight:400!important;font-size:14px!important;font-family:Roboto,sans-serif!important;z-index:10!important;transition:color .2s ease!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .p-button-icon{display:none!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell:hover .grid-cell-text:before{color:#000!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell .p-datatable-column-sorted .grid-cell-text:before, [_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell .grid-cell-text.p-datatable-column-sorted:before, [_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell[aria-sort] .grid-cell-text:before{color:#000!important}[_nghost-%COMP%] lib-grid.dark-theme-grid th.grid-cell:hover{transition:background-color .2s ease!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .grid-cell-text .ng-star-inserted{margin-left:auto!important;margin-right:8px!important;transition:filter .2s ease!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .filter-toolbar-top-container{display:none!important;height:0!important;min-height:0!important;padding:0!important;margin:0!important;border:none!important;visibility:hidden!important;opacity:0!important}[_nghost-%COMP%] lib-grid.dark-theme-grid td[alignfrozen=left]:empty{display:none!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .p-datatable-wrapper{overflow-x:auto!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .checkbox-header{background:#374151!important;border-left:1px solid #423D48!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .checkbox-cell{border-left:1px solid #423D48!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .checkbox-cell .custom-grid-checkbox:hover{border-color:#6b7280!important;background-color:#6b72801a!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .checkbox-cell .custom-grid-checkbox.checked:hover{background-color:#2563eb!important;border-color:#2563eb!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .grid-row-menu-button, [_nghost-%COMP%] lib-grid.dark-theme-grid [alignfrozen=left]{padding:0 40px 0 0!important;text-align:center!important;vertical-align:middle!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .grid-row-menu-button button, [_nghost-%COMP%] lib-grid.dark-theme-grid [alignfrozen=left] button{all:initial!important;width:32px!important;height:32px!important;min-width:32px!important;min-height:32px!important;display:inline-block!important;position:relative!important;cursor:pointer!important;margin:0 auto!important;border:none!important;background:none!important;padding:0!important;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDQgMTYiIGZpbGw9IiM5Y2EzYWYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjIiLz48Y2lyY2xlIGN4PSIyIiBjeT0iOCIgcj0iMiIvPjxjaXJjbGUgY3g9IjIiIGN5PSIxNCIgcj0iMiIvPjwvc3ZnPg==)!important;background-repeat:no-repeat!important;background-position:center!important;background-size:4px 16px!important;border-radius:6px!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .grid-row-menu-button button:hover, [_nghost-%COMP%] lib-grid.dark-theme-grid [alignfrozen=left] button:hover{background-color:#4b5563!important;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDQgMTYiIGZpbGw9IiM5Y2EzYWYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjIiLz48Y2lyY2xlIGN4PSIyIiBjeT0iOCIgcj0iMiIvPjxjaXJjbGUgY3g9IjIiIGN5PSIxNCIgcj0iMiIvPjwvc3ZnPg==)!important}[_nghost-%COMP%] lib-grid.dark-theme-grid .grid-row-menu-button button i, [_nghost-%COMP%] lib-grid.dark-theme-grid [alignfrozen=left] button i, [_nghost-%COMP%] lib-grid.dark-theme-grid .pi-ellipsis-v{display:none!important;width:0!important;height:0!important;font-size:0!important;visibility:hidden!important;opacity:0!important}[_nghost-%COMP%] .dark-theme-grid .p-datatable{justify-content:center;align-items:center}[_nghost-%COMP%] .dark-theme-grid .p-menu-list{background:#fff!important}.filter-container[_ngcontent-%COMP%]{position:relative;display:inline-block;border:2px solid #423D48;padding:3px;border-radius:20px}.filter-container[_ngcontent-%COMP%]:before{content:\"\";position:absolute;inset:1.5px;background:transparent;border-radius:20px;z-index:0;transition:all .2s ease}.filter-container[_ngcontent-%COMP%] .flex[_ngcontent-%COMP%]{position:relative;z-index:1}.filter-container[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{position:relative;z-index:2;min-width:80px;all:unset;cursor:pointer;text-align:center;padding:.5rem 1rem;border-radius:16px;font-size:.875rem;font-weight:500;transition:all .2s ease}.filter-container[_ngcontent-%COMP%] button.selected-filter[_ngcontent-%COMP%]{background-color:#374151;color:#fff;border:1px solid #4b5563;box-shadow:0 1px 2px #0000001a}.filter-container[_ngcontent-%COMP%] button.unselected-filter[_ngcontent-%COMP%]{background-color:transparent;color:#d1d5db;border:1px solid transparent}.filter-container[_ngcontent-%COMP%] button.unselected-filter[_ngcontent-%COMP%]:hover{background-color:#4b556333;color:#fff}"] });
1712
+ }
1713
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WaitlistComponent, [{
1714
+ type: Component,
1715
+ args: [{ selector: 'app-waitlist', standalone: false, template: "<div class=\"waitlist-page min-h-screen\">\r\n <div class=\"waitlist-container\">\r\n <app-waitlist-stats-overview></app-waitlist-stats-overview>\r\n </div>\r\n\r\n <div class=\"main-grid-section p-6\">\r\n <!-- Header Section -->\r\n <div class=\"code-management-header mb-6 p-3\">\r\n <div class=\"flex flex-col lg:flex-row lg:items-center lg:justify-between\">\r\n <div class=\"mb-4 lg:mb-0\">\r\n <h3 class=\"text-xl font-semibold text-white mb-2\">Waitlist Members</h3>\r\n <p class=\"text-gray-400 text-sm\">\r\n Manage waitlist and convert members to invitation codes\r\n </p>\r\n </div>\r\n <div class=\"flex space-x-2\" *ngIf=\"checkedRows.size > 0\">\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"openConvertModal()\"\r\n class=\"!bg-blue-600 hover:!bg-blue-700 flex items-center gap-2\">\r\n <mat-icon class=\"!text-lg\">send</mat-icon>\r\n Convert {{checkedRows.size}} to Invite\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filter Tabs -->\r\n <div class=\"filter-tabs mb-6\">\r\n <div class=\"filter-container p-1.5 bg-gray-800 border border-gray-700 rounded-xl w-fit\">\r\n <div class=\"flex space-x-0.5\">\r\n <button\r\n *ngFor=\"let filter of filters\"\r\n (click)=\"setFilter(filter)\"\r\n [class]=\"activeFilter === filter\r\n ? 'selected-filter px-4 py-2 text-sm font-medium transition-colors'\r\n : 'unselected-filter px-4 py-2 text-sm font-medium transition-colors'\">\r\n {{ getFilterDisplayName(filter) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Grid Section with click handler -->\r\n <div class=\"grid-placeholder bg-gray-800 rounded-lg border border-gray-700\">\r\n <lib-grid\r\n [data]=\"gridData\"\r\n [columns]=\"columns\"\r\n [isLoading]=\"isLoading\"\r\n [totalRecords]=\"totalRecords\"\r\n [rowsPerPage]=\"rowsPerPage\"\r\n [rowsPerPageOptions]=\"rowsPerPageOptions\"\r\n [sortField]=\"sortField\"\r\n [sortOrder]=\"sortOrder\"\r\n [enableSelection]=\"false\"\r\n [enableCreate]=\"false\"\r\n [enableRefresh]=\"false\"\r\n [enableTrash]=\"false\"\r\n [enableGridFilters]=\"false\"\r\n [hideToolbar]=\"true\"\r\n [hideSettings]=\"true\"\r\n [hideRowMenu]=\"false\"\r\n (lazyLoad)=\"onLazyLoad($event)\"\r\n (cellClicked)=\"onCellClicked($event)\"\r\n class=\"dark-theme-grid w-full\">\r\n </lib-grid>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".main-grid-section{border:2px solid #423D48;border-radius:10px;margin-top:35px;background:#29252d}:host ::ng-deep lib-grid.dark-theme-grid .grid-cell-text{position:relative!important;min-height:48px!important;display:flex!important;align-items:center!important;transition:all .2s ease!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell:nth-of-type(2) .grid-cell-text:before{content:\"Name\"!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell:nth-of-type(3) .grid-cell-text:before{content:\"Email\"!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell:nth-of-type(4) .grid-cell-text:before{content:\"User Type\"!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell:nth-of-type(5) .grid-cell-text:before{content:\"Priority\"!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell:nth-of-type(6) .grid-cell-text:before{content:\"Joined\"!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell:nth-of-type(7) .grid-cell-text:before{content:\"Wait Time\"!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell:nth-of-type(8) .grid-cell-text:before{content:\"Notes\"!important}:host ::ng-deep lib-grid.dark-theme-grid .grid-cell-text:before{color:#fff!important;font-weight:400!important;font-size:14px!important;font-family:Roboto,sans-serif!important;z-index:10!important;transition:color .2s ease!important}:host ::ng-deep lib-grid.dark-theme-grid .p-button-icon{display:none!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell:hover .grid-cell-text:before{color:#000!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell .p-datatable-column-sorted .grid-cell-text:before,:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell .grid-cell-text.p-datatable-column-sorted:before,:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell[aria-sort] .grid-cell-text:before{color:#000!important}:host ::ng-deep lib-grid.dark-theme-grid th.grid-cell:hover{transition:background-color .2s ease!important}:host ::ng-deep lib-grid.dark-theme-grid .grid-cell-text .ng-star-inserted{margin-left:auto!important;margin-right:8px!important;transition:filter .2s ease!important}:host ::ng-deep lib-grid.dark-theme-grid .filter-toolbar-top-container{display:none!important;height:0!important;min-height:0!important;padding:0!important;margin:0!important;border:none!important;visibility:hidden!important;opacity:0!important}:host ::ng-deep lib-grid.dark-theme-grid td[alignfrozen=left]:empty{display:none!important}:host ::ng-deep lib-grid.dark-theme-grid .p-datatable-wrapper{overflow-x:auto!important}:host ::ng-deep lib-grid.dark-theme-grid .checkbox-header{background:#374151!important;border-left:1px solid #423D48!important}:host ::ng-deep lib-grid.dark-theme-grid .checkbox-cell{border-left:1px solid #423D48!important}:host ::ng-deep lib-grid.dark-theme-grid .checkbox-cell .custom-grid-checkbox:hover{border-color:#6b7280!important;background-color:#6b72801a!important}:host ::ng-deep lib-grid.dark-theme-grid .checkbox-cell .custom-grid-checkbox.checked:hover{background-color:#2563eb!important;border-color:#2563eb!important}:host ::ng-deep lib-grid.dark-theme-grid .grid-row-menu-button,:host ::ng-deep lib-grid.dark-theme-grid [alignfrozen=left]{padding:0 40px 0 0!important;text-align:center!important;vertical-align:middle!important}:host ::ng-deep lib-grid.dark-theme-grid .grid-row-menu-button button,:host ::ng-deep lib-grid.dark-theme-grid [alignfrozen=left] button{all:initial!important;width:32px!important;height:32px!important;min-width:32px!important;min-height:32px!important;display:inline-block!important;position:relative!important;cursor:pointer!important;margin:0 auto!important;border:none!important;background:none!important;padding:0!important;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDQgMTYiIGZpbGw9IiM5Y2EzYWYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjIiLz48Y2lyY2xlIGN4PSIyIiBjeT0iOCIgcj0iMiIvPjxjaXJjbGUgY3g9IjIiIGN5PSIxNCIgcj0iMiIvPjwvc3ZnPg==)!important;background-repeat:no-repeat!important;background-position:center!important;background-size:4px 16px!important;border-radius:6px!important}:host ::ng-deep lib-grid.dark-theme-grid .grid-row-menu-button button:hover,:host ::ng-deep lib-grid.dark-theme-grid [alignfrozen=left] button:hover{background-color:#4b5563!important;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNCIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDQgMTYiIGZpbGw9IiM5Y2EzYWYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjIiLz48Y2lyY2xlIGN4PSIyIiBjeT0iOCIgcj0iMiIvPjxjaXJjbGUgY3g9IjIiIGN5PSIxNCIgcj0iMiIvPjwvc3ZnPg==)!important}:host ::ng-deep lib-grid.dark-theme-grid .grid-row-menu-button button i,:host ::ng-deep lib-grid.dark-theme-grid [alignfrozen=left] button i,:host ::ng-deep lib-grid.dark-theme-grid .pi-ellipsis-v{display:none!important;width:0!important;height:0!important;font-size:0!important;visibility:hidden!important;opacity:0!important}:host ::ng-deep .dark-theme-grid .p-datatable{justify-content:center;align-items:center}:host ::ng-deep .dark-theme-grid .p-menu-list{background:#fff!important}.filter-container{position:relative;display:inline-block;border:2px solid #423D48;padding:3px;border-radius:20px}.filter-container:before{content:\"\";position:absolute;inset:1.5px;background:transparent;border-radius:20px;z-index:0;transition:all .2s ease}.filter-container .flex{position:relative;z-index:1}.filter-container button{position:relative;z-index:2;min-width:80px;all:unset;cursor:pointer;text-align:center;padding:.5rem 1rem;border-radius:16px;font-size:.875rem;font-weight:500;transition:all .2s ease}.filter-container button.selected-filter{background-color:#374151;color:#fff;border:1px solid #4b5563;box-shadow:0 1px 2px #0000001a}.filter-container button.unselected-filter{background-color:transparent;color:#d1d5db;border:1px solid transparent}.filter-container button.unselected-filter:hover{background-color:#4b556333;color:#fff}\n"] }]
1716
+ }], () => [{ type: WaitlistGridService }, { type: i0.ChangeDetectorRef }, { type: i1$1.MatDialog }], null); })();
1717
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WaitlistComponent, { className: "WaitlistComponent", filePath: "lib/pages/waitlist/waitlist.component.ts", lineNumber: 18 }); })();
1718
+
1719
+ class CodeManagementHeaderComponent {
1720
+ activeTab = 'codes';
1721
+ activeFilter = 'all';
1722
+ tabChanged = new EventEmitter();
1723
+ filterChanged = new EventEmitter();
1724
+ setActiveTab(tab) {
1725
+ this.activeTab = tab;
1726
+ this.tabChanged.emit(tab);
1727
+ }
1728
+ setActiveFilter(filter) {
1729
+ this.activeFilter = filter;
1730
+ this.filterChanged.emit(filter);
1731
+ }
1732
+ static ɵfac = function CodeManagementHeaderComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CodeManagementHeaderComponent)(); };
1733
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CodeManagementHeaderComponent, selectors: [["app-code-management-header"]], outputs: { tabChanged: "tabChanged", filterChanged: "filterChanged" }, standalone: false, decls: 7, vars: 4, consts: [[1, "mb-6"], [1, "tab-container", "p-1.5", "bg-gray-800", "border", "border-gray-700", "rounded-xl", "w-fit"], [1, "flex", "space-x-0.5"], [3, "click"]], template: function CodeManagementHeaderComponent_Template(rf, ctx) { if (rf & 1) {
1734
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "button", 3);
1735
+ i0.ɵɵlistener("click", function CodeManagementHeaderComponent_Template_button_click_3_listener() { return ctx.setActiveTab("codes"); });
1736
+ i0.ɵɵtext(4, " Invitation Codes ");
1737
+ i0.ɵɵelementEnd();
1738
+ i0.ɵɵelementStart(5, "button", 3);
1739
+ i0.ɵɵlistener("click", function CodeManagementHeaderComponent_Template_button_click_5_listener() { return ctx.setActiveTab("waitlist"); });
1740
+ i0.ɵɵtext(6, " Waitlist ");
1741
+ i0.ɵɵelementEnd()()()();
1742
+ } if (rf & 2) {
1743
+ i0.ɵɵadvance(3);
1744
+ i0.ɵɵclassMap(ctx.activeTab === "codes" ? "selected-tab px-4 py-2 text-sm font-medium transition-colors" : "unselected-tab px-4 py-2 text-sm font-medium transition-colors");
1745
+ i0.ɵɵadvance(2);
1746
+ i0.ɵɵclassMap(ctx.activeTab === "waitlist" ? "selected-tab px-4 py-2 text-sm font-medium transition-colors" : "unselected-tab px-4 py-2 text-sm font-medium transition-colors");
1747
+ } }, styles: [".tab-container[_ngcontent-%COMP%]{position:relative;display:inline-block;border:2px solid #423D48;padding:3px;border-radius:20px}.tab-container[_ngcontent-%COMP%]:before{content:\"\";position:absolute;inset:1.5px;background:transparent;border-radius:20px;z-index:0;transition:all .2s ease}.tab-container[_ngcontent-%COMP%] .flex[_ngcontent-%COMP%]{position:relative;z-index:1}.tab-container[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{position:relative;z-index:2;min-width:120px;all:unset;cursor:pointer;text-align:center;padding:.5rem 1rem;border-radius:16px;font-size:.875rem;font-weight:500;transition:all .2s ease}.tab-container[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:first-child{margin-left:0}.tab-container[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:last-child{margin-right:0}.tab-container[_ngcontent-%COMP%] button.selected-tab[_ngcontent-%COMP%]{background-color:#374151;color:#fff;border:1px solid #4b5563;box-shadow:0 1px 2px #0000001a}.tab-container[_ngcontent-%COMP%] button.unselected-tab[_ngcontent-%COMP%]{background-color:transparent;color:#d1d5db;border:1px solid transparent}.tab-container[_ngcontent-%COMP%] button.unselected-tab[_ngcontent-%COMP%]:hover{background-color:#4b556333;color:#fff}"] });
1748
+ }
1749
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CodeManagementHeaderComponent, [{
1750
+ type: Component,
1751
+ args: [{ selector: 'app-code-management-header', standalone: false, template: "<div class=\"mb-6\">\r\n <!-- Tab Navigation -->\r\n <div class=\"tab-container p-1.5 bg-gray-800 border border-gray-700 rounded-xl w-fit\">\r\n <div class=\"flex space-x-0.5\">\r\n <button\r\n (click)=\"setActiveTab('codes')\"\r\n [class]=\"activeTab === 'codes'\r\n ? 'selected-tab px-4 py-2 text-sm font-medium transition-colors'\r\n : 'unselected-tab px-4 py-2 text-sm font-medium transition-colors'\">\r\n Invitation Codes\r\n </button>\r\n <button\r\n (click)=\"setActiveTab('waitlist')\"\r\n [class]=\"activeTab === 'waitlist'\r\n ? 'selected-tab px-4 py-2 text-sm font-medium transition-colors'\r\n : 'unselected-tab px-4 py-2 text-sm font-medium transition-colors'\">\r\n Waitlist\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".tab-container{position:relative;display:inline-block;border:2px solid #423D48;padding:3px;border-radius:20px}.tab-container:before{content:\"\";position:absolute;inset:1.5px;background:transparent;border-radius:20px;z-index:0;transition:all .2s ease}.tab-container .flex{position:relative;z-index:1}.tab-container button{position:relative;z-index:2;min-width:120px;all:unset;cursor:pointer;text-align:center;padding:.5rem 1rem;border-radius:16px;font-size:.875rem;font-weight:500;transition:all .2s ease}.tab-container button:first-child{margin-left:0}.tab-container button:last-child{margin-right:0}.tab-container button.selected-tab{background-color:#374151;color:#fff;border:1px solid #4b5563;box-shadow:0 1px 2px #0000001a}.tab-container button.unselected-tab{background-color:transparent;color:#d1d5db;border:1px solid transparent}.tab-container button.unselected-tab:hover{background-color:#4b556333;color:#fff}\n"] }]
1752
+ }], null, { tabChanged: [{
1753
+ type: Output
1754
+ }], filterChanged: [{
1755
+ type: Output
1756
+ }] }); })();
1757
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CodeManagementHeaderComponent, { className: "CodeManagementHeaderComponent", filePath: "lib/components/code-management-header/code-management-header.component.ts", lineNumber: 12 }); })();
1758
+
1759
+ // generate-code-dialog.component.ts
1760
+ function GenerateCodeDialogComponent_button_53_Template(rf, ctx) { if (rf & 1) {
1761
+ const _r1 = i0.ɵɵgetCurrentView();
1762
+ i0.ɵɵelementStart(0, "button", 29);
1763
+ i0.ɵɵlistener("click", function GenerateCodeDialogComponent_button_53_Template_button_click_0_listener() { const level_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectAccessLevel(level_r2.value)); });
1764
+ i0.ɵɵelementStart(1, "div", 30)(2, "mat-icon", 31);
1765
+ i0.ɵɵtext(3);
1766
+ i0.ɵɵelementEnd()();
1767
+ i0.ɵɵelementStart(4, "div", 32)(5, "div", 33)(6, "span", 34);
1768
+ i0.ɵɵtext(7);
1769
+ i0.ɵɵelementEnd()();
1770
+ i0.ɵɵelementStart(8, "div", 35);
1771
+ i0.ɵɵtext(9);
1772
+ i0.ɵɵelementEnd()()();
1773
+ } if (rf & 2) {
1774
+ let tmp_2_0;
1775
+ const level_r2 = ctx.$implicit;
1776
+ const ctx_r2 = i0.ɵɵnextContext();
1777
+ i0.ɵɵclassMap(((tmp_2_0 = ctx_r2.codeForm.get("accessLevel")) == null ? null : tmp_2_0.value) === level_r2.value ? "access-level-selected bg-blue-900/30 border-blue-500 text-blue-300" : "access-level-unselected bg-gray-800/50 border-gray-700 text-gray-300");
1778
+ i0.ɵɵadvance();
1779
+ i0.ɵɵclassMap(ctx_r2.getLevelIconClass(level_r2.value));
1780
+ i0.ɵɵadvance(2);
1781
+ i0.ɵɵtextInterpolate(ctx_r2.getLevelIcon(level_r2.value));
1782
+ i0.ɵɵadvance(4);
1783
+ i0.ɵɵtextInterpolate(level_r2.label);
1784
+ i0.ɵɵadvance(2);
1785
+ i0.ɵɵtextInterpolate1(" ", level_r2.description, " ");
1786
+ } }
1787
+ function GenerateCodeDialogComponent_div_54_Template(rf, ctx) { if (rf & 1) {
1788
+ const _r4 = i0.ɵɵgetCurrentView();
1789
+ i0.ɵɵelementStart(0, "div", 36)(1, "div", 37)(2, "span", 38);
1790
+ i0.ɵɵtext(3, "Generated Code:");
1791
+ i0.ɵɵelementEnd();
1792
+ i0.ɵɵelementStart(4, "button", 39);
1793
+ i0.ɵɵlistener("click", function GenerateCodeDialogComponent_div_54_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.copyToClipboard()); });
1794
+ i0.ɵɵelementStart(5, "mat-icon", 40);
1795
+ i0.ɵɵtext(6, "content_copy");
1796
+ i0.ɵɵelementEnd();
1797
+ i0.ɵɵelementStart(7, "span");
1798
+ i0.ɵɵtext(8, "Copy");
1799
+ i0.ɵɵelementEnd()()();
1800
+ i0.ɵɵelementStart(9, "div", 41)(10, "code", 42);
1801
+ i0.ɵɵtext(11);
1802
+ i0.ɵɵelementEnd()();
1803
+ i0.ɵɵelementStart(12, "p", 43);
1804
+ i0.ɵɵtext(13, "Share this code with users to grant them access");
1805
+ i0.ɵɵelementEnd()();
1806
+ } if (rf & 2) {
1807
+ const ctx_r2 = i0.ɵɵnextContext();
1808
+ i0.ɵɵadvance(11);
1809
+ i0.ɵɵtextInterpolate(ctx_r2.generatedCode);
1810
+ } }
1811
+ function GenerateCodeDialogComponent_div_55_li_7_Template(rf, ctx) { if (rf & 1) {
1812
+ i0.ɵɵelementStart(0, "li");
1813
+ i0.ɵɵtext(1, "Please enter a valid email address");
1814
+ i0.ɵɵelementEnd();
1815
+ } }
1816
+ function GenerateCodeDialogComponent_div_55_li_8_Template(rf, ctx) { if (rf & 1) {
1817
+ i0.ɵɵelementStart(0, "li");
1818
+ i0.ɵɵtext(1, "Maximum uses must be at least 1");
1819
+ i0.ɵɵelementEnd();
1820
+ } }
1821
+ function GenerateCodeDialogComponent_div_55_li_9_Template(rf, ctx) { if (rf & 1) {
1822
+ i0.ɵɵelementStart(0, "li");
1823
+ i0.ɵɵtext(1, "Access level is required");
1824
+ i0.ɵɵelementEnd();
1825
+ } }
1826
+ function GenerateCodeDialogComponent_div_55_Template(rf, ctx) { if (rf & 1) {
1827
+ i0.ɵɵelementStart(0, "div", 44)(1, "div", 45)(2, "mat-icon", 46);
1828
+ i0.ɵɵtext(3, "error");
1829
+ i0.ɵɵelementEnd();
1830
+ i0.ɵɵelementStart(4, "div", 47);
1831
+ i0.ɵɵtext(5, " Please fix the following errors: ");
1832
+ i0.ɵɵelementStart(6, "ul", 48);
1833
+ i0.ɵɵtemplate(7, GenerateCodeDialogComponent_div_55_li_7_Template, 2, 0, "li", 49)(8, GenerateCodeDialogComponent_div_55_li_8_Template, 2, 0, "li", 49)(9, GenerateCodeDialogComponent_div_55_li_9_Template, 2, 0, "li", 49);
1834
+ i0.ɵɵelementEnd()()()();
1835
+ } if (rf & 2) {
1836
+ let tmp_1_0;
1837
+ let tmp_2_0;
1838
+ let tmp_3_0;
1839
+ const ctx_r2 = i0.ɵɵnextContext();
1840
+ i0.ɵɵadvance(7);
1841
+ i0.ɵɵproperty("ngIf", (tmp_1_0 = ctx_r2.codeForm.get("email")) == null ? null : tmp_1_0.hasError("email"));
1842
+ i0.ɵɵadvance();
1843
+ i0.ɵɵproperty("ngIf", (tmp_2_0 = ctx_r2.codeForm.get("maxUses")) == null ? null : tmp_2_0.hasError("min"));
1844
+ i0.ɵɵadvance();
1845
+ i0.ɵɵproperty("ngIf", (tmp_3_0 = ctx_r2.codeForm.get("accessLevel")) == null ? null : tmp_3_0.hasError("required"));
1846
+ } }
1847
+ function GenerateCodeDialogComponent_span_60_Template(rf, ctx) { if (rf & 1) {
1848
+ i0.ɵɵelementStart(0, "span", 15)(1, "mat-icon", 50);
1849
+ i0.ɵɵtext(2, "refresh");
1850
+ i0.ɵɵelementEnd();
1851
+ i0.ɵɵelementStart(3, "span");
1852
+ i0.ɵɵtext(4, "Generating...");
1853
+ i0.ɵɵelementEnd()();
1854
+ } }
1855
+ function GenerateCodeDialogComponent_span_61_Template(rf, ctx) { if (rf & 1) {
1856
+ i0.ɵɵelementStart(0, "span", 15)(1, "mat-icon");
1857
+ i0.ɵɵtext(2, "add");
1858
+ i0.ɵɵelementEnd();
1859
+ i0.ɵɵelementStart(3, "span");
1860
+ i0.ɵɵtext(4, "Generate Code");
1861
+ i0.ɵɵelementEnd()();
1862
+ } }
1863
+ class GenerateCodeDialogComponent {
1864
+ fb;
1865
+ invitationCodeService;
1866
+ dialogRef;
1867
+ data;
1868
+ codeForm;
1869
+ isGenerating = false;
1870
+ generatedCode = null;
1871
+ generatedData = null;
1872
+ showSuccessMessage = false;
1873
+ accessLevels = [
1874
+ {
1875
+ value: 'basic',
1876
+ label: 'Basic Access',
1877
+ description: 'Standard features',
1878
+ icon: 'person',
1879
+ userType: 'standard'
1880
+ },
1881
+ {
1882
+ value: 'premium',
1883
+ label: 'Premium Access',
1884
+ description: 'Advanced features',
1885
+ icon: 'star',
1886
+ userType: 'premium'
1887
+ },
1888
+ {
1889
+ value: 'vip',
1890
+ label: 'VIP Access',
1891
+ description: 'Exclusive features',
1892
+ icon: 'workspace_premium',
1893
+ userType: 'vip'
1894
+ }
1895
+ ];
1896
+ constructor(fb, invitationCodeService, dialogRef, data) {
1897
+ this.fb = fb;
1898
+ this.invitationCodeService = invitationCodeService;
1899
+ this.dialogRef = dialogRef;
1900
+ this.data = data;
1901
+ this.codeForm = this.fb.group({
1902
+ name: ['', [Validators.maxLength(50)]],
1903
+ maxUses: [null, [Validators.min(1)]],
1904
+ expiryDate: [null],
1905
+ accessLevel: ['basic', Validators.required],
1906
+ email: ['', [Validators.email]]
1907
+ });
1908
+ if (data) {
1909
+ this.codeForm.patchValue(data);
1910
+ }
1911
+ this.codeForm.valueChanges.subscribe(() => {
1912
+ this.codeForm.markAsTouched();
1913
+ });
1914
+ }
1915
+ ngOnInit() { }
1916
+ onCancel() {
1917
+ this.dialogRef.close();
1918
+ }
1919
+ onSubmit() {
1920
+ if (this.codeForm.valid) {
1921
+ this.isGenerating = true;
1922
+ this.generatedCode = null;
1923
+ this.generatedData = null;
1924
+ this.showSuccessMessage = false;
1925
+ const formData = this.codeForm.value;
1926
+ // Map access level to userType
1927
+ const selectedAccessLevel = this.accessLevels.find(level => level.value === formData.accessLevel);
1928
+ const userType = selectedAccessLevel?.userType || 'standard';
1929
+ const codeData = {
1930
+ name: formData.name,
1931
+ maxUses: formData.maxUses,
1932
+ expiryDate: formData.expiryDate ? new Date(formData.expiryDate).toISOString() : null,
1933
+ accessLevel: formData.accessLevel,
1934
+ userType: userType,
1935
+ email: formData.email || null
1936
+ };
1937
+ // Call the actual API
1938
+ this.invitationCodeService.generateCode(codeData).subscribe({
1939
+ next: (response) => {
1940
+ this.generatedCode = response.code;
1941
+ this.generatedData = response;
1942
+ this.isGenerating = false;
1943
+ this.showSuccessMessage = true;
1944
+ // Show success alert
1945
+ setTimeout(() => {
1946
+ alert('Invitation code generated successfully!');
1947
+ // Close the dialog and pass success result
1948
+ this.dialogRef.close({
1949
+ success: true,
1950
+ data: response,
1951
+ message: 'Code generated successfully!'
1952
+ });
1953
+ }, 500); // Small delay for better UX
1954
+ },
1955
+ error: (error) => {
1956
+ console.error('Error generating code:', error);
1957
+ this.isGenerating = false;
1958
+ // Show error message
1959
+ alert('Failed to generate code. Please try again.');
1960
+ }
1961
+ });
1962
+ }
1963
+ else {
1964
+ this.markFormGroupTouched(this.codeForm);
1965
+ }
1966
+ }
1967
+ selectAccessLevel(level) {
1968
+ this.codeForm.patchValue({ accessLevel: level });
1969
+ }
1970
+ clearExpiryDate() {
1971
+ this.codeForm.patchValue({ expiryDate: null });
1972
+ }
1973
+ copyToClipboard() {
1974
+ if (this.generatedCode) {
1975
+ navigator.clipboard.writeText(this.generatedCode).then(() => {
1976
+ // Show copied message
1977
+ const originalText = event?.target;
1978
+ if (originalText) {
1979
+ const originalContent = originalText.innerHTML;
1980
+ originalText.innerHTML = '<mat-icon class="!text-base">check</mat-icon><span>Copied!</span>';
1981
+ setTimeout(() => {
1982
+ originalText.innerHTML = originalContent;
1983
+ }, 2000);
1984
+ }
1985
+ }).catch(err => {
1986
+ console.error('Failed to copy: ', err);
1987
+ });
1988
+ }
1989
+ }
1990
+ getLevelIcon(level) {
1991
+ const found = this.accessLevels.find(l => l.value === level);
1992
+ return found?.icon || 'person';
1993
+ }
1994
+ getLevelIconClass(level) {
1995
+ const baseClasses = 'w-8 h-8 rounded-full flex items-center justify-center';
1996
+ switch (level) {
1997
+ case 'basic': return `${baseClasses} bg-blue-500/20 text-blue-400`;
1998
+ case 'premium': return `${baseClasses} bg-yellow-500/20 text-yellow-400`;
1999
+ case 'vip': return `${baseClasses} bg-purple-500/20 text-purple-400`;
2000
+ default: return `${baseClasses} bg-gray-600`;
2001
+ }
2002
+ }
2003
+ markFormGroupTouched(formGroup) {
2004
+ Object.values(formGroup.controls).forEach(control => {
2005
+ control.markAsTouched();
2006
+ if (control instanceof FormGroup) {
2007
+ this.markFormGroupTouched(control);
2008
+ }
2009
+ });
2010
+ }
2011
+ static ɵfac = function GenerateCodeDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || GenerateCodeDialogComponent)(i0.ɵɵdirectiveInject(i1$2.FormBuilder), i0.ɵɵdirectiveInject(InvitationCodeService), i0.ɵɵdirectiveInject(i1$1.MatDialogRef), i0.ɵɵdirectiveInject(MAT_DIALOG_DATA)); };
2012
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: GenerateCodeDialogComponent, selectors: [["app-generate-code-dialog"]], standalone: false, decls: 62, vars: 8, consts: [[1, "generate-code-dialog"], ["mat-dialog-title", "", 1, "text-white", "!pb-2", "!text-xl", "font-semibold"], [1, "!pb-0", "!min-w-[500px]"], [1, "space-y-6"], [1, "text-md", "text-gray-300"], [1, "border-t", "border-gray-700"], [1, "space-y-6", 3, "formGroup"], [1, "form-group"], [1, "block", "text-sm", "font-medium", "text-gray-300", "mb-2"], [1, "text-gray-500", "text-xs", "font-normal"], ["type", "email", "formControlName", "email", "placeholder", "Enter email address (optional)", "email", "", 1, "w-full", "px-4", "py-3", "bg-gray-800", "border", "border-gray-700", "rounded-lg", "text-white", "placeholder-gray-500", "focus:outline-none", "focus:ring-2", "focus:ring-blue-500", "focus:border-transparent", "transition-colors"], [1, "mt-1", "text-xs", "text-gray-500"], ["type", "text", "formControlName", "name", "placeholder", "e.g., VIP Users, Team Beta", "maxlength", "50", 1, "w-full", "px-4", "py-3", "bg-gray-800", "border", "border-gray-700", "rounded-lg", "text-white", "placeholder-gray-500", "focus:outline-none", "focus:ring-2", "focus:ring-blue-500", "focus:border-transparent", "transition-colors"], [1, "mt-1", "text-xs", "text-gray-500", "flex", "justify-between"], ["type", "number", "formControlName", "maxUses", "min", "1", "placeholder", "e.g., 50", 1, "w-full", "px-4", "py-3", "bg-gray-800", "border", "border-gray-700", "rounded-lg", "text-white", "placeholder-gray-500", "focus:outline-none", "focus:ring-2", "focus:ring-blue-500", "focus:border-transparent", "transition-colors"], [1, "flex", "items-center", "space-x-2"], ["type", "date", "formControlName", "expiryDate", 1, "flex-1", "px-4", "py-3", "bg-gray-800", "border", "border-gray-700", "rounded-lg", "text-white", "placeholder-gray-500", "focus:outline-none", "focus:ring-2", "focus:ring-blue-500", "focus:border-transparent", "transition-colors"], ["type", "button", 1, "px-4", "py-3", "text-sm", "text-gray-400", "hover:text-white", "hover:bg-gray-700", "rounded-lg", "transition-colors", "border", "border-gray-600", 3, "click"], [1, "mb-6"], [1, "text-md", "font-medium", "text-white", "mb-2"], [1, "text-red-400"], [1, "grid", "grid-cols-2", "gap-2"], ["type", "button", "class", "access-level-button px-3 py-2.5 rounded-lg border hover:bg-gray-700/50 transition-all duration-200 flex items-start space-x-3", 3, "class", "click", 4, "ngFor", "ngForOf"], ["class", "mt-4 p-4 bg-gray-800/50 border border-gray-700 rounded-lg", 4, "ngIf"], ["class", "mt-4 p-3 bg-red-900/20 border border-red-800/30 rounded-lg", 4, "ngIf"], ["align", "end", 1, "!border-t", "!border-gray-700"], ["mat-stroked-button", "", 1, "!border-gray-600", "!text-gray-300", "hover:!bg-gray-700", "hover:!border-gray-500", 3, "click"], ["mat-raised-button", "", "color", "primary", 1, "!bg-blue-600", "hover:!bg-blue-700", "disabled:!opacity-50", "disabled:!cursor-not-allowed", 3, "click", "disabled"], ["class", "flex items-center space-x-2", 4, "ngIf"], ["type", "button", 1, "access-level-button", "px-3", "py-2.5", "rounded-lg", "border", "hover:bg-gray-700/50", "transition-all", "duration-200", "flex", "items-start", "space-x-3", 3, "click"], [1, "w-8", "h-8", "rounded-lg", "flex", "items-center", "justify-center", "flex-shrink-0", "mt-0.5"], [1, "!text-sm"], [1, "flex-1", "min-w-0"], [1, "flex", "items-center", "justify-between", "mb-1"], [1, "font-medium", "text-sm", "truncate"], [1, "text-xs", "opacity-75", "truncate"], [1, "mt-4", "p-4", "bg-gray-800/50", "border", "border-gray-700", "rounded-lg"], [1, "flex", "items-center", "justify-between", "mb-2"], [1, "text-sm", "font-medium", "text-gray-300"], ["type", "button", 1, "text-sm", "text-blue-400", "hover:text-blue-300", "flex", "items-center", "space-x-1", "transition-colors", 3, "click"], [1, "!text-base"], [1, "bg-gray-900", "p-3", "rounded", "border", "border-gray-700"], [1, "font-mono", "text-lg", "font-bold", "text-green-400", "select-all"], [1, "mt-2", "text-xs", "text-gray-500"], [1, "mt-4", "p-3", "bg-red-900/20", "border", "border-red-800/30", "rounded-lg"], [1, "flex", "items-start", "space-x-2"], [1, "!text-red-400", "!text-lg", "flex-shrink-0"], [1, "text-sm", "text-red-300"], [1, "mt-1", "ml-4", "list-disc", "text-red-400"], [4, "ngIf"], [1, "animate-spin", "!text-lg"]], template: function GenerateCodeDialogComponent_Template(rf, ctx) { if (rf & 1) {
2013
+ i0.ɵɵelementStart(0, "div", 0)(1, "h2", 1);
2014
+ i0.ɵɵtext(2, "Generate Invitation Code");
2015
+ i0.ɵɵelementEnd();
2016
+ i0.ɵɵelementStart(3, "mat-dialog-content", 2)(4, "div", 3)(5, "div", 4);
2017
+ i0.ɵɵtext(6, " Create a new invitation code with custom settings ");
2018
+ i0.ɵɵelementEnd();
2019
+ i0.ɵɵelement(7, "div", 5);
2020
+ i0.ɵɵelementStart(8, "form", 6)(9, "div", 7)(10, "label", 8);
2021
+ i0.ɵɵtext(11, " Email Address ");
2022
+ i0.ɵɵelementStart(12, "span", 9);
2023
+ i0.ɵɵtext(13, "(Optional)");
2024
+ i0.ɵɵelementEnd()();
2025
+ i0.ɵɵelement(14, "input", 10);
2026
+ i0.ɵɵelementStart(15, "p", 11);
2027
+ i0.ɵɵtext(16, "If provided, only this email can use the code");
2028
+ i0.ɵɵelementEnd()();
2029
+ i0.ɵɵelementStart(17, "div", 7)(18, "label", 8);
2030
+ i0.ɵɵtext(19, " Code Name ");
2031
+ i0.ɵɵelementStart(20, "span", 9);
2032
+ i0.ɵɵtext(21, "(Optional)");
2033
+ i0.ɵɵelementEnd()();
2034
+ i0.ɵɵelement(22, "input", 12);
2035
+ i0.ɵɵelementStart(23, "div", 13)(24, "span");
2036
+ i0.ɵɵtext(25, "A descriptive name for this code");
2037
+ i0.ɵɵelementEnd();
2038
+ i0.ɵɵelementStart(26, "span");
2039
+ i0.ɵɵtext(27);
2040
+ i0.ɵɵelementEnd()()();
2041
+ i0.ɵɵelementStart(28, "div", 7)(29, "label", 8);
2042
+ i0.ɵɵtext(30, " Maximum Uses ");
2043
+ i0.ɵɵelementStart(31, "span", 9);
2044
+ i0.ɵɵtext(32, "(Optional)");
2045
+ i0.ɵɵelementEnd()();
2046
+ i0.ɵɵelement(33, "input", 14);
2047
+ i0.ɵɵelementStart(34, "p", 11);
2048
+ i0.ɵɵtext(35, "Leave empty for unlimited uses");
2049
+ i0.ɵɵelementEnd()();
2050
+ i0.ɵɵelementStart(36, "div", 7)(37, "label", 8);
2051
+ i0.ɵɵtext(38, " Expiration Date ");
2052
+ i0.ɵɵelementStart(39, "span", 9);
2053
+ i0.ɵɵtext(40, "(Optional)");
2054
+ i0.ɵɵelementEnd()();
2055
+ i0.ɵɵelementStart(41, "div", 15);
2056
+ i0.ɵɵelement(42, "input", 16);
2057
+ i0.ɵɵelementStart(43, "button", 17);
2058
+ i0.ɵɵlistener("click", function GenerateCodeDialogComponent_Template_button_click_43_listener() { return ctx.clearExpiryDate(); });
2059
+ i0.ɵɵtext(44, " Clear ");
2060
+ i0.ɵɵelementEnd()();
2061
+ i0.ɵɵelementStart(45, "p", 11);
2062
+ i0.ɵɵtext(46, "Leave empty for no expiration (30 days default)");
2063
+ i0.ɵɵelementEnd()();
2064
+ i0.ɵɵelementStart(47, "div", 18)(48, "h3", 19);
2065
+ i0.ɵɵtext(49, "Access Level ");
2066
+ i0.ɵɵelementStart(50, "span", 20);
2067
+ i0.ɵɵtext(51, "*");
2068
+ i0.ɵɵelementEnd()();
2069
+ i0.ɵɵelementStart(52, "div", 21);
2070
+ i0.ɵɵtemplate(53, GenerateCodeDialogComponent_button_53_Template, 10, 7, "button", 22);
2071
+ i0.ɵɵelementEnd()();
2072
+ i0.ɵɵtemplate(54, GenerateCodeDialogComponent_div_54_Template, 14, 1, "div", 23)(55, GenerateCodeDialogComponent_div_55_Template, 10, 3, "div", 24);
2073
+ i0.ɵɵelementEnd()()();
2074
+ i0.ɵɵelementStart(56, "mat-dialog-actions", 25)(57, "button", 26);
2075
+ i0.ɵɵlistener("click", function GenerateCodeDialogComponent_Template_button_click_57_listener() { return ctx.onCancel(); });
2076
+ i0.ɵɵtext(58, " Cancel ");
2077
+ i0.ɵɵelementEnd();
2078
+ i0.ɵɵelementStart(59, "button", 27);
2079
+ i0.ɵɵlistener("click", function GenerateCodeDialogComponent_Template_button_click_59_listener() { return ctx.onSubmit(); });
2080
+ i0.ɵɵtemplate(60, GenerateCodeDialogComponent_span_60_Template, 5, 0, "span", 28)(61, GenerateCodeDialogComponent_span_61_Template, 5, 0, "span", 28);
2081
+ i0.ɵɵelementEnd()()();
2082
+ } if (rf & 2) {
2083
+ let tmp_1_0;
2084
+ i0.ɵɵadvance(8);
2085
+ i0.ɵɵproperty("formGroup", ctx.codeForm);
2086
+ i0.ɵɵadvance(19);
2087
+ i0.ɵɵtextInterpolate1("", ((tmp_1_0 = ctx.codeForm.get("name")) == null ? null : tmp_1_0.value == null ? null : tmp_1_0.value.length) || 0, "/50");
2088
+ i0.ɵɵadvance(26);
2089
+ i0.ɵɵproperty("ngForOf", ctx.accessLevels);
2090
+ i0.ɵɵadvance();
2091
+ i0.ɵɵproperty("ngIf", ctx.generatedCode);
2092
+ i0.ɵɵadvance();
2093
+ i0.ɵɵproperty("ngIf", ctx.codeForm.invalid && (ctx.codeForm.touched || ctx.codeForm.dirty));
2094
+ i0.ɵɵadvance(4);
2095
+ i0.ɵɵproperty("disabled", !ctx.codeForm.valid || ctx.isGenerating);
2096
+ i0.ɵɵadvance();
2097
+ i0.ɵɵproperty("ngIf", ctx.isGenerating);
2098
+ i0.ɵɵadvance();
2099
+ i0.ɵɵproperty("ngIf", !ctx.isGenerating);
2100
+ } }, dependencies: [i2.NgForOf, i2.NgIf, i1$2.ɵNgNoValidate, i1$2.DefaultValueAccessor, i1$2.NumberValueAccessor, i1$2.NgControlStatus, i1$2.NgControlStatusGroup, i1$2.MaxLengthValidator, i1$2.EmailValidator, i1$2.MinValidator, i1$2.FormGroupDirective, i1$2.FormControlName, i1$1.MatDialogTitle, i1$1.MatDialogActions, i1$1.MatDialogContent, i4$1.MatButton, i5.MatIcon], styles: ["[_nghost-%COMP%]{display:block}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-container[_ngcontent-%COMP%]{background-color:#1f2937!important;border:1px solid #374151}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-title[_ngcontent-%COMP%]{color:#fff!important;font-size:1.25rem!important;padding-bottom:.5rem!important}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-content[_ngcontent-%COMP%]{color:#d1d5db!important}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-actions[_ngcontent-%COMP%]{padding-top:0!important;padding-bottom:0!important}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .transition-colors[_ngcontent-%COMP%]{height:30px}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%]{grid-template-columns:repeat(2,minmax(0,1fr))}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button[_ngcontent-%COMP%]{min-height:70px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);transition:all .2s cubic-bezier(.4,0,.2,1);padding:7px;margin:5px}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button.access-level-unselected[_ngcontent-%COMP%]{background:#1f293799;border:1px solid rgba(75,85,99,.5)}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button.access-level-unselected[_ngcontent-%COMP%]:hover{background:#374151b3;border-color:#6b728099;transform:translateY(-1px);box-shadow:0 2px 8px #00000026}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button.access-level-unselected[_ngcontent-%COMP%]:active{transform:translateY(0)}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button.access-level-selected[_ngcontent-%COMP%]{background:#1e40af33;border:1px solid rgba(59,130,246,.5);box-shadow:0 0 0 1px #3b82f61a,inset 0 1px #ffffff0d}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button.access-level-selected[_ngcontent-%COMP%]:hover{background:#1e40af40;border-color:#3b82f699;transform:translateY(-1px)}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button[_ngcontent-%COMP%] .bg-blue-500\\/20.text-blue-400[_ngcontent-%COMP%]{color:#93c5fd}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button[_ngcontent-%COMP%] .bg-yellow-500\\/20.text-yellow-400[_ngcontent-%COMP%]{color:#fcd34d}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button[_ngcontent-%COMP%] .bg-red-500\\/20.text-red-400[_ngcontent-%COMP%]{color:#fca5a5}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button[_ngcontent-%COMP%] .bg-purple-500\\/20.text-purple-400[_ngcontent-%COMP%]{color:#c4b5fd}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button[_ngcontent-%COMP%] mat-icon.check_circle[_ngcontent-%COMP%]{transition:transform .2s ease}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .access-level-button[_ngcontent-%COMP%]:hover mat-icon.check_circle[_ngcontent-%COMP%]{transform:scale(1.1)}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .min-w-0[_ngcontent-%COMP%]{min-width:0;margin:auto}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .grid-cols-2[_ngcontent-%COMP%] .min-w-0[_ngcontent-%COMP%] .truncate[_ngcontent-%COMP%]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%]{margin-bottom:1.25rem}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{display:block;margin-bottom:.375rem;font-size:.875rem}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%] input[_ngcontent-%COMP%], [_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%] select[_ngcontent-%COMP%]{width:100%;font-size:.875rem;padding:.5rem .75rem;background:#1f293799;border:1px solid rgba(75,85,99,.5)}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus, [_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%] select[_ngcontent-%COMP%]:focus{background:#1f2937cc;border-color:#3b82f699;box-shadow:0 0 0 2px #3b82f61a}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder, [_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%] select[_ngcontent-%COMP%]::placeholder{color:#9ca3afb3}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-content::-webkit-scrollbar{width:4px}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-content::-webkit-scrollbar-track{background:transparent}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-content::-webkit-scrollbar-thumb{background:#4b556380;border-radius:2px}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-content::-webkit-scrollbar-thumb:hover{background:#6b7280b3}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .bg-gray-800\\/50[_ngcontent-%COMP%]{background:#1f293799;border:1px solid rgba(75,85,99,.5);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .bg-gray-800\\/50 code[_ngcontent-%COMP%]{font-family:SF Mono,Monaco,Inconsolata,monospace;font-size:.875rem;letter-spacing:.025em;color:#34d399}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .bg-green-900\\/20[_ngcontent-%COMP%]{background:#064e3b33;border:1px solid rgba(52,211,153,.3);animation:_ngcontent-%COMP%_slideIn .3s ease-out}@keyframes _ngcontent-%COMP%_slideIn{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-surface{background:#111827f2!important;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid rgba(75,85,99,.3);border-radius:12px!important;box-shadow:0 10px 25px -5px #00000080,0 8px 10px -6px #0006,inset 0 1px #ffffff0d;width:auto!important;min-width:500px;max-width:550px}@media (max-width: 640px){[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-surface{min-width:90vw!important;margin:1rem}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-surface .grid-cols-2{grid-template-columns:1fr;gap:1rem}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .mat-mdc-dialog-surface .grid-cols-2 .access-level-button{min-height:65px}}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] button[mat-raised-button][_ngcontent-%COMP%]:not(:disabled):hover{transform:translateY(-1px);box-shadow:0 4px 12px #3b82f640,0 2px 4px #3b82f61a}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] button[mat-stroked-button][_ngcontent-%COMP%]:not(:disabled):hover{transform:translateY(-1px);background:#3741514d;border-color:#6b728099}@keyframes _ngcontent-%COMP%_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .animate-spin[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_spin 1s linear infinite}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .bg-red-900\\/20[_ngcontent-%COMP%]{background:#7f1d1d33;border:1px solid rgba(248,113,113,.3)}[_nghost-%COMP%] .generate-code-dialog[_ngcontent-%COMP%] .bg-red-900\\/20[_ngcontent-%COMP%] mat-icon[_ngcontent-%COMP%]{color:#fca5a5}"] });
2101
+ }
2102
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(GenerateCodeDialogComponent, [{
2103
+ type: Component,
2104
+ args: [{ selector: 'app-generate-code-dialog', standalone: false, template: "<div class=\"generate-code-dialog\">\r\n <h2 mat-dialog-title class=\"text-white !pb-2 !text-xl font-semibold\">Generate Invitation Code</h2>\r\n\r\n <mat-dialog-content class=\"!pb-0 !min-w-[500px]\">\r\n <div class=\"space-y-6\">\r\n <div class=\"text-md text-gray-300\">\r\n Create a new invitation code with custom settings\r\n </div>\r\n <div class=\"border-t border-gray-700\"></div>\r\n\r\n <form [formGroup]=\"codeForm\" class=\"space-y-6\">\r\n <div class=\"form-group\">\r\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">\r\n Email Address <span class=\"text-gray-500 text-xs font-normal\">(Optional)</span>\r\n </label>\r\n <input\r\n type=\"email\"\r\n formControlName=\"email\"\r\n class=\"w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors\"\r\n placeholder=\"Enter email address (optional)\"\r\n email>\r\n <p class=\"mt-1 text-xs text-gray-500\">If provided, only this email can use the code</p>\r\n </div>\r\n\r\n <!-- Code Name -->\r\n <div class=\"form-group\">\r\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">\r\n Code Name <span class=\"text-gray-500 text-xs font-normal\">(Optional)</span>\r\n </label>\r\n <input\r\n type=\"text\"\r\n formControlName=\"name\"\r\n class=\"w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors\"\r\n placeholder=\"e.g., VIP Users, Team Beta\"\r\n maxlength=\"50\">\r\n <div class=\"mt-1 text-xs text-gray-500 flex justify-between\">\r\n <span>A descriptive name for this code</span>\r\n <span>{{ codeForm.get('name')?.value?.length || 0 }}/50</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Max Uses -->\r\n <div class=\"form-group\">\r\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">\r\n Maximum Uses <span class=\"text-gray-500 text-xs font-normal\">(Optional)</span>\r\n </label>\r\n <input\r\n type=\"number\"\r\n formControlName=\"maxUses\"\r\n min=\"1\"\r\n class=\"w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors\"\r\n placeholder=\"e.g., 50\">\r\n <p class=\"mt-1 text-xs text-gray-500\">Leave empty for unlimited uses</p>\r\n </div>\r\n\r\n <!-- Expiration Date -->\r\n <div class=\"form-group\">\r\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">\r\n Expiration Date <span class=\"text-gray-500 text-xs font-normal\">(Optional)</span>\r\n </label>\r\n <div class=\"flex items-center space-x-2\">\r\n <input\r\n type=\"date\"\r\n formControlName=\"expiryDate\"\r\n class=\"flex-1 px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors\">\r\n <button\r\n type=\"button\"\r\n (click)=\"clearExpiryDate()\"\r\n class=\"px-4 py-3 text-sm text-gray-400 hover:text-white hover:bg-gray-700 rounded-lg transition-colors border border-gray-600\">\r\n Clear\r\n </button>\r\n </div>\r\n <p class=\"mt-1 text-xs text-gray-500\">Leave empty for no expiration (30 days default)</p>\r\n </div>\r\n\r\n <!-- Access Level -->\r\n <div class=\"mb-6\">\r\n <h3 class=\"text-md font-medium text-white mb-2\">Access Level <span class=\"text-red-400\">*</span></h3>\r\n <div class=\"grid grid-cols-2 gap-2\">\r\n <button\r\n type=\"button\"\r\n *ngFor=\"let level of accessLevels\"\r\n (click)=\"selectAccessLevel(level.value)\"\r\n [class]=\"codeForm.get('accessLevel')?.value === level.value\r\n ? 'access-level-selected bg-blue-900/30 border-blue-500 text-blue-300'\r\n : 'access-level-unselected bg-gray-800/50 border-gray-700 text-gray-300'\"\r\n class=\"access-level-button px-3 py-2.5 rounded-lg border hover:bg-gray-700/50 transition-all duration-200 flex items-start space-x-3\">\r\n\r\n <!-- Icon Container -->\r\n <div [class]=\"getLevelIconClass(level.value)\"\r\n class=\"w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0 mt-0.5\">\r\n <mat-icon class=\"!text-sm\">{{ getLevelIcon(level.value) }}</mat-icon>\r\n </div>\r\n\r\n <!-- Text Content -->\r\n <div class=\"flex-1 min-w-0\">\r\n <!-- First line: Label with checkmark -->\r\n <div class=\"flex items-center justify-between mb-1\">\r\n <span class=\"font-medium text-sm truncate\">{{ level.label }}</span>\r\n\r\n </div>\r\n\r\n <!-- Second line: Description -->\r\n <div class=\"text-xs opacity-75 truncate\">\r\n {{ level.description }}\r\n </div>\r\n </div>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Generated Code Preview -->\r\n <div *ngIf=\"generatedCode\" class=\"mt-4 p-4 bg-gray-800/50 border border-gray-700 rounded-lg\">\r\n <div class=\"flex items-center justify-between mb-2\">\r\n <span class=\"text-sm font-medium text-gray-300\">Generated Code:</span>\r\n <button\r\n type=\"button\"\r\n (click)=\"copyToClipboard()\"\r\n class=\"text-sm text-blue-400 hover:text-blue-300 flex items-center space-x-1 transition-colors\">\r\n <mat-icon class=\"!text-base\">content_copy</mat-icon>\r\n <span>Copy</span>\r\n </button>\r\n </div>\r\n <div class=\"bg-gray-900 p-3 rounded border border-gray-700\">\r\n <code class=\"font-mono text-lg font-bold text-green-400 select-all\">{{ generatedCode }}</code>\r\n </div>\r\n <p class=\"mt-2 text-xs text-gray-500\">Share this code with users to grant them access</p>\r\n </div>\r\n\r\n <!-- Form Validation Summary -->\r\n <div *ngIf=\"codeForm.invalid && (codeForm.touched || codeForm.dirty)\" class=\"mt-4 p-3 bg-red-900/20 border border-red-800/30 rounded-lg\">\r\n <div class=\"flex items-start space-x-2\">\r\n <mat-icon class=\"!text-red-400 !text-lg flex-shrink-0\">error</mat-icon>\r\n <div class=\"text-sm text-red-300\">\r\n Please fix the following errors:\r\n <ul class=\"mt-1 ml-4 list-disc text-red-400\">\r\n <li *ngIf=\"codeForm.get('email')?.hasError('email')\">Please enter a valid email address</li>\r\n <li *ngIf=\"codeForm.get('maxUses')?.hasError('min')\">Maximum uses must be at least 1</li>\r\n <li *ngIf=\"codeForm.get('accessLevel')?.hasError('required')\">Access level is required</li>\r\n </ul>\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"!border-t !border-gray-700\">\r\n <button\r\n mat-stroked-button\r\n (click)=\"onCancel()\"\r\n class=\"!border-gray-600 !text-gray-300 hover:!bg-gray-700 hover:!border-gray-500\">\r\n Cancel\r\n </button>\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"onSubmit()\"\r\n [disabled]=\"!codeForm.valid || isGenerating\"\r\n class=\"!bg-blue-600 hover:!bg-blue-700 disabled:!opacity-50 disabled:!cursor-not-allowed\">\r\n <span *ngIf=\"isGenerating\" class=\"flex items-center space-x-2\">\r\n <mat-icon class=\"animate-spin !text-lg\">refresh</mat-icon>\r\n <span>Generating...</span>\r\n </span>\r\n <span *ngIf=\"!isGenerating\" class=\"flex items-center space-x-2\">\r\n <mat-icon>add</mat-icon>\r\n <span>Generate Code</span>\r\n </span>\r\n </button>\r\n </mat-dialog-actions>\r\n</div>\r\n\r\n", styles: [":host{display:block}:host .generate-code-dialog .mat-mdc-dialog-container{background-color:#1f2937!important;border:1px solid #374151}:host .generate-code-dialog .mat-mdc-dialog-title{color:#fff!important;font-size:1.25rem!important;padding-bottom:.5rem!important}:host .generate-code-dialog .mat-mdc-dialog-content{color:#d1d5db!important}:host .generate-code-dialog .mat-mdc-dialog-actions{padding-top:0!important;padding-bottom:0!important}:host .generate-code-dialog .transition-colors{height:30px}:host .generate-code-dialog .grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}:host .generate-code-dialog .grid-cols-2 .access-level-button{min-height:70px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);transition:all .2s cubic-bezier(.4,0,.2,1);padding:7px;margin:5px}:host .generate-code-dialog .grid-cols-2 .access-level-button.access-level-unselected{background:#1f293799;border:1px solid rgba(75,85,99,.5)}:host .generate-code-dialog .grid-cols-2 .access-level-button.access-level-unselected:hover{background:#374151b3;border-color:#6b728099;transform:translateY(-1px);box-shadow:0 2px 8px #00000026}:host .generate-code-dialog .grid-cols-2 .access-level-button.access-level-unselected:active{transform:translateY(0)}:host .generate-code-dialog .grid-cols-2 .access-level-button.access-level-selected{background:#1e40af33;border:1px solid rgba(59,130,246,.5);box-shadow:0 0 0 1px #3b82f61a,inset 0 1px #ffffff0d}:host .generate-code-dialog .grid-cols-2 .access-level-button.access-level-selected:hover{background:#1e40af40;border-color:#3b82f699;transform:translateY(-1px)}:host .generate-code-dialog .grid-cols-2 .access-level-button .bg-blue-500\\/20.text-blue-400{color:#93c5fd}:host .generate-code-dialog .grid-cols-2 .access-level-button .bg-yellow-500\\/20.text-yellow-400{color:#fcd34d}:host .generate-code-dialog .grid-cols-2 .access-level-button .bg-red-500\\/20.text-red-400{color:#fca5a5}:host .generate-code-dialog .grid-cols-2 .access-level-button .bg-purple-500\\/20.text-purple-400{color:#c4b5fd}:host .generate-code-dialog .grid-cols-2 .access-level-button mat-icon.check_circle{transition:transform .2s ease}:host .generate-code-dialog .grid-cols-2 .access-level-button:hover mat-icon.check_circle{transform:scale(1.1)}:host .generate-code-dialog .grid-cols-2 .min-w-0{min-width:0;margin:auto}:host .generate-code-dialog .grid-cols-2 .min-w-0 .truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .generate-code-dialog .form-group{margin-bottom:1.25rem}:host .generate-code-dialog .form-group label{display:block;margin-bottom:.375rem;font-size:.875rem}:host .generate-code-dialog .form-group input,:host .generate-code-dialog .form-group select{width:100%;font-size:.875rem;padding:.5rem .75rem;background:#1f293799;border:1px solid rgba(75,85,99,.5)}:host .generate-code-dialog .form-group input:focus,:host .generate-code-dialog .form-group select:focus{background:#1f2937cc;border-color:#3b82f699;box-shadow:0 0 0 2px #3b82f61a}:host .generate-code-dialog .form-group input::placeholder,:host .generate-code-dialog .form-group select::placeholder{color:#9ca3afb3}:host .generate-code-dialog ::ng-deep .mat-mdc-dialog-content::-webkit-scrollbar{width:4px}:host .generate-code-dialog ::ng-deep .mat-mdc-dialog-content::-webkit-scrollbar-track{background:transparent}:host .generate-code-dialog ::ng-deep .mat-mdc-dialog-content::-webkit-scrollbar-thumb{background:#4b556380;border-radius:2px}:host .generate-code-dialog ::ng-deep .mat-mdc-dialog-content::-webkit-scrollbar-thumb:hover{background:#6b7280b3}:host .generate-code-dialog .bg-gray-800\\/50{background:#1f293799;border:1px solid rgba(75,85,99,.5);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}:host .generate-code-dialog .bg-gray-800\\/50 code{font-family:SF Mono,Monaco,Inconsolata,monospace;font-size:.875rem;letter-spacing:.025em;color:#34d399}:host .generate-code-dialog .bg-green-900\\/20{background:#064e3b33;border:1px solid rgba(52,211,153,.3);animation:slideIn .3s ease-out}@keyframes slideIn{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}:host .generate-code-dialog ::ng-deep .mat-mdc-dialog-surface{background:#111827f2!important;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid rgba(75,85,99,.3);border-radius:12px!important;box-shadow:0 10px 25px -5px #00000080,0 8px 10px -6px #0006,inset 0 1px #ffffff0d;width:auto!important;min-width:500px;max-width:550px}@media (max-width: 640px){:host .generate-code-dialog ::ng-deep .mat-mdc-dialog-surface{min-width:90vw!important;margin:1rem}:host .generate-code-dialog ::ng-deep .mat-mdc-dialog-surface .grid-cols-2{grid-template-columns:1fr;gap:1rem}:host .generate-code-dialog ::ng-deep .mat-mdc-dialog-surface .grid-cols-2 .access-level-button{min-height:65px}}:host .generate-code-dialog button[mat-raised-button]:not(:disabled):hover{transform:translateY(-1px);box-shadow:0 4px 12px #3b82f640,0 2px 4px #3b82f61a}:host .generate-code-dialog button[mat-stroked-button]:not(:disabled):hover{transform:translateY(-1px);background:#3741514d;border-color:#6b728099}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host .generate-code-dialog .animate-spin{animation:spin 1s linear infinite}:host .generate-code-dialog .bg-red-900\\/20{background:#7f1d1d33;border:1px solid rgba(248,113,113,.3)}:host .generate-code-dialog .bg-red-900\\/20 mat-icon{color:#fca5a5}\n"] }]
2105
+ }], () => [{ type: i1$2.FormBuilder }, { type: InvitationCodeService }, { type: i1$1.MatDialogRef }, { type: undefined, decorators: [{
2106
+ type: Inject,
2107
+ args: [MAT_DIALOG_DATA]
2108
+ }] }], null); })();
2109
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(GenerateCodeDialogComponent, { className: "GenerateCodeDialogComponent", filePath: "lib/components/modal/generate-code-dialog/generate-code-dialog.component.ts", lineNumber: 31 }); })();
2110
+
2111
+ function StatsCardComponent_div_4_Template(rf, ctx) { if (rf & 1) {
2112
+ i0.ɵɵelementStart(0, "div", 7)(1, "span", 8);
2113
+ i0.ɵɵtext(2);
2114
+ i0.ɵɵelementEnd()();
2115
+ } if (rf & 2) {
2116
+ const ctx_r0 = i0.ɵɵnextContext();
2117
+ i0.ɵɵadvance(2);
2118
+ i0.ɵɵtextInterpolate(ctx_r0.stats.icon);
2119
+ } }
2120
+ function StatsCardComponent_p_8_Template(rf, ctx) { if (rf & 1) {
2121
+ i0.ɵɵelementStart(0, "p", 9);
2122
+ i0.ɵɵtext(1);
2123
+ i0.ɵɵelementEnd();
2124
+ } if (rf & 2) {
2125
+ const ctx_r0 = i0.ɵɵnextContext();
2126
+ i0.ɵɵadvance();
2127
+ i0.ɵɵtextInterpolate(ctx_r0.stats.description);
2128
+ } }
2129
+ class StatsCardComponent {
2130
+ stats;
2131
+ static ɵfac = function StatsCardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || StatsCardComponent)(); };
2132
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: StatsCardComponent, selectors: [["app-stats-card"]], inputs: { stats: "stats" }, standalone: false, decls: 9, vars: 4, consts: [[1, "stats-card", "bg-gray-800", "rounded-lg", "p-6", "border", "border-gray-700", "hover:border-gray-600", "transition-colors", "duration-200"], [1, "flex", "items-center", "justify-between", "mb-6"], [1, "text-gray-400", "text-sm", "font-medium"], ["class", "p-2 rounded-full bg-gray-400", 4, "ngIf"], [1, "mt-4"], [1, "text-3xl", "font-bold", "text-white"], ["class", "text-gray-500 text-sm mt-2", 4, "ngIf"], [1, "p-2", "rounded-full", "bg-gray-400"], [1, "material-icons", "text-gray-300", "text-lg"], [1, "text-gray-500", "text-sm", "mt-2"]], template: function StatsCardComponent_Template(rf, ctx) { if (rf & 1) {
2133
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "h3", 2);
2134
+ i0.ɵɵtext(3);
2135
+ i0.ɵɵelementEnd();
2136
+ i0.ɵɵtemplate(4, StatsCardComponent_div_4_Template, 3, 1, "div", 3);
2137
+ i0.ɵɵelementEnd();
2138
+ i0.ɵɵelementStart(5, "div", 4)(6, "p", 5);
2139
+ i0.ɵɵtext(7);
2140
+ i0.ɵɵelementEnd();
2141
+ i0.ɵɵtemplate(8, StatsCardComponent_p_8_Template, 2, 1, "p", 6);
2142
+ i0.ɵɵelementEnd()();
2143
+ } if (rf & 2) {
2144
+ i0.ɵɵadvance(3);
2145
+ i0.ɵɵtextInterpolate(ctx.stats.title);
2146
+ i0.ɵɵadvance();
2147
+ i0.ɵɵproperty("ngIf", ctx.stats.icon);
2148
+ i0.ɵɵadvance(3);
2149
+ i0.ɵɵtextInterpolate(ctx.stats.value);
2150
+ i0.ɵɵadvance();
2151
+ i0.ɵɵproperty("ngIf", ctx.stats.description);
2152
+ } }, dependencies: [i2.NgIf], styles: ["[_nghost-%COMP%]{display:block}.stats-card[_ngcontent-%COMP%]{background:#29252d;border:1px solid #423d48;border-radius:.5rem;padding:1.5rem;transition:all .2s ease;box-shadow:0 10px 15px -3px #00000040,0 4px 6px -2px #00000026,inset 0 0 0 1px #ffffff0d}.stats-card[_ngcontent-%COMP%]:hover{transform:translateY(-2px);border-color:#a855f7;box-shadow:0 20px 25px -5px #00000059,0 10px 10px -5px #0003,inset 0 0 0 1px #ffffff1a,0 0 20px #a855f726}.stats-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem}.stats-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{color:#a5a1aa;font-size:.875rem;font-weight:500}.stats-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .icon-container[_ngcontent-%COMP%]{padding:.5rem;border-radius:9999px;background:#423d48;transition:background .2s ease}.stats-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .icon-container[_ngcontent-%COMP%] .material-icons[_ngcontent-%COMP%]{color:#d8d4de;font-size:1rem;transition:color .2s ease}.stats-card[_ngcontent-%COMP%]:hover .card-header[_ngcontent-%COMP%] .icon-container[_ngcontent-%COMP%]{background:#a855f7}.stats-card[_ngcontent-%COMP%]:hover .card-header[_ngcontent-%COMP%] .icon-container[_ngcontent-%COMP%] .material-icons[_ngcontent-%COMP%]{color:#fff}.stats-card[_ngcontent-%COMP%] .card-content[_ngcontent-%COMP%]{margin-top:1rem}.stats-card[_ngcontent-%COMP%] .card-content[_ngcontent-%COMP%] .value[_ngcontent-%COMP%]{font-size:1.875rem;font-weight:700;color:#fff;margin:0}.stats-card[_ngcontent-%COMP%] .card-content[_ngcontent-%COMP%] .description[_ngcontent-%COMP%]{color:#9ca3af;font-size:.75rem;margin:.5rem 0 0}"] });
2153
+ }
2154
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(StatsCardComponent, [{
2155
+ type: Component,
2156
+ args: [{ selector: 'app-stats-card', standalone: false, template: "<div class=\"stats-card bg-gray-800 rounded-lg p-6 border border-gray-700 hover:border-gray-600 transition-colors duration-200\">\r\n <!-- Title and icon on the same line -->\r\n <div class=\"flex items-center justify-between mb-6\">\r\n <h3 class=\"text-gray-400 text-sm font-medium\">{{ stats.title }}</h3>\r\n <!-- Material Icons on the same line as title -->\r\n <div *ngIf=\"stats.icon\" class=\"p-2 rounded-full bg-gray-400\">\r\n <span class=\"material-icons text-gray-300 text-lg\">{{ stats.icon }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Number and description below with more space above -->\r\n <div class=\"mt-4\">\r\n <p class=\"text-3xl font-bold text-white\">{{ stats.value }}</p>\r\n <p *ngIf=\"stats.description\" class=\"text-gray-500 text-sm mt-2\">{{ stats.description }}</p>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}.stats-card{background:#29252d;border:1px solid #423d48;border-radius:.5rem;padding:1.5rem;transition:all .2s ease;box-shadow:0 10px 15px -3px #00000040,0 4px 6px -2px #00000026,inset 0 0 0 1px #ffffff0d}.stats-card:hover{transform:translateY(-2px);border-color:#a855f7;box-shadow:0 20px 25px -5px #00000059,0 10px 10px -5px #0003,inset 0 0 0 1px #ffffff1a,0 0 20px #a855f726}.stats-card .card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem}.stats-card .card-header h3{color:#a5a1aa;font-size:.875rem;font-weight:500}.stats-card .card-header .icon-container{padding:.5rem;border-radius:9999px;background:#423d48;transition:background .2s ease}.stats-card .card-header .icon-container .material-icons{color:#d8d4de;font-size:1rem;transition:color .2s ease}.stats-card:hover .card-header .icon-container{background:#a855f7}.stats-card:hover .card-header .icon-container .material-icons{color:#fff}.stats-card .card-content{margin-top:1rem}.stats-card .card-content .value{font-size:1.875rem;font-weight:700;color:#fff;margin:0}.stats-card .card-content .description{color:#9ca3af;font-size:.75rem;margin:.5rem 0 0}\n"] }]
2157
+ }], null, { stats: [{
2158
+ type: Input
2159
+ }] }); })();
2160
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(StatsCardComponent, { className: "StatsCardComponent", filePath: "lib/components/shared/stats-card/stats-card.component.ts", lineNumber: 11 }); })();
2161
+
2162
+ // stats-overview.component.ts
2163
+ function StatsOverviewComponent_app_stats_card_12_Template(rf, ctx) { if (rf & 1) {
2164
+ i0.ɵɵelement(0, "app-stats-card", 9);
2165
+ } if (rf & 2) {
2166
+ const stat_r1 = ctx.$implicit;
2167
+ i0.ɵɵproperty("stats", stat_r1);
2168
+ } }
2169
+ class StatsOverviewComponent {
2170
+ invitationCodeService;
2171
+ dialog;
2172
+ stats$;
2173
+ constructor(invitationCodeService, dialog) {
2174
+ this.invitationCodeService = invitationCodeService;
2175
+ this.dialog = dialog;
2176
+ }
2177
+ ngOnInit() {
2178
+ this.stats$ = this.invitationCodeService.getStats();
2179
+ }
2180
+ openGenerateCodeDialog() {
2181
+ const dialogRef = this.dialog.open(GenerateCodeDialogComponent, {
2182
+ width: 'auto', // Let content determine width
2183
+ maxWidth: '600px', // Maximum width
2184
+ maxHeight: '85vh', // Maximum height
2185
+ panelClass: 'generate-code-dialog',
2186
+ autoFocus: false,
2187
+ disableClose: false,
2188
+ data: {
2189
+ name: '',
2190
+ maxUses: null,
2191
+ expiryDate: null,
2192
+ accessLevel: 'basic'
2193
+ }
2194
+ });
2195
+ dialogRef.afterClosed().subscribe((result) => {
2196
+ if (result && result.code) {
2197
+ console.log('Generated code:', result);
2198
+ // Handle the generated code
2199
+ this.handleGeneratedCode(result);
2200
+ }
2201
+ });
2202
+ }
2203
+ handleGeneratedCode(data) {
2204
+ this.invitationCodeService.generateCode(data).subscribe({
2205
+ next: (response) => {
2206
+ console.log('Code generated successfully:', response);
2207
+ alert(`Code "${response.code}" generated successfully!`);
2208
+ },
2209
+ error: (error) => {
2210
+ console.error('Failed to generate code:', error);
2211
+ alert(`Failed to generate code: ${error.message}`);
2212
+ }
2213
+ });
2214
+ }
2215
+ static ɵfac = function StatsOverviewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || StatsOverviewComponent)(i0.ɵɵdirectiveInject(InvitationCodeService), i0.ɵɵdirectiveInject(i1$1.MatDialog)); };
2216
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: StatsOverviewComponent, selectors: [["app-stats-overview"]], standalone: false, decls: 14, vars: 3, consts: [[1, "stats-overview", "mb-8"], [1, "header-section", "flex", "flex-col", "lg:flex-row", "lg:items-center", "lg:justify-between", "mb-10"], [1, "header-content"], [1, "text-2xl", "font-bold", "text-white"], [1, "text-gray-400", "text-md"], ["mat-raised-button", "", "color", "primary", 1, "mt-4", "lg:mt-0", "flex", "items-center", "justify-center", "gap-2", "!bg-blue-600", "hover:!bg-blue-700", 3, "click"], [1, "!text-lg"], [1, "grid", "grid-cols-1", "md:grid-cols-2", "lg:grid-cols-5", "gap-4"], [3, "stats", 4, "ngFor", "ngForOf"], [3, "stats"]], template: function StatsOverviewComponent_Template(rf, ctx) { if (rf & 1) {
2217
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "h2", 3);
2218
+ i0.ɵɵtext(4, "Access Management");
2219
+ i0.ɵɵelementEnd();
2220
+ i0.ɵɵelementStart(5, "p", 4);
2221
+ i0.ɵɵtext(6, "Manage invitation codes and waitlist members");
2222
+ i0.ɵɵelementEnd()();
2223
+ i0.ɵɵelementStart(7, "button", 5);
2224
+ i0.ɵɵlistener("click", function StatsOverviewComponent_Template_button_click_7_listener() { return ctx.openGenerateCodeDialog(); });
2225
+ i0.ɵɵelementStart(8, "mat-icon", 6);
2226
+ i0.ɵɵtext(9, "add");
2227
+ i0.ɵɵelementEnd();
2228
+ i0.ɵɵtext(10, " Generate Code ");
2229
+ i0.ɵɵelementEnd()();
2230
+ i0.ɵɵelementStart(11, "div", 7);
2231
+ i0.ɵɵtemplate(12, StatsOverviewComponent_app_stats_card_12_Template, 1, 1, "app-stats-card", 8);
2232
+ i0.ɵɵpipe(13, "async");
2233
+ i0.ɵɵelementEnd()();
2234
+ } if (rf & 2) {
2235
+ i0.ɵɵadvance(12);
2236
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind1(13, 1, ctx.stats$));
2237
+ } }, dependencies: [i2.NgForOf, i4$1.MatButton, i5.MatIcon, StatsCardComponent, i2.AsyncPipe], styles: ["[_nghost-%COMP%]{display:block}.header-section[_ngcontent-%COMP%] .header-content[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{margin-bottom:1rem;font-weight:400}.header-section[_ngcontent-%COMP%] button[mat-raised-button][_ngcontent-%COMP%]{transition:all .2s ease}.header-section[_ngcontent-%COMP%] button[mat-raised-button][_ngcontent-%COMP%]:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 12px #3b82f64d}.header-section[_ngcontent-%COMP%] button[mat-raised-button][_ngcontent-%COMP%]:active:not(:disabled){transform:translateY(0)} .dark-dialog .mat-mdc-dialog-surface{background-color:#29252d!important;border-radius:12px!important;border:1px solid #374151;box-shadow:0 20px 25px -5px #00000080,0 10px 10px -5px #0006} .dark-dialog .mat-mdc-dialog-container{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}"] });
2238
+ }
2239
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(StatsOverviewComponent, [{
2240
+ type: Component,
2241
+ args: [{ selector: 'app-stats-overview', standalone: false, template: "<!-- stats-overview.component.html -->\r\n<div class=\"stats-overview mb-8\">\r\n <!-- Header section with flex layout -->\r\n <div class=\"header-section flex flex-col lg:flex-row lg:items-center lg:justify-between mb-10\">\r\n <div class=\"header-content\">\r\n <h2 class=\"text-2xl font-bold text-white\">Access Management</h2>\r\n <p class=\"text-gray-400 text-md\">Manage invitation codes and waitlist members</p>\r\n </div>\r\n\r\n <!-- Generate Code Button -->\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"openGenerateCodeDialog()\"\r\n class=\"mt-4 lg:mt-0 flex items-center justify-center gap-2 !bg-blue-600 hover:!bg-blue-700\">\r\n <mat-icon class=\"!text-lg\">add</mat-icon>\r\n Generate Code\r\n </button>\r\n </div>\r\n\r\n <!-- Stats cards grid -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4\">\r\n <app-stats-card\r\n *ngFor=\"let stat of stats$ | async\"\r\n [stats]=\"stat\">\r\n </app-stats-card>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}.header-section .header-content h2{margin-bottom:1rem;font-weight:400}.header-section button[mat-raised-button]{transition:all .2s ease}.header-section button[mat-raised-button]:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 12px #3b82f64d}.header-section button[mat-raised-button]:active:not(:disabled){transform:translateY(0)}::ng-deep .dark-dialog .mat-mdc-dialog-surface{background-color:#29252d!important;border-radius:12px!important;border:1px solid #374151;box-shadow:0 20px 25px -5px #00000080,0 10px 10px -5px #0006}::ng-deep .dark-dialog .mat-mdc-dialog-container{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}\n"] }]
2242
+ }], () => [{ type: InvitationCodeService }, { type: i1$1.MatDialog }], null); })();
2243
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(StatsOverviewComponent, { className: "StatsOverviewComponent", filePath: "lib/components/stats-overview/stats-overview.component.ts", lineNumber: 17 }); })();
2244
+
2245
+ function WaitlistStatsCardComponent_div_4_Template(rf, ctx) { if (rf & 1) {
2246
+ i0.ɵɵelementStart(0, "div", 7)(1, "span", 8);
2247
+ i0.ɵɵtext(2);
2248
+ i0.ɵɵelementEnd()();
2249
+ } if (rf & 2) {
2250
+ const ctx_r0 = i0.ɵɵnextContext();
2251
+ i0.ɵɵadvance(2);
2252
+ i0.ɵɵtextInterpolate(ctx_r0.stats.icon);
2253
+ } }
2254
+ function WaitlistStatsCardComponent_p_8_Template(rf, ctx) { if (rf & 1) {
2255
+ i0.ɵɵelementStart(0, "p", 9);
2256
+ i0.ɵɵtext(1);
2257
+ i0.ɵɵelementEnd();
2258
+ } if (rf & 2) {
2259
+ const ctx_r0 = i0.ɵɵnextContext();
2260
+ i0.ɵɵadvance();
2261
+ i0.ɵɵtextInterpolate(ctx_r0.stats.description);
2262
+ } }
2263
+ class WaitlistStatsCardComponent {
2264
+ stats;
2265
+ static ɵfac = function WaitlistStatsCardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WaitlistStatsCardComponent)(); };
2266
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: WaitlistStatsCardComponent, selectors: [["app-waitlist-stats-card"]], inputs: { stats: "stats" }, standalone: false, decls: 9, vars: 4, consts: [[1, "stats-card", "bg-gray-800", "rounded-lg", "p-6", "border", "border-gray-700", "hover:border-gray-600", "transition-colors", "duration-200"], [1, "flex", "items-center", "justify-between", "mb-6"], [1, "text-gray-400", "text-sm", "font-medium"], ["class", "p-2 rounded-full bg-gray-400", 4, "ngIf"], [1, "mt-4"], [1, "text-3xl", "font-bold", "text-white"], ["class", "text-gray-500 text-sm mt-2", 4, "ngIf"], [1, "p-2", "rounded-full", "bg-gray-400"], [1, "material-icons", "text-gray-300", "text-lg"], [1, "text-gray-500", "text-sm", "mt-2"]], template: function WaitlistStatsCardComponent_Template(rf, ctx) { if (rf & 1) {
2267
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "h3", 2);
2268
+ i0.ɵɵtext(3);
2269
+ i0.ɵɵelementEnd();
2270
+ i0.ɵɵtemplate(4, WaitlistStatsCardComponent_div_4_Template, 3, 1, "div", 3);
2271
+ i0.ɵɵelementEnd();
2272
+ i0.ɵɵelementStart(5, "div", 4)(6, "p", 5);
2273
+ i0.ɵɵtext(7);
2274
+ i0.ɵɵelementEnd();
2275
+ i0.ɵɵtemplate(8, WaitlistStatsCardComponent_p_8_Template, 2, 1, "p", 6);
2276
+ i0.ɵɵelementEnd()();
2277
+ } if (rf & 2) {
2278
+ i0.ɵɵadvance(3);
2279
+ i0.ɵɵtextInterpolate(ctx.stats.title);
2280
+ i0.ɵɵadvance();
2281
+ i0.ɵɵproperty("ngIf", ctx.stats.icon);
2282
+ i0.ɵɵadvance(3);
2283
+ i0.ɵɵtextInterpolate(ctx.stats.value);
2284
+ i0.ɵɵadvance();
2285
+ i0.ɵɵproperty("ngIf", ctx.stats.description);
2286
+ } }, dependencies: [i2.NgIf], styles: ["[_nghost-%COMP%]{display:block;width:100%}.stats-card[_ngcontent-%COMP%]{background:#29252d;border:1px solid #423d48;border-radius:.5rem;padding:1.5rem;transition:all .2s ease;box-shadow:0 10px 15px -3px #00000040,0 4px 6px -2px #00000026,inset 0 0 0 1px #ffffff0d}.stats-card[_ngcontent-%COMP%]:hover{transform:translateY(-2px);border-color:#a855f7;box-shadow:0 20px 25px -5px #00000059,0 10px 10px -5px #0003,inset 0 0 0 1px #ffffff1a,0 0 20px #a855f726}.stats-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem}.stats-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{color:#a5a1aa;font-size:.875rem;font-weight:500}.stats-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .icon-container[_ngcontent-%COMP%]{padding:.5rem;border-radius:9999px;background:#423d48;transition:background .2s ease}.stats-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .icon-container[_ngcontent-%COMP%] .material-icons[_ngcontent-%COMP%]{color:#d8d4de;font-size:1rem;transition:color .2s ease}.stats-card[_ngcontent-%COMP%]:hover .card-header[_ngcontent-%COMP%] .icon-container[_ngcontent-%COMP%]{background:#a855f7}.stats-card[_ngcontent-%COMP%]:hover .card-header[_ngcontent-%COMP%] .icon-container[_ngcontent-%COMP%] .material-icons[_ngcontent-%COMP%]{color:#fff}.stats-card[_ngcontent-%COMP%] .card-content[_ngcontent-%COMP%]{margin-top:1rem}.stats-card[_ngcontent-%COMP%] .card-content[_ngcontent-%COMP%] .value[_ngcontent-%COMP%]{font-size:1.875rem;font-weight:700;color:#fff;margin:0}.stats-card[_ngcontent-%COMP%] .card-content[_ngcontent-%COMP%] .description[_ngcontent-%COMP%]{color:#9ca3af;font-size:.75rem;margin:.5rem 0 0}"] });
2287
+ }
2288
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WaitlistStatsCardComponent, [{
2289
+ type: Component,
2290
+ args: [{ selector: 'app-waitlist-stats-card', standalone: false, template: "<div class=\"stats-card bg-gray-800 rounded-lg p-6 border border-gray-700 hover:border-gray-600 transition-colors duration-200\">\r\n <div class=\"flex items-center justify-between mb-6\">\r\n <h3 class=\"text-gray-400 text-sm font-medium\">{{ stats.title }}</h3>\r\n\r\n <div *ngIf=\"stats.icon\" class=\"p-2 rounded-full bg-gray-400\">\r\n <span class=\"material-icons text-gray-300 text-lg\">{{ stats.icon }}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mt-4\">\r\n <p class=\"text-3xl font-bold text-white\">{{ stats.value }}</p>\r\n <p *ngIf=\"stats.description\" class=\"text-gray-500 text-sm mt-2\">{{ stats.description }}</p>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;width:100%}.stats-card{background:#29252d;border:1px solid #423d48;border-radius:.5rem;padding:1.5rem;transition:all .2s ease;box-shadow:0 10px 15px -3px #00000040,0 4px 6px -2px #00000026,inset 0 0 0 1px #ffffff0d}.stats-card:hover{transform:translateY(-2px);border-color:#a855f7;box-shadow:0 20px 25px -5px #00000059,0 10px 10px -5px #0003,inset 0 0 0 1px #ffffff1a,0 0 20px #a855f726}.stats-card .card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem}.stats-card .card-header h3{color:#a5a1aa;font-size:.875rem;font-weight:500}.stats-card .card-header .icon-container{padding:.5rem;border-radius:9999px;background:#423d48;transition:background .2s ease}.stats-card .card-header .icon-container .material-icons{color:#d8d4de;font-size:1rem;transition:color .2s ease}.stats-card:hover .card-header .icon-container{background:#a855f7}.stats-card:hover .card-header .icon-container .material-icons{color:#fff}.stats-card .card-content{margin-top:1rem}.stats-card .card-content .value{font-size:1.875rem;font-weight:700;color:#fff;margin:0}.stats-card .card-content .description{color:#9ca3af;font-size:.75rem;margin:.5rem 0 0}\n"] }]
2291
+ }], null, { stats: [{
2292
+ type: Input
2293
+ }] }); })();
2294
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WaitlistStatsCardComponent, { className: "WaitlistStatsCardComponent", filePath: "lib/components/shared/waitlist-stats-card/waitlist-stats-card.component.ts", lineNumber: 11 }); })();
2295
+
2296
+ function WaitlistStatsOverviewComponent_ng_container_0_app_waitlist_stats_card_2_Template(rf, ctx) { if (rf & 1) {
2297
+ i0.ɵɵelement(0, "app-waitlist-stats-card", 7);
2298
+ } if (rf & 2) {
2299
+ const stat_r1 = ctx.$implicit;
2300
+ i0.ɵɵproperty("stats", stat_r1);
2301
+ } }
2302
+ function WaitlistStatsOverviewComponent_ng_container_0_Template(rf, ctx) { if (rf & 1) {
2303
+ i0.ɵɵelementContainerStart(0);
2304
+ i0.ɵɵelementStart(1, "div", 5);
2305
+ i0.ɵɵtemplate(2, WaitlistStatsOverviewComponent_ng_container_0_app_waitlist_stats_card_2_Template, 1, 1, "app-waitlist-stats-card", 6);
2306
+ i0.ɵɵelementEnd();
2307
+ i0.ɵɵelementContainerEnd();
2308
+ } if (rf & 2) {
2309
+ const stats_r2 = ctx.ngIf;
2310
+ const ctx_r2 = i0.ɵɵnextContext();
2311
+ i0.ɵɵadvance();
2312
+ i0.ɵɵstyleProp("grid-template-columns", ctx_r2.getCols(stats_r2.length));
2313
+ i0.ɵɵadvance();
2314
+ i0.ɵɵproperty("ngForOf", stats_r2);
2315
+ } }
2316
+ function WaitlistStatsOverviewComponent_div_7_Template(rf, ctx) { if (rf & 1) {
2317
+ i0.ɵɵelementStart(0, "div", 8)(1, "div", 9)(2, "span");
2318
+ i0.ɵɵtext(3);
2319
+ i0.ɵɵelementEnd();
2320
+ i0.ɵɵelementStart(4, "span");
2321
+ i0.ɵɵtext(5);
2322
+ i0.ɵɵelementEnd()();
2323
+ i0.ɵɵelementStart(6, "div", 10);
2324
+ i0.ɵɵelement(7, "div", 11);
2325
+ i0.ɵɵelementEnd()();
2326
+ } if (rf & 2) {
2327
+ const item_r4 = ctx.$implicit;
2328
+ const ctx_r2 = i0.ɵɵnextContext();
2329
+ i0.ɵɵadvance(3);
2330
+ i0.ɵɵtextInterpolate(item_r4.label);
2331
+ i0.ɵɵadvance(2);
2332
+ i0.ɵɵtextInterpolate(item_r4.value);
2333
+ i0.ɵɵadvance(2);
2334
+ i0.ɵɵstyleProp("width", ctx_r2.getPercentage(item_r4.value) + "%");
2335
+ } }
2336
+ class WaitlistStatsOverviewComponent {
2337
+ WaitlistCodeService;
2338
+ waitlistStats$;
2339
+ userDemand = [
2340
+ { label: 'Premium Member', value: 2 },
2341
+ { label: 'Standard Member', value: 2 },
2342
+ { label: 'VIP Member', value: 1 }
2343
+ ];
2344
+ constructor(WaitlistCodeService) {
2345
+ this.WaitlistCodeService = WaitlistCodeService;
2346
+ }
2347
+ ngOnInit() {
2348
+ this.waitlistStats$ = this.WaitlistCodeService.getWaitlistStats();
2349
+ }
2350
+ getPercentage(value) {
2351
+ const max = Math.max(...this.userDemand.map(x => x.value));
2352
+ return (value / max) * 100;
2353
+ }
2354
+ getCols(count) {
2355
+ return `repeat(${count}, minmax(0, 1fr))`;
2356
+ }
2357
+ static ɵfac = function WaitlistStatsOverviewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WaitlistStatsOverviewComponent)(i0.ɵɵdirectiveInject(WaitlistCodeService)); };
2358
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: WaitlistStatsOverviewComponent, selectors: [["app-waitlist-stats-overview"]], standalone: false, decls: 8, vars: 4, consts: [[4, "ngIf"], [1, "user-demand", "bg-gray-800", "rounded-lg", "p-6", "border", "border-gray-700", "hover:border-gray-600", "transition-colors", "duration-200"], [1, "text-lg", "font-semibold", "text-white", "mb-4"], [1, "text-gray-400", "text-sm", "mb-6"], ["class", "mb-5 last:mb-0", 4, "ngFor", "ngForOf"], [1, "grid", "gap-4", "w-full"], ["class", "w-full", 3, "stats", 4, "ngFor", "ngForOf"], [1, "w-full", 3, "stats"], [1, "mb-5", "last:mb-0"], [1, "flex", "items-center", "justify-between", "text-sm", "text-white", "mb-2"], [1, "w-full", "h-4", "bg-gray-700", "rounded-full", "overflow-hidden"], [1, "h-full", "bg-gradient-to-r", "from-blue-500", "to-purple-500", "rounded-full", "transition-all", "duration-700"]], template: function WaitlistStatsOverviewComponent_Template(rf, ctx) { if (rf & 1) {
2359
+ i0.ɵɵtemplate(0, WaitlistStatsOverviewComponent_ng_container_0_Template, 3, 3, "ng-container", 0);
2360
+ i0.ɵɵpipe(1, "async");
2361
+ i0.ɵɵelementStart(2, "div", 1)(3, "h2", 2);
2362
+ i0.ɵɵtext(4, "Demand by User Type");
2363
+ i0.ɵɵelementEnd();
2364
+ i0.ɵɵelementStart(5, "p", 3);
2365
+ i0.ɵɵtext(6, " See which user types have the most waitlist members ");
2366
+ i0.ɵɵelementEnd();
2367
+ i0.ɵɵtemplate(7, WaitlistStatsOverviewComponent_div_7_Template, 8, 4, "div", 4);
2368
+ i0.ɵɵelementEnd();
2369
+ } if (rf & 2) {
2370
+ i0.ɵɵproperty("ngIf", i0.ɵɵpipeBind1(1, 2, ctx.waitlistStats$));
2371
+ i0.ɵɵadvance(7);
2372
+ i0.ɵɵproperty("ngForOf", ctx.userDemand);
2373
+ } }, dependencies: [i2.NgForOf, i2.NgIf, WaitlistStatsCardComponent, i2.AsyncPipe], styles: [".user-demand[_ngcontent-%COMP%]{background:#29252d;border:1px solid #423d48;border-radius:.5rem;padding:1.5rem;transition:all .2s ease;margin-top:25px;box-shadow:0 10px 15px -3px #00000040,0 4px 6px -2px #00000026,inset 0 0 0 1px #ffffff0d}"] });
2374
+ }
2375
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WaitlistStatsOverviewComponent, [{
2376
+ type: Component,
2377
+ args: [{ selector: 'app-waitlist-stats-overview', standalone: false, template: "<ng-container *ngIf=\"waitlistStats$ | async as stats\">\r\n <div class=\"grid gap-4 w-full\"\r\n [style.grid-template-columns]=\"getCols(stats.length)\">\r\n <app-waitlist-stats-card\r\n *ngFor=\"let stat of stats\"\r\n class=\"w-full\"\r\n [stats]=\"stat\">\r\n </app-waitlist-stats-card>\r\n </div>\r\n</ng-container>\r\n<!-- DEMAND BY USER TYPE -->\r\n<div class=\"user-demand bg-gray-800 rounded-lg p-6 border border-gray-700 hover:border-gray-600 transition-colors duration-200\">\r\n <h2 class=\"text-lg font-semibold text-white mb-4\">Demand by User Type</h2>\r\n <p class=\"text-gray-400 text-sm mb-6\">\r\n See which user types have the most waitlist members\r\n </p>\r\n\r\n <div *ngFor=\"let item of userDemand\" class=\"mb-5 last:mb-0\">\r\n <div class=\"flex items-center justify-between text-sm text-white mb-2\">\r\n <span>{{ item.label }}</span>\r\n <span>{{ item.value }}</span>\r\n </div>\r\n\r\n <!-- Progress bar container -->\r\n <div class=\"w-full h-4 bg-gray-700 rounded-full overflow-hidden\">\r\n <div class=\"h-full bg-gradient-to-r from-blue-500 to-purple-500 rounded-full transition-all duration-700\"\r\n [style.width]=\"getPercentage(item.value) + '%'\">\r\n </div>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n\r\n", styles: [".user-demand{background:#29252d;border:1px solid #423d48;border-radius:.5rem;padding:1.5rem;transition:all .2s ease;margin-top:25px;box-shadow:0 10px 15px -3px #00000040,0 4px 6px -2px #00000026,inset 0 0 0 1px #ffffff0d}\n"] }]
2378
+ }], () => [{ type: WaitlistCodeService }], null); })();
2379
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WaitlistStatsOverviewComponent, { className: "WaitlistStatsOverviewComponent", filePath: "lib/components/wait-list-stats-overview/waitlist-stats-overview.component.ts", lineNumber: 12 }); })();
2380
+
2381
+ const INVITATION_CODE_CONFIG = new InjectionToken('InvitationCodeConfig');
2382
+ // Separate page components that have circular dependencies
2383
+ const PAGE_COMPONENTS = [
2384
+ CodeManagementComponent,
2385
+ InvitationCodesComponent,
2386
+ WaitlistComponent
2387
+ ];
2388
+ // UI components (no circular issues)
2389
+ const UI_COMPONENTS = [
2390
+ CodeManagementHeaderComponent,
2391
+ GenerateCodeDialogComponent,
2392
+ ConvertToInvitationDialogComponent,
2393
+ StatsOverviewComponent,
2394
+ WaitlistStatsOverviewComponent,
2395
+ StatsCardComponent,
2396
+ WaitlistStatsCardComponent
2397
+ ];
2398
+ // Apply forwardRef only to page components with circular dependencies
2399
+ const ALL_COMPONENTS = [
2400
+ // Page components with forwardRef
2401
+ forwardRef(() => CodeManagementComponent),
2402
+ forwardRef(() => InvitationCodesComponent),
2403
+ forwardRef(() => WaitlistComponent),
2404
+ // UI components without forwardRef
2405
+ ...UI_COMPONENTS
2406
+ ];
2407
+ class InvitationCodeModule {
2408
+ static forRoot(config) {
2409
+ return {
2410
+ ngModule: InvitationCodeModule,
2411
+ providers: [
2412
+ {
2413
+ provide: INVITATION_CODE_CONFIG,
2414
+ useValue: config
2415
+ },
2416
+ InvitationCodeService,
2417
+ WaitlistCodeService,
2418
+ InvitationGridService,
2419
+ WaitlistGridService
2420
+ ]
2421
+ };
2422
+ }
2423
+ static ɵfac = function InvitationCodeModule_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || InvitationCodeModule)(); };
2424
+ static ɵmod = /*@__PURE__*/ i0.ɵɵdefineNgModule({ type: InvitationCodeModule });
2425
+ static ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ imports: [CommonModule,
2426
+ FormsModule,
2427
+ ReactiveFormsModule,
2428
+ HttpClientModule,
2429
+ RouterModule,
2430
+ // Material
2431
+ MatDialogModule,
2432
+ MatButtonModule,
2433
+ MatInputModule,
2434
+ MatFormFieldModule,
2435
+ MatSelectModule,
2436
+ MatTableModule,
2437
+ MatPaginatorModule,
2438
+ MatSortModule,
2439
+ MatIconModule,
2440
+ MatTooltipModule,
2441
+ MatCardModule,
2442
+ MatDatepickerModule,
2443
+ MatNativeDateModule,
2444
+ MatProgressSpinnerModule,
2445
+ MatSnackBarModule,
2446
+ MatRadioModule,
2447
+ // Third-party
2448
+ GridModule] });
2449
+ }
2450
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(InvitationCodeModule, [{
2451
+ type: NgModule,
2452
+ args: [{
2453
+ imports: [
2454
+ CommonModule,
2455
+ FormsModule,
2456
+ ReactiveFormsModule,
2457
+ HttpClientModule,
2458
+ RouterModule,
2459
+ // Material
2460
+ MatDialogModule,
2461
+ MatButtonModule,
2462
+ MatInputModule,
2463
+ MatFormFieldModule,
2464
+ MatSelectModule,
2465
+ MatTableModule,
2466
+ MatPaginatorModule,
2467
+ MatSortModule,
2468
+ MatIconModule,
2469
+ MatTooltipModule,
2470
+ MatCardModule,
2471
+ MatDatepickerModule,
2472
+ MatNativeDateModule,
2473
+ MatProgressSpinnerModule,
2474
+ MatSnackBarModule,
2475
+ MatRadioModule,
2476
+ // Third-party
2477
+ GridModule,
2478
+ ],
2479
+ declarations: ALL_COMPONENTS,
2480
+ exports: [...PAGE_COMPONENTS, ...UI_COMPONENTS]
2481
+ }]
2482
+ }], null, null); })();
2483
+ (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(InvitationCodeModule, { declarations: [CodeManagementComponent, InvitationCodesComponent, WaitlistComponent, CodeManagementHeaderComponent,
2484
+ GenerateCodeDialogComponent,
2485
+ ConvertToInvitationDialogComponent,
2486
+ StatsOverviewComponent,
2487
+ WaitlistStatsOverviewComponent,
2488
+ StatsCardComponent,
2489
+ WaitlistStatsCardComponent], imports: [CommonModule,
2490
+ FormsModule,
2491
+ ReactiveFormsModule,
2492
+ HttpClientModule,
2493
+ RouterModule,
2494
+ // Material
2495
+ MatDialogModule,
2496
+ MatButtonModule,
2497
+ MatInputModule,
2498
+ MatFormFieldModule,
2499
+ MatSelectModule,
2500
+ MatTableModule,
2501
+ MatPaginatorModule,
2502
+ MatSortModule,
2503
+ MatIconModule,
2504
+ MatTooltipModule,
2505
+ MatCardModule,
2506
+ MatDatepickerModule,
2507
+ MatNativeDateModule,
2508
+ MatProgressSpinnerModule,
2509
+ MatSnackBarModule,
2510
+ MatRadioModule,
2511
+ // Third-party
2512
+ GridModule], exports: [CodeManagementComponent,
2513
+ InvitationCodesComponent,
2514
+ WaitlistComponent, CodeManagementHeaderComponent,
2515
+ GenerateCodeDialogComponent,
2516
+ ConvertToInvitationDialogComponent,
2517
+ StatsOverviewComponent,
2518
+ WaitlistStatsOverviewComponent,
2519
+ StatsCardComponent,
2520
+ WaitlistStatsCardComponent] }); })();
2521
+ i0.ɵɵsetComponentScope(CodeManagementComponent, function () { return [i2.NgIf, InvitationCodesComponent, WaitlistComponent, CodeManagementHeaderComponent,
2522
+ StatsOverviewComponent]; }, []);
2523
+ i0.ɵɵsetComponentScope(WaitlistComponent, function () { return [i2.NgForOf, i2.NgIf, i4$1.MatButton, i5.MatIcon, i4.GridComponent, WaitlistStatsOverviewComponent]; }, []);
2524
+
2525
+ // Core exports
2526
+
2527
+ /**
2528
+ * Generated bundle index. Do not edit.
2529
+ */
2530
+
2531
+ export { CodeManagementComponent, CodeManagementHeaderComponent, ConvertToInvitationDialogComponent, GenerateCodeDialogComponent, INVITATION_CODE_CONFIG, InvitationCodeModule, InvitationCodeService, InvitationCodesComponent, InvitationGridService, StatsCardComponent, StatsOverviewComponent, WaitlistCodeService, WaitlistComponent, WaitlistGridService, WaitlistStatsCardComponent, WaitlistStatsOverviewComponent };
2532
+ //# sourceMappingURL=invitation-code-lib.mjs.map