@memberjunction/ng-mj-livekit-room 6.2.0-edge.2 → 6.2.0-edge.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/lib/meetings/meeting-list.component.d.ts +30 -0
  2. package/dist/lib/meetings/meeting-list.component.d.ts.map +1 -0
  3. package/dist/lib/meetings/meeting-list.component.js +528 -0
  4. package/dist/lib/meetings/meeting-list.component.js.map +1 -0
  5. package/dist/lib/meetings/meeting-lobby.component.d.ts +25 -0
  6. package/dist/lib/meetings/meeting-lobby.component.d.ts.map +1 -0
  7. package/dist/lib/meetings/meeting-lobby.component.js +372 -0
  8. package/dist/lib/meetings/meeting-lobby.component.js.map +1 -0
  9. package/dist/lib/meetings/meeting-participant-picker.component.d.ts +43 -0
  10. package/dist/lib/meetings/meeting-participant-picker.component.d.ts.map +1 -0
  11. package/dist/lib/meetings/meeting-participant-picker.component.js +595 -0
  12. package/dist/lib/meetings/meeting-participant-picker.component.js.map +1 -0
  13. package/dist/lib/meetings/meeting-schedule-form.component.d.ts +32 -0
  14. package/dist/lib/meetings/meeting-schedule-form.component.d.ts.map +1 -0
  15. package/dist/lib/meetings/meeting-schedule-form.component.js +487 -0
  16. package/dist/lib/meetings/meeting-schedule-form.component.js.map +1 -0
  17. package/dist/lib/mj-livekit-room.component.d.ts +49 -3
  18. package/dist/lib/mj-livekit-room.component.d.ts.map +1 -1
  19. package/dist/lib/mj-livekit-room.component.js +330 -65
  20. package/dist/lib/mj-livekit-room.component.js.map +1 -1
  21. package/dist/lib/turn-state-poller.d.ts +57 -0
  22. package/dist/lib/turn-state-poller.d.ts.map +1 -0
  23. package/dist/lib/turn-state-poller.js +108 -0
  24. package/dist/lib/turn-state-poller.js.map +1 -0
  25. package/dist/lib/turn-taking-options.d.ts +63 -0
  26. package/dist/lib/turn-taking-options.d.ts.map +1 -0
  27. package/dist/lib/turn-taking-options.js +63 -0
  28. package/dist/lib/turn-taking-options.js.map +1 -0
  29. package/dist/public-api.d.ts +6 -0
  30. package/dist/public-api.d.ts.map +1 -1
  31. package/dist/public-api.js +6 -0
  32. package/dist/public-api.js.map +1 -1
  33. package/package.json +9 -8
@@ -0,0 +1,30 @@
1
+ import { EventEmitter, OnInit } from '@angular/core';
2
+ import type { IMetadataProvider } from '@memberjunction/core';
3
+ import { type MeetingInfo } from '@memberjunction/graphql-dataprovider';
4
+ import * as i0 from "@angular/core";
5
+ export declare class MJMeetingListComponent implements OnInit {
6
+ private readonly cdr;
7
+ Provider?: IMetadataProvider;
8
+ JoinMeeting: EventEmitter<MeetingInfo>;
9
+ ScheduleRequested: EventEmitter<void>;
10
+ EditMeetingRequested: EventEmitter<MeetingInfo>;
11
+ Meetings: MeetingInfo[];
12
+ FilteredMeetings: MeetingInfo[];
13
+ ActiveFilter: 'all' | 'live' | 'scheduled' | 'past';
14
+ SearchQuery: string;
15
+ Loading: boolean;
16
+ ErrorMessage: string | null;
17
+ ngOnInit(): void;
18
+ LoadMeetings(): Promise<void>;
19
+ SetFilter(filter: 'all' | 'live' | 'scheduled' | 'past'): void;
20
+ OnSearchChange(): void;
21
+ ApplyFilter(): void;
22
+ OnJoin(meeting: MeetingInfo): void;
23
+ OnSchedule(): void;
24
+ OnEdit(meeting: MeetingInfo): void;
25
+ OnCancelMeeting(meeting: MeetingInfo): Promise<void>;
26
+ FormatTime(dateStr?: string): string;
27
+ static ɵfac: i0.ɵɵFactoryDeclaration<MJMeetingListComponent, never>;
28
+ static ɵcmp: i0.ɵɵComponentDeclaration<MJMeetingListComponent, "mj-meeting-list", never, { "Provider": { "alias": "Provider"; "required": false; }; }, { "JoinMeeting": "JoinMeeting"; "ScheduleRequested": "ScheduleRequested"; "EditMeetingRequested": "EditMeetingRequested"; }, never, never, true, never>;
29
+ }
30
+ //# sourceMappingURL=meeting-list.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meeting-list.component.d.ts","sourceRoot":"","sources":["../../../src/lib/meetings/meeting-list.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyD,YAAY,EAAS,MAAM,EAAkB,MAAM,eAAe,CAAC;AAGnI,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sCAAsC,CAAC;;AAE9C,qBAiaa,sBAAuB,YAAW,MAAM;IACnD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiD;IAE5D,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAE5B,WAAW,4BAAmC;IAC9C,iBAAiB,qBAA4B;IAC7C,oBAAoB,4BAAmC;IAE1D,QAAQ,EAAE,WAAW,EAAE,CAAM;IAC7B,gBAAgB,EAAE,WAAW,EAAE,CAAM;IACrC,YAAY,EAAE,KAAK,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAS;IAC5D,WAAW,EAAE,MAAM,CAAM;IACzB,OAAO,EAAE,OAAO,CAAS;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C,QAAQ,IAAI,IAAI;IAIH,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBnC,SAAS,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI;IAK9D,cAAc,IAAI,IAAI;IAItB,WAAW,IAAI,IAAI;IAyBnB,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIlC,UAAU,IAAI,IAAI;IAIlB,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAI5B,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB1D,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;yCApGhC,sBAAsB;2CAAtB,sBAAsB;CAkHlC"}
@@ -0,0 +1,528 @@
1
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { GraphQLDataProvider, GraphQLMeetingClient, } from '@memberjunction/graphql-dataprovider';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/forms";
7
+ const _forTrack0 = ($index, $item) => $item.ID;
8
+ function MJMeetingListComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
9
+ i0.ɵɵelementStart(0, "div", 10);
10
+ i0.ɵɵelement(1, "i", 14);
11
+ i0.ɵɵelementStart(2, "span");
12
+ i0.ɵɵtext(3, "Loading meetings\u2026");
13
+ i0.ɵɵelementEnd()();
14
+ } }
15
+ function MJMeetingListComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
16
+ const _r1 = i0.ɵɵgetCurrentView();
17
+ i0.ɵɵelementStart(0, "div", 11);
18
+ i0.ɵɵelement(1, "i", 15);
19
+ i0.ɵɵelementStart(2, "span");
20
+ i0.ɵɵtext(3);
21
+ i0.ɵɵelementEnd();
22
+ i0.ɵɵelementStart(4, "button", 16);
23
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Conditional_19_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.LoadMeetings()); });
24
+ i0.ɵɵtext(5, "Retry");
25
+ i0.ɵɵelementEnd()();
26
+ } if (rf & 2) {
27
+ const ctx_r1 = i0.ɵɵnextContext();
28
+ i0.ɵɵadvance(3);
29
+ i0.ɵɵtextInterpolate(ctx_r1.ErrorMessage);
30
+ } }
31
+ function MJMeetingListComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
32
+ const _r3 = i0.ɵɵgetCurrentView();
33
+ i0.ɵɵelementStart(0, "div", 12)(1, "div", 17);
34
+ i0.ɵɵelement(2, "i", 18);
35
+ i0.ɵɵelementEnd();
36
+ i0.ɵɵelementStart(3, "h3", 19);
37
+ i0.ɵɵtext(4, "No meetings found");
38
+ i0.ɵɵelementEnd();
39
+ i0.ɵɵelementStart(5, "p", 20);
40
+ i0.ɵɵtext(6);
41
+ i0.ɵɵelementEnd();
42
+ i0.ɵɵelementStart(7, "button", 8);
43
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Conditional_20_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnSchedule()); });
44
+ i0.ɵɵelement(8, "i", 9);
45
+ i0.ɵɵtext(9, " Schedule your first meeting ");
46
+ i0.ɵɵelementEnd()();
47
+ } if (rf & 2) {
48
+ const ctx_r1 = i0.ɵɵnextContext();
49
+ i0.ɵɵadvance(6);
50
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.SearchQuery ? "Try adjusting your search query or filter." : "You have no meetings scheduled.", " ");
51
+ } }
52
+ function MJMeetingListComponent_Conditional_21_For_2_Conditional_3_Template(rf, ctx) { if (rf & 1) {
53
+ i0.ɵɵelement(0, "span", 7);
54
+ } }
55
+ function MJMeetingListComponent_Conditional_21_For_2_Conditional_5_Template(rf, ctx) { if (rf & 1) {
56
+ i0.ɵɵelementStart(0, "span", 25);
57
+ i0.ɵɵelement(1, "i", 35);
58
+ i0.ɵɵtext(2);
59
+ i0.ɵɵelementEnd();
60
+ } if (rf & 2) {
61
+ const m_r4 = i0.ɵɵnextContext().$implicit;
62
+ i0.ɵɵproperty("title", i0.ɵɵinterpolate1("Recording ", m_r4.RecordingPolicy));
63
+ i0.ɵɵadvance(2);
64
+ i0.ɵɵtextInterpolate1(" ", m_r4.RecordingPolicy, " ");
65
+ } }
66
+ function MJMeetingListComponent_Conditional_21_For_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
67
+ i0.ɵɵelementStart(0, "p", 27);
68
+ i0.ɵɵtext(1);
69
+ i0.ɵɵelementEnd();
70
+ } if (rf & 2) {
71
+ const m_r4 = i0.ɵɵnextContext().$implicit;
72
+ i0.ɵɵadvance();
73
+ i0.ɵɵtextInterpolate(m_r4.Description);
74
+ } }
75
+ function MJMeetingListComponent_Conditional_21_For_2_Conditional_14_Template(rf, ctx) { if (rf & 1) {
76
+ i0.ɵɵelementStart(0, "div", 29);
77
+ i0.ɵɵelement(1, "i", 36);
78
+ i0.ɵɵelementStart(2, "span");
79
+ i0.ɵɵtext(3);
80
+ i0.ɵɵelementEnd()();
81
+ } if (rf & 2) {
82
+ const m_r4 = i0.ɵɵnextContext().$implicit;
83
+ const ctx_r1 = i0.ɵɵnextContext(2);
84
+ i0.ɵɵadvance(3);
85
+ i0.ɵɵtextInterpolate(ctx_r1.FormatTime(m_r4.ScheduledStartAt));
86
+ } }
87
+ function MJMeetingListComponent_Conditional_21_For_2_Conditional_15_Template(rf, ctx) { if (rf & 1) {
88
+ i0.ɵɵelementStart(0, "div", 31);
89
+ i0.ɵɵelement(1, "i", 37);
90
+ i0.ɵɵelementStart(2, "span");
91
+ i0.ɵɵtext(3);
92
+ i0.ɵɵelementEnd()();
93
+ } if (rf & 2) {
94
+ const m_r4 = i0.ɵɵnextContext().$implicit;
95
+ i0.ɵɵadvance(3);
96
+ i0.ɵɵtextInterpolate2("Dial-In: ", m_r4.DialInPhoneNumber, " (PIN: ", m_r4.DialInCode, ")");
97
+ } }
98
+ function MJMeetingListComponent_Conditional_21_For_2_Conditional_16_Template(rf, ctx) { if (rf & 1) {
99
+ i0.ɵɵelementStart(0, "div", 29);
100
+ i0.ɵɵelement(1, "i", 38);
101
+ i0.ɵɵelementStart(2, "span");
102
+ i0.ɵɵtext(3);
103
+ i0.ɵɵelementEnd()();
104
+ } if (rf & 2) {
105
+ const m_r4 = i0.ɵɵnextContext().$implicit;
106
+ i0.ɵɵadvance(3);
107
+ i0.ɵɵtextInterpolate2("", m_r4.Participants.length, " participant", m_r4.Participants.length > 1 ? "s" : "");
108
+ } }
109
+ function MJMeetingListComponent_Conditional_21_For_2_Conditional_18_Template(rf, ctx) { if (rf & 1) {
110
+ const _r5 = i0.ɵɵgetCurrentView();
111
+ i0.ɵɵelementStart(0, "button", 39);
112
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Conditional_21_For_2_Conditional_18_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const m_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnJoin(m_r4)); });
113
+ i0.ɵɵelement(1, "i", 40);
114
+ i0.ɵɵtext(2, " Join Call ");
115
+ i0.ɵɵelementEnd();
116
+ } }
117
+ function MJMeetingListComponent_Conditional_21_For_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
118
+ const _r6 = i0.ɵɵgetCurrentView();
119
+ i0.ɵɵelementStart(0, "button", 8);
120
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Conditional_21_For_2_Conditional_19_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const m_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnJoin(m_r4)); });
121
+ i0.ɵɵelement(1, "i", 41);
122
+ i0.ɵɵtext(2, " Enter Lobby ");
123
+ i0.ɵɵelementEnd();
124
+ i0.ɵɵelementStart(3, "button", 42);
125
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Conditional_21_For_2_Conditional_19_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r6); const m_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnEdit(m_r4)); });
126
+ i0.ɵɵelement(4, "i", 43);
127
+ i0.ɵɵtext(5, " Edit ");
128
+ i0.ɵɵelementEnd();
129
+ } }
130
+ function MJMeetingListComponent_Conditional_21_For_2_Conditional_20_Template(rf, ctx) { if (rf & 1) {
131
+ const _r7 = i0.ɵɵgetCurrentView();
132
+ i0.ɵɵelementStart(0, "button", 44);
133
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Conditional_21_For_2_Conditional_20_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r7); const m_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnCancelMeeting(m_r4)); });
134
+ i0.ɵɵelement(1, "i", 45);
135
+ i0.ɵɵtext(2, " Cancel ");
136
+ i0.ɵɵelementEnd();
137
+ } }
138
+ function MJMeetingListComponent_Conditional_21_For_2_Template(rf, ctx) { if (rf & 1) {
139
+ i0.ɵɵelementStart(0, "div", 22)(1, "div", 23)(2, "span", 24);
140
+ i0.ɵɵconditionalCreate(3, MJMeetingListComponent_Conditional_21_For_2_Conditional_3_Template, 1, 0, "span", 7);
141
+ i0.ɵɵtext(4);
142
+ i0.ɵɵelementEnd();
143
+ i0.ɵɵconditionalCreate(5, MJMeetingListComponent_Conditional_21_For_2_Conditional_5_Template, 3, 3, "span", 25);
144
+ i0.ɵɵelementEnd();
145
+ i0.ɵɵelementStart(6, "h3", 26);
146
+ i0.ɵɵtext(7);
147
+ i0.ɵɵelementEnd();
148
+ i0.ɵɵconditionalCreate(8, MJMeetingListComponent_Conditional_21_For_2_Conditional_8_Template, 2, 1, "p", 27);
149
+ i0.ɵɵelementStart(9, "div", 28)(10, "div", 29);
150
+ i0.ɵɵelement(11, "i", 30);
151
+ i0.ɵɵelementStart(12, "span");
152
+ i0.ɵɵtext(13);
153
+ i0.ɵɵelementEnd()();
154
+ i0.ɵɵconditionalCreate(14, MJMeetingListComponent_Conditional_21_For_2_Conditional_14_Template, 4, 1, "div", 29);
155
+ i0.ɵɵconditionalCreate(15, MJMeetingListComponent_Conditional_21_For_2_Conditional_15_Template, 4, 2, "div", 31);
156
+ i0.ɵɵconditionalCreate(16, MJMeetingListComponent_Conditional_21_For_2_Conditional_16_Template, 4, 2, "div", 29);
157
+ i0.ɵɵelementEnd();
158
+ i0.ɵɵelementStart(17, "div", 32);
159
+ i0.ɵɵconditionalCreate(18, MJMeetingListComponent_Conditional_21_For_2_Conditional_18_Template, 3, 0, "button", 33)(19, MJMeetingListComponent_Conditional_21_For_2_Conditional_19_Template, 6, 0);
160
+ i0.ɵɵconditionalCreate(20, MJMeetingListComponent_Conditional_21_For_2_Conditional_20_Template, 3, 0, "button", 34);
161
+ i0.ɵɵelementEnd()();
162
+ } if (rf & 2) {
163
+ const m_r4 = ctx.$implicit;
164
+ i0.ɵɵclassProp("mj-mtg-card--live", m_r4.Status === "Live");
165
+ i0.ɵɵadvance(2);
166
+ i0.ɵɵclassMap("mj-mtg-pill--" + m_r4.Status.toLowerCase());
167
+ i0.ɵɵadvance();
168
+ i0.ɵɵconditional(m_r4.Status === "Live" ? 3 : -1);
169
+ i0.ɵɵadvance();
170
+ i0.ɵɵtextInterpolate1(" ", m_r4.Status, " ");
171
+ i0.ɵɵadvance();
172
+ i0.ɵɵconditional(m_r4.RecordingPolicy !== "Off" ? 5 : -1);
173
+ i0.ɵɵadvance(2);
174
+ i0.ɵɵtextInterpolate(m_r4.Title);
175
+ i0.ɵɵadvance();
176
+ i0.ɵɵconditional(m_r4.Description ? 8 : -1);
177
+ i0.ɵɵadvance(5);
178
+ i0.ɵɵtextInterpolate1("Host: ", m_r4.HostUserName || "Host");
179
+ i0.ɵɵadvance();
180
+ i0.ɵɵconditional(m_r4.ScheduledStartAt ? 14 : -1);
181
+ i0.ɵɵadvance();
182
+ i0.ɵɵconditional(m_r4.AllowPhoneDialIn && m_r4.DialInPhoneNumber ? 15 : -1);
183
+ i0.ɵɵadvance();
184
+ i0.ɵɵconditional(m_r4.Participants && m_r4.Participants.length > 0 ? 16 : -1);
185
+ i0.ɵɵadvance(2);
186
+ i0.ɵɵconditional(m_r4.Status === "Live" ? 18 : m_r4.Status === "Scheduled" ? 19 : -1);
187
+ i0.ɵɵadvance(2);
188
+ i0.ɵɵconditional(m_r4.Status === "Live" || m_r4.Status === "Scheduled" ? 20 : -1);
189
+ } }
190
+ function MJMeetingListComponent_Conditional_21_Template(rf, ctx) { if (rf & 1) {
191
+ i0.ɵɵelementStart(0, "div", 13);
192
+ i0.ɵɵrepeaterCreate(1, MJMeetingListComponent_Conditional_21_For_2_Template, 21, 15, "div", 21, _forTrack0);
193
+ i0.ɵɵelementEnd();
194
+ } if (rf & 2) {
195
+ const ctx_r1 = i0.ɵɵnextContext();
196
+ i0.ɵɵadvance();
197
+ i0.ɵɵrepeater(ctx_r1.FilteredMeetings);
198
+ } }
199
+ export class MJMeetingListComponent {
200
+ cdr = inject(ChangeDetectorRef, { optional: true });
201
+ Provider;
202
+ JoinMeeting = new EventEmitter();
203
+ ScheduleRequested = new EventEmitter();
204
+ EditMeetingRequested = new EventEmitter();
205
+ Meetings = [];
206
+ FilteredMeetings = [];
207
+ ActiveFilter = 'all';
208
+ SearchQuery = '';
209
+ Loading = false;
210
+ ErrorMessage = null;
211
+ ngOnInit() {
212
+ void this.LoadMeetings();
213
+ }
214
+ async LoadMeetings() {
215
+ this.Loading = true;
216
+ this.ErrorMessage = null;
217
+ this.cdr?.markForCheck();
218
+ try {
219
+ const client = new GraphQLMeetingClient(this.Provider || GraphQLDataProvider.Instance);
220
+ this.Meetings = await client.MyMeetings();
221
+ this.ApplyFilter();
222
+ }
223
+ catch (err) {
224
+ this.ErrorMessage = err instanceof Error ? err.message : String(err);
225
+ }
226
+ finally {
227
+ this.Loading = false;
228
+ this.cdr?.markForCheck();
229
+ }
230
+ }
231
+ SetFilter(filter) {
232
+ this.ActiveFilter = filter;
233
+ this.ApplyFilter();
234
+ }
235
+ OnSearchChange() {
236
+ this.ApplyFilter();
237
+ }
238
+ ApplyFilter() {
239
+ let list = [...this.Meetings];
240
+ if (this.ActiveFilter === 'live') {
241
+ list = list.filter((m) => m.Status === 'Live');
242
+ }
243
+ else if (this.ActiveFilter === 'scheduled') {
244
+ list = list.filter((m) => m.Status === 'Scheduled');
245
+ }
246
+ else if (this.ActiveFilter === 'past') {
247
+ list = list.filter((m) => m.Status === 'Ended' || m.Status === 'Cancelled');
248
+ }
249
+ if (this.SearchQuery.trim()) {
250
+ const q = this.SearchQuery.toLowerCase().trim();
251
+ list = list.filter((m) => m.Title.toLowerCase().includes(q) ||
252
+ (m.Description && m.Description.toLowerCase().includes(q)) ||
253
+ (m.HostUserName && m.HostUserName.toLowerCase().includes(q)));
254
+ }
255
+ this.FilteredMeetings = list;
256
+ this.cdr?.markForCheck();
257
+ }
258
+ OnJoin(meeting) {
259
+ this.JoinMeeting.emit(meeting);
260
+ }
261
+ OnSchedule() {
262
+ this.ScheduleRequested.emit();
263
+ }
264
+ OnEdit(meeting) {
265
+ this.EditMeetingRequested.emit(meeting);
266
+ }
267
+ async OnCancelMeeting(meeting) {
268
+ if (!confirm(`Are you sure you want to cancel the meeting "${meeting.Title}"?`)) {
269
+ return;
270
+ }
271
+ try {
272
+ const client = new GraphQLMeetingClient(this.Provider || GraphQLDataProvider.Instance);
273
+ const res = await client.CancelMeeting(meeting.ID);
274
+ if (res.Success) {
275
+ await this.LoadMeetings();
276
+ }
277
+ else {
278
+ alert(res.ErrorMessage || 'Failed to cancel meeting.');
279
+ }
280
+ }
281
+ catch (err) {
282
+ alert(err instanceof Error ? err.message : String(err));
283
+ }
284
+ }
285
+ FormatTime(dateStr) {
286
+ if (!dateStr)
287
+ return '';
288
+ try {
289
+ const d = new Date(dateStr);
290
+ return d.toLocaleString(undefined, {
291
+ month: 'short',
292
+ day: 'numeric',
293
+ hour: 'numeric',
294
+ minute: '2-digit',
295
+ });
296
+ }
297
+ catch {
298
+ return dateStr;
299
+ }
300
+ }
301
+ static ɵfac = function MJMeetingListComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJMeetingListComponent)(); };
302
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJMeetingListComponent, selectors: [["mj-meeting-list"]], inputs: { Provider: "Provider" }, outputs: { JoinMeeting: "JoinMeeting", ScheduleRequested: "ScheduleRequested", EditMeetingRequested: "EditMeetingRequested" }, decls: 22, vars: 10, consts: [[1, "mj-mtg-list-view"], [1, "mj-mtg-list-view__toolbar"], [1, "mj-mtg-list-view__search-wrap"], [1, "fa-solid", "fa-magnifying-glass", "mj-mtg-list-view__search-icon"], ["type", "text", "placeholder", "Search meetings by title or host\u2026", 1, "mj-input", "mj-mtg-list-view__search-input", 3, "ngModelChange", "ngModel"], [1, "mj-mtg-list-view__filters"], ["type", "button", 1, "mj-mtg-filter-btn", 3, "click"], [1, "mj-mtg-dot-live"], ["type", "button", 1, "mj-btn", "mj-btn--primary", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "mj-mtg-status"], [1, "mj-mtg-status", "mj-mtg-status--error"], [1, "mj-mtg-empty"], [1, "mj-mtg-grid"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-triangle-exclamation"], ["type", "button", 1, "mj-btn", "mj-btn--secondary", 3, "click"], [1, "mj-mtg-empty__icon"], [1, "fa-solid", "fa-calendar-days"], [1, "mj-mtg-empty__title"], [1, "mj-mtg-empty__subtitle"], [1, "mj-mtg-card", 3, "mj-mtg-card--live"], [1, "mj-mtg-card"], [1, "mj-mtg-card__header"], [1, "mj-mtg-pill"], [1, "mj-mtg-badge-rec", 3, "title"], [1, "mj-mtg-card__title"], [1, "mj-mtg-card__desc"], [1, "mj-mtg-card__meta"], [1, "mj-mtg-card__meta-item"], [1, "fa-solid", "fa-user"], [1, "mj-mtg-card__meta-item", "mj-mtg-card__dialin"], [1, "mj-mtg-card__actions"], ["type", "button", 1, "mj-btn", "mj-btn--primary", "mj-btn--success"], ["type", "button", "title", "Cancel Meeting", 1, "mj-btn", "mj-btn--danger-text"], [1, "fa-solid", "fa-record-vinyl"], [1, "fa-solid", "fa-clock"], [1, "fa-solid", "fa-phone"], [1, "fa-solid", "fa-users"], ["type", "button", 1, "mj-btn", "mj-btn--primary", "mj-btn--success", 3, "click"], [1, "fa-solid", "fa-video"], [1, "fa-solid", "fa-arrow-right-to-bracket"], ["type", "button", "title", "Edit Meeting", 1, "mj-btn", "mj-btn--secondary", 3, "click"], [1, "fa-solid", "fa-pen"], ["type", "button", "title", "Cancel Meeting", 1, "mj-btn", "mj-btn--danger-text", 3, "click"], [1, "fa-solid", "fa-ban"]], template: function MJMeetingListComponent_Template(rf, ctx) { if (rf & 1) {
303
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
304
+ i0.ɵɵelement(3, "i", 3);
305
+ i0.ɵɵelementStart(4, "input", 4);
306
+ i0.ɵɵtwoWayListener("ngModelChange", function MJMeetingListComponent_Template_input_ngModelChange_4_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.SearchQuery, $event) || (ctx.SearchQuery = $event); return $event; });
307
+ i0.ɵɵlistener("ngModelChange", function MJMeetingListComponent_Template_input_ngModelChange_4_listener() { return ctx.OnSearchChange(); });
308
+ i0.ɵɵelementEnd()();
309
+ i0.ɵɵelementStart(5, "div", 5)(6, "button", 6);
310
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Template_button_click_6_listener() { return ctx.SetFilter("all"); });
311
+ i0.ɵɵtext(7, " All ");
312
+ i0.ɵɵelementEnd();
313
+ i0.ɵɵelementStart(8, "button", 6);
314
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Template_button_click_8_listener() { return ctx.SetFilter("live"); });
315
+ i0.ɵɵelement(9, "span", 7);
316
+ i0.ɵɵtext(10, " Live ");
317
+ i0.ɵɵelementEnd();
318
+ i0.ɵɵelementStart(11, "button", 6);
319
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Template_button_click_11_listener() { return ctx.SetFilter("scheduled"); });
320
+ i0.ɵɵtext(12, " Scheduled ");
321
+ i0.ɵɵelementEnd();
322
+ i0.ɵɵelementStart(13, "button", 6);
323
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Template_button_click_13_listener() { return ctx.SetFilter("past"); });
324
+ i0.ɵɵtext(14, " Past ");
325
+ i0.ɵɵelementEnd()();
326
+ i0.ɵɵelementStart(15, "button", 8);
327
+ i0.ɵɵlistener("click", function MJMeetingListComponent_Template_button_click_15_listener() { return ctx.OnSchedule(); });
328
+ i0.ɵɵelement(16, "i", 9);
329
+ i0.ɵɵtext(17, " Schedule Meeting ");
330
+ i0.ɵɵelementEnd()();
331
+ i0.ɵɵconditionalCreate(18, MJMeetingListComponent_Conditional_18_Template, 4, 0, "div", 10)(19, MJMeetingListComponent_Conditional_19_Template, 6, 1, "div", 11)(20, MJMeetingListComponent_Conditional_20_Template, 10, 1, "div", 12)(21, MJMeetingListComponent_Conditional_21_Template, 3, 0, "div", 13);
332
+ i0.ɵɵelementEnd();
333
+ } if (rf & 2) {
334
+ i0.ɵɵadvance(4);
335
+ i0.ɵɵtwoWayProperty("ngModel", ctx.SearchQuery);
336
+ i0.ɵɵadvance(2);
337
+ i0.ɵɵclassProp("mj-mtg-filter-btn--active", ctx.ActiveFilter === "all");
338
+ i0.ɵɵadvance(2);
339
+ i0.ɵɵclassProp("mj-mtg-filter-btn--active", ctx.ActiveFilter === "live");
340
+ i0.ɵɵadvance(3);
341
+ i0.ɵɵclassProp("mj-mtg-filter-btn--active", ctx.ActiveFilter === "scheduled");
342
+ i0.ɵɵadvance(2);
343
+ i0.ɵɵclassProp("mj-mtg-filter-btn--active", ctx.ActiveFilter === "past");
344
+ i0.ɵɵadvance(5);
345
+ i0.ɵɵconditional(ctx.Loading ? 18 : ctx.ErrorMessage ? 19 : ctx.FilteredMeetings.length === 0 ? 20 : 21);
346
+ } }, dependencies: [CommonModule, FormsModule, i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel], styles: ["[_nghost-%COMP%] {\n display: block;\n padding: var(--mj-space-6, 24px) var(--mj-space-4, 16px);\n max-width: 72rem;\n margin: 0 auto;\n }\n .mj-mtg-list-view__toolbar[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--mj-space-3, 12px);\n margin-bottom: var(--mj-space-6, 24px);\n }\n .mj-mtg-list-view__search-wrap[_ngcontent-%COMP%] {\n position: relative;\n flex: 1;\n min-width: 220px;\n }\n .mj-mtg-list-view__search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-secondary, #94a3b8);\n font-size: 0.875rem;\n }\n .mj-mtg-list-view__search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 9px 12px 9px 34px;\n border: 1px solid var(--mj-border-default, #cbd5e1);\n border-radius: 8px;\n font-size: 0.875rem;\n box-sizing: border-box;\n }\n .mj-mtg-list-view__filters[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n background: var(--mj-bg-surface-card, #f1f5f9);\n padding: 4px;\n border-radius: 8px;\n }\n .mj-mtg-filter-btn[_ngcontent-%COMP%] {\n border: none;\n background: none;\n padding: 6px 12px;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n border-radius: 6px;\n color: var(--mj-text-secondary, #64748b);\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n .mj-mtg-filter-btn--active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface, #ffffff);\n color: var(--mj-text-primary, #0f172a);\n font-weight: 600;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n }\n .mj-mtg-dot-live[_ngcontent-%COMP%] {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--mj-status-success, #16a34a);\n display: inline-block;\n box-shadow: 0 0 0 2px var(--mj-status-success-subtle, rgba(22, 163, 74, 0.2));\n animation: _ngcontent-%COMP%_pulse 2s infinite;\n }\n @keyframes _ngcontent-%COMP%_pulse {\n 0% { transform: scale(0.95); opacity: 0.9; }\n 50% { transform: scale(1.15); opacity: 1; }\n 100% { transform: scale(0.95); opacity: 0.9; }\n }\n .mj-mtg-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: var(--mj-space-4, 16px);\n }\n .mj-mtg-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface, #ffffff);\n border: 1px solid var(--mj-border-default, #e2e8f0);\n border-radius: 12px;\n padding: var(--mj-space-5, 20px);\n display: flex;\n flex-direction: column;\n transition: border-color 0.2s, box-shadow 0.2s;\n }\n .mj-mtg-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary, #0076b6);\n box-shadow: var(--mj-shadow-md, 0 4px 12px rgba(0, 0, 0, 0.05));\n }\n .mj-mtg-card--live[_ngcontent-%COMP%] {\n border-color: var(--mj-status-success, #22c55e);\n background: var(--mj-status-success-subtle, #f0fdf4);\n }\n .mj-mtg-card__header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--mj-space-2, 8px);\n }\n .mj-mtg-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 8px;\n border-radius: 999px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n }\n .mj-mtg-pill--live[_ngcontent-%COMP%] {\n background: var(--mj-status-success-subtle, #dcfce7);\n color: var(--mj-status-success, #15803d);\n }\n .mj-mtg-pill--scheduled[_ngcontent-%COMP%] {\n background: var(--mj-status-info-subtle, #e0f2fe);\n color: var(--mj-status-info, #0369a1);\n }\n .mj-mtg-pill--ended[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card, #f1f5f9);\n color: var(--mj-text-secondary, #64748b);\n }\n .mj-mtg-pill--cancelled[_ngcontent-%COMP%] {\n background: var(--mj-status-error-subtle, #fee2e2);\n color: var(--mj-status-error, #b91c1c);\n }\n .mj-mtg-badge-rec[_ngcontent-%COMP%] {\n font-size: 0.6875rem;\n color: var(--mj-status-error, #ef4444);\n display: flex;\n align-items: center;\n gap: 4px;\n font-weight: 500;\n }\n .mj-mtg-card__title[_ngcontent-%COMP%] {\n margin: 0 0 var(--mj-space-2, 8px) 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary, #0f172a);\n }\n .mj-mtg-card__desc[_ngcontent-%COMP%] {\n margin: 0 0 var(--mj-space-4, 16px) 0;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary, #64748b);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n .mj-mtg-card__meta[_ngcontent-%COMP%] {\n margin-top: auto;\n display: flex;\n flex-direction: column;\n gap: 6px;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary, #64748b);\n padding-top: var(--mj-space-3, 12px);\n border-top: 1px solid var(--mj-border-default, #f1f5f9);\n }\n .mj-mtg-card__meta-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .mj-mtg-card__dialin[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary, #0076b6);\n }\n .mj-mtg-card__actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: var(--mj-space-4, 16px);\n }\n .mj-btn[_ngcontent-%COMP%] {\n padding: 8px 14px;\n border-radius: 6px;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: none;\n }\n .mj-btn--primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary, #0076b6);\n color: var(--mj-text-inverse, #ffffff);\n }\n .mj-btn--success[_ngcontent-%COMP%] {\n background: var(--mj-status-success, #16a34a);\n color: var(--mj-text-inverse, #ffffff);\n }\n .mj-btn--secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface, #ffffff);\n color: var(--mj-text-primary, #1e293b);\n border: 1px solid var(--mj-border-default, #cbd5e1);\n }\n .mj-btn--danger-text[_ngcontent-%COMP%] {\n background: none;\n color: var(--mj-status-error, #ef4444);\n padding: 6px 8px;\n }\n .mj-mtg-status[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 48px;\n color: var(--mj-text-secondary, #64748b);\n }\n .mj-mtg-status[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2rem;\n color: var(--mj-brand-primary, #0076b6);\n }\n .mj-mtg-empty[_ngcontent-%COMP%] {\n text-align: center;\n padding: 64px 16px;\n max-width: 24rem;\n margin: 0 auto;\n }\n .mj-mtg-empty__icon[_ngcontent-%COMP%] {\n font-size: 2.5rem;\n color: var(--mj-text-secondary, #94a3b8);\n margin-bottom: 12px;\n }\n .mj-mtg-empty__title[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n font-weight: 600;\n margin: 0 0 6px 0;\n color: var(--mj-text-primary, #0f172a);\n }\n .mj-mtg-empty__subtitle[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: var(--mj-text-secondary, #64748b);\n margin: 0 0 16px 0;\n }"], changeDetection: 0 });
347
+ }
348
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJMeetingListComponent, [{
349
+ type: Component,
350
+ args: [{ selector: 'mj-meeting-list', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule], template: `
351
+ <div class="mj-mtg-list-view">
352
+ <!-- Toolbar -->
353
+ <div class="mj-mtg-list-view__toolbar">
354
+ <div class="mj-mtg-list-view__search-wrap">
355
+ <i class="fa-solid fa-magnifying-glass mj-mtg-list-view__search-icon"></i>
356
+ <input
357
+ type="text"
358
+ class="mj-input mj-mtg-list-view__search-input"
359
+ placeholder="Search meetings by title or host…"
360
+ [(ngModel)]="SearchQuery"
361
+ (ngModelChange)="OnSearchChange()"
362
+ />
363
+ </div>
364
+
365
+ <div class="mj-mtg-list-view__filters">
366
+ <button
367
+ type="button"
368
+ class="mj-mtg-filter-btn"
369
+ [class.mj-mtg-filter-btn--active]="ActiveFilter === 'all'"
370
+ (click)="SetFilter('all')">
371
+ All
372
+ </button>
373
+ <button
374
+ type="button"
375
+ class="mj-mtg-filter-btn"
376
+ [class.mj-mtg-filter-btn--active]="ActiveFilter === 'live'"
377
+ (click)="SetFilter('live')">
378
+ <span class="mj-mtg-dot-live"></span> Live
379
+ </button>
380
+ <button
381
+ type="button"
382
+ class="mj-mtg-filter-btn"
383
+ [class.mj-mtg-filter-btn--active]="ActiveFilter === 'scheduled'"
384
+ (click)="SetFilter('scheduled')">
385
+ Scheduled
386
+ </button>
387
+ <button
388
+ type="button"
389
+ class="mj-mtg-filter-btn"
390
+ [class.mj-mtg-filter-btn--active]="ActiveFilter === 'past'"
391
+ (click)="SetFilter('past')">
392
+ Past
393
+ </button>
394
+ </div>
395
+
396
+ <button
397
+ type="button"
398
+ class="mj-btn mj-btn--primary"
399
+ (click)="OnSchedule()">
400
+ <i class="fa-solid fa-plus"></i> Schedule Meeting
401
+ </button>
402
+ </div>
403
+
404
+ <!-- State Views -->
405
+ @if (Loading) {
406
+ <div class="mj-mtg-status">
407
+ <i class="fa-solid fa-spinner fa-spin"></i>
408
+ <span>Loading meetings…</span>
409
+ </div>
410
+ } @else if (ErrorMessage) {
411
+ <div class="mj-mtg-status mj-mtg-status--error">
412
+ <i class="fa-solid fa-triangle-exclamation"></i>
413
+ <span>{{ ErrorMessage }}</span>
414
+ <button type="button" class="mj-btn mj-btn--secondary" (click)="LoadMeetings()">Retry</button>
415
+ </div>
416
+ } @else if (FilteredMeetings.length === 0) {
417
+ <div class="mj-mtg-empty">
418
+ <div class="mj-mtg-empty__icon"><i class="fa-solid fa-calendar-days"></i></div>
419
+ <h3 class="mj-mtg-empty__title">No meetings found</h3>
420
+ <p class="mj-mtg-empty__subtitle">
421
+ {{ SearchQuery ? 'Try adjusting your search query or filter.' : 'You have no meetings scheduled.' }}
422
+ </p>
423
+ <button type="button" class="mj-btn mj-btn--primary" (click)="OnSchedule()">
424
+ <i class="fa-solid fa-plus"></i> Schedule your first meeting
425
+ </button>
426
+ </div>
427
+ } @else {
428
+ <!-- Meetings Grid -->
429
+ <div class="mj-mtg-grid">
430
+ @for (m of FilteredMeetings; track m.ID) {
431
+ <div class="mj-mtg-card" [class.mj-mtg-card--live]="m.Status === 'Live'">
432
+ <div class="mj-mtg-card__header">
433
+ <span class="mj-mtg-pill" [class]="'mj-mtg-pill--' + m.Status.toLowerCase()">
434
+ @if (m.Status === 'Live') {
435
+ <span class="mj-mtg-dot-live"></span>
436
+ }
437
+ {{ m.Status }}
438
+ </span>
439
+ @if (m.RecordingPolicy !== 'Off') {
440
+ <span class="mj-mtg-badge-rec" title="Recording {{ m.RecordingPolicy }}">
441
+ <i class="fa-solid fa-record-vinyl"></i> {{ m.RecordingPolicy }}
442
+ </span>
443
+ }
444
+ </div>
445
+
446
+ <h3 class="mj-mtg-card__title">{{ m.Title }}</h3>
447
+
448
+ @if (m.Description) {
449
+ <p class="mj-mtg-card__desc">{{ m.Description }}</p>
450
+ }
451
+
452
+ <div class="mj-mtg-card__meta">
453
+ <div class="mj-mtg-card__meta-item">
454
+ <i class="fa-solid fa-user"></i>
455
+ <span>Host: {{ m.HostUserName || 'Host' }}</span>
456
+ </div>
457
+ @if (m.ScheduledStartAt) {
458
+ <div class="mj-mtg-card__meta-item">
459
+ <i class="fa-solid fa-clock"></i>
460
+ <span>{{ FormatTime(m.ScheduledStartAt) }}</span>
461
+ </div>
462
+ }
463
+ @if (m.AllowPhoneDialIn && m.DialInPhoneNumber) {
464
+ <div class="mj-mtg-card__meta-item mj-mtg-card__dialin">
465
+ <i class="fa-solid fa-phone"></i>
466
+ <span>Dial-In: {{ m.DialInPhoneNumber }} (PIN: {{ m.DialInCode }})</span>
467
+ </div>
468
+ }
469
+ @if (m.Participants && m.Participants.length > 0) {
470
+ <div class="mj-mtg-card__meta-item">
471
+ <i class="fa-solid fa-users"></i>
472
+ <span>{{ m.Participants.length }} participant{{ m.Participants.length > 1 ? 's' : '' }}</span>
473
+ </div>
474
+ }
475
+ </div>
476
+
477
+ <!-- Card Actions — Confirm/Join button LEFT -->
478
+ <div class="mj-mtg-card__actions">
479
+ @if (m.Status === 'Live') {
480
+ <button
481
+ type="button"
482
+ class="mj-btn mj-btn--primary mj-btn--success"
483
+ (click)="OnJoin(m)">
484
+ <i class="fa-solid fa-video"></i> Join Call
485
+ </button>
486
+ } @else if (m.Status === 'Scheduled') {
487
+ <button
488
+ type="button"
489
+ class="mj-btn mj-btn--primary"
490
+ (click)="OnJoin(m)">
491
+ <i class="fa-solid fa-arrow-right-to-bracket"></i> Enter Lobby
492
+ </button>
493
+ <button
494
+ type="button"
495
+ class="mj-btn mj-btn--secondary"
496
+ title="Edit Meeting"
497
+ (click)="OnEdit(m)">
498
+ <i class="fa-solid fa-pen"></i> Edit
499
+ </button>
500
+ }
501
+
502
+ @if (m.Status === 'Live' || m.Status === 'Scheduled') {
503
+ <button
504
+ type="button"
505
+ class="mj-btn mj-btn--danger-text"
506
+ title="Cancel Meeting"
507
+ (click)="OnCancelMeeting(m)">
508
+ <i class="fa-solid fa-ban"></i> Cancel
509
+ </button>
510
+ }
511
+ </div>
512
+ </div>
513
+ }
514
+ </div>
515
+ }
516
+ </div>
517
+ `, styles: ["\n :host {\n display: block;\n padding: var(--mj-space-6, 24px) var(--mj-space-4, 16px);\n max-width: 72rem;\n margin: 0 auto;\n }\n .mj-mtg-list-view__toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--mj-space-3, 12px);\n margin-bottom: var(--mj-space-6, 24px);\n }\n .mj-mtg-list-view__search-wrap {\n position: relative;\n flex: 1;\n min-width: 220px;\n }\n .mj-mtg-list-view__search-icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-secondary, #94a3b8);\n font-size: 0.875rem;\n }\n .mj-mtg-list-view__search-input {\n width: 100%;\n padding: 9px 12px 9px 34px;\n border: 1px solid var(--mj-border-default, #cbd5e1);\n border-radius: 8px;\n font-size: 0.875rem;\n box-sizing: border-box;\n }\n .mj-mtg-list-view__filters {\n display: flex;\n gap: 4px;\n background: var(--mj-bg-surface-card, #f1f5f9);\n padding: 4px;\n border-radius: 8px;\n }\n .mj-mtg-filter-btn {\n border: none;\n background: none;\n padding: 6px 12px;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n border-radius: 6px;\n color: var(--mj-text-secondary, #64748b);\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n .mj-mtg-filter-btn--active {\n background: var(--mj-bg-surface, #ffffff);\n color: var(--mj-text-primary, #0f172a);\n font-weight: 600;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n }\n .mj-mtg-dot-live {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--mj-status-success, #16a34a);\n display: inline-block;\n box-shadow: 0 0 0 2px var(--mj-status-success-subtle, rgba(22, 163, 74, 0.2));\n animation: pulse 2s infinite;\n }\n @keyframes pulse {\n 0% { transform: scale(0.95); opacity: 0.9; }\n 50% { transform: scale(1.15); opacity: 1; }\n 100% { transform: scale(0.95); opacity: 0.9; }\n }\n .mj-mtg-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: var(--mj-space-4, 16px);\n }\n .mj-mtg-card {\n background: var(--mj-bg-surface, #ffffff);\n border: 1px solid var(--mj-border-default, #e2e8f0);\n border-radius: 12px;\n padding: var(--mj-space-5, 20px);\n display: flex;\n flex-direction: column;\n transition: border-color 0.2s, box-shadow 0.2s;\n }\n .mj-mtg-card:hover {\n border-color: var(--mj-brand-primary, #0076b6);\n box-shadow: var(--mj-shadow-md, 0 4px 12px rgba(0, 0, 0, 0.05));\n }\n .mj-mtg-card--live {\n border-color: var(--mj-status-success, #22c55e);\n background: var(--mj-status-success-subtle, #f0fdf4);\n }\n .mj-mtg-card__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--mj-space-2, 8px);\n }\n .mj-mtg-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 8px;\n border-radius: 999px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n }\n .mj-mtg-pill--live {\n background: var(--mj-status-success-subtle, #dcfce7);\n color: var(--mj-status-success, #15803d);\n }\n .mj-mtg-pill--scheduled {\n background: var(--mj-status-info-subtle, #e0f2fe);\n color: var(--mj-status-info, #0369a1);\n }\n .mj-mtg-pill--ended {\n background: var(--mj-bg-surface-card, #f1f5f9);\n color: var(--mj-text-secondary, #64748b);\n }\n .mj-mtg-pill--cancelled {\n background: var(--mj-status-error-subtle, #fee2e2);\n color: var(--mj-status-error, #b91c1c);\n }\n .mj-mtg-badge-rec {\n font-size: 0.6875rem;\n color: var(--mj-status-error, #ef4444);\n display: flex;\n align-items: center;\n gap: 4px;\n font-weight: 500;\n }\n .mj-mtg-card__title {\n margin: 0 0 var(--mj-space-2, 8px) 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary, #0f172a);\n }\n .mj-mtg-card__desc {\n margin: 0 0 var(--mj-space-4, 16px) 0;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary, #64748b);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n .mj-mtg-card__meta {\n margin-top: auto;\n display: flex;\n flex-direction: column;\n gap: 6px;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary, #64748b);\n padding-top: var(--mj-space-3, 12px);\n border-top: 1px solid var(--mj-border-default, #f1f5f9);\n }\n .mj-mtg-card__meta-item {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .mj-mtg-card__dialin {\n color: var(--mj-brand-primary, #0076b6);\n }\n .mj-mtg-card__actions {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: var(--mj-space-4, 16px);\n }\n .mj-btn {\n padding: 8px 14px;\n border-radius: 6px;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: none;\n }\n .mj-btn--primary {\n background: var(--mj-brand-primary, #0076b6);\n color: var(--mj-text-inverse, #ffffff);\n }\n .mj-btn--success {\n background: var(--mj-status-success, #16a34a);\n color: var(--mj-text-inverse, #ffffff);\n }\n .mj-btn--secondary {\n background: var(--mj-bg-surface, #ffffff);\n color: var(--mj-text-primary, #1e293b);\n border: 1px solid var(--mj-border-default, #cbd5e1);\n }\n .mj-btn--danger-text {\n background: none;\n color: var(--mj-status-error, #ef4444);\n padding: 6px 8px;\n }\n .mj-mtg-status {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 48px;\n color: var(--mj-text-secondary, #64748b);\n }\n .mj-mtg-status i {\n font-size: 2rem;\n color: var(--mj-brand-primary, #0076b6);\n }\n .mj-mtg-empty {\n text-align: center;\n padding: 64px 16px;\n max-width: 24rem;\n margin: 0 auto;\n }\n .mj-mtg-empty__icon {\n font-size: 2.5rem;\n color: var(--mj-text-secondary, #94a3b8);\n margin-bottom: 12px;\n }\n .mj-mtg-empty__title {\n font-size: 1.125rem;\n font-weight: 600;\n margin: 0 0 6px 0;\n color: var(--mj-text-primary, #0f172a);\n }\n .mj-mtg-empty__subtitle {\n font-size: 0.875rem;\n color: var(--mj-text-secondary, #64748b);\n margin: 0 0 16px 0;\n }\n "] }]
518
+ }], null, { Provider: [{
519
+ type: Input
520
+ }], JoinMeeting: [{
521
+ type: Output
522
+ }], ScheduleRequested: [{
523
+ type: Output
524
+ }], EditMeetingRequested: [{
525
+ type: Output
526
+ }] }); })();
527
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJMeetingListComponent, { className: "MJMeetingListComponent", filePath: "src/lib/meetings/meeting-list.component.ts", lineNumber: 428 }); })();
528
+ //# sourceMappingURL=meeting-list.component.js.map