@ieeesa-npm/dashboard 0.0.0-stage → 0.0.2

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 (73) hide show
  1. package/README.md +75 -3
  2. package/esm2022/ieeesa-npm-dashboard.mjs +5 -0
  3. package/esm2022/lib/assets/constants.json +158 -0
  4. package/esm2022/lib/assets/dashboard-mock.mjs +221 -0
  5. package/esm2022/lib/assets/dashboard-route-paths.mock.mjs +14 -0
  6. package/esm2022/lib/assets/dashboard-user-permissions.mock.mjs +23 -0
  7. package/esm2022/lib/assets/date-formats.mjs +28 -0
  8. package/esm2022/lib/components/event-group-card/event-group-card.component.mjs +414 -0
  9. package/esm2022/lib/components/meeting-attendance-row/meeting-attendance-row.component.mjs +182 -0
  10. package/esm2022/lib/components/member-level-badge/member-level-badge.component.mjs +79 -0
  11. package/esm2022/lib/components/upcoming-meetings-events/upcoming-meetings-events.component.mjs +261 -0
  12. package/esm2022/lib/components/welcome-header/dashboard-welcome-header.component.mjs +151 -0
  13. package/esm2022/lib/components/your-groups/your-groups.component.mjs +243 -0
  14. package/esm2022/lib/dashboard.component.mjs +417 -0
  15. package/esm2022/lib/dashboard.module.mjs +16 -0
  16. package/esm2022/lib/dashboard.routes.mjs +7 -0
  17. package/esm2022/lib/models/attendance-action-permissions.model.mjs +2 -0
  18. package/esm2022/lib/models/attendance-state.model.mjs +7 -0
  19. package/esm2022/lib/models/dashboard-list-response.model.mjs +2 -0
  20. package/esm2022/lib/models/dashboard-route-config.model.mjs +2 -0
  21. package/esm2022/lib/models/dashboard-section-state.model.mjs +9 -0
  22. package/esm2022/lib/models/dashboard-user-info.model.mjs +2 -0
  23. package/esm2022/lib/models/event-meeting-list-item.model.mjs +2 -0
  24. package/esm2022/lib/models/event-meeting-list-payload.model.mjs +8 -0
  25. package/esm2022/lib/models/group-row.model.mjs +2 -0
  26. package/esm2022/lib/models/meeting-row.model.mjs +2 -0
  27. package/esm2022/lib/models/my-groups-view.model.mjs +2 -0
  28. package/esm2022/lib/models/page-change.model.mjs +2 -0
  29. package/esm2022/lib/models/upcoming-event.model.mjs +13 -0
  30. package/esm2022/lib/services/attendance-reducers.mjs +54 -0
  31. package/esm2022/lib/services/dashboard.service.mjs +402 -0
  32. package/esm2022/lib/services/user-permissions.service.mjs +50 -0
  33. package/esm2022/lib/utils/attendance-action.util.mjs +53 -0
  34. package/esm2022/lib/utils/date-format.util.mjs +110 -0
  35. package/esm2022/lib/utils/event-meeting-mapper.util.mjs +96 -0
  36. package/esm2022/public-api.mjs +36 -0
  37. package/fesm2022/ieeesa-npm-dashboard.mjs +2981 -0
  38. package/fesm2022/ieeesa-npm-dashboard.mjs.map +1 -0
  39. package/index.d.ts +5 -0
  40. package/lib/assets/dashboard-mock.d.ts +31 -0
  41. package/lib/assets/dashboard-route-paths.mock.d.ts +2 -0
  42. package/lib/assets/dashboard-user-permissions.mock.d.ts +2 -0
  43. package/lib/assets/date-formats.d.ts +27 -0
  44. package/lib/components/event-group-card/event-group-card.component.d.ts +268 -0
  45. package/lib/components/meeting-attendance-row/meeting-attendance-row.component.d.ts +115 -0
  46. package/lib/components/member-level-badge/member-level-badge.component.d.ts +177 -0
  47. package/lib/components/upcoming-meetings-events/upcoming-meetings-events.component.d.ts +175 -0
  48. package/lib/components/welcome-header/dashboard-welcome-header.component.d.ts +98 -0
  49. package/lib/components/your-groups/your-groups.component.d.ts +159 -0
  50. package/lib/dashboard.component.d.ts +414 -0
  51. package/lib/dashboard.module.d.ts +7 -0
  52. package/lib/dashboard.routes.d.ts +2 -0
  53. package/lib/models/attendance-action-permissions.model.d.ts +4 -0
  54. package/lib/models/attendance-state.model.d.ts +4 -0
  55. package/lib/models/dashboard-list-response.model.d.ts +5 -0
  56. package/lib/models/dashboard-route-config.model.d.ts +7 -0
  57. package/lib/models/dashboard-section-state.model.d.ts +6 -0
  58. package/lib/models/dashboard-user-info.model.d.ts +5 -0
  59. package/lib/models/event-meeting-list-item.model.d.ts +107 -0
  60. package/lib/models/event-meeting-list-payload.model.d.ts +40 -0
  61. package/lib/models/group-row.model.d.ts +33 -0
  62. package/lib/models/meeting-row.model.d.ts +28 -0
  63. package/lib/models/my-groups-view.model.d.ts +56 -0
  64. package/lib/models/page-change.model.d.ts +4 -0
  65. package/lib/models/upcoming-event.model.d.ts +51 -0
  66. package/lib/services/attendance-reducers.d.ts +43 -0
  67. package/lib/services/dashboard.service.d.ts +202 -0
  68. package/lib/services/user-permissions.service.d.ts +31 -0
  69. package/lib/utils/attendance-action.util.d.ts +38 -0
  70. package/lib/utils/date-format.util.d.ts +60 -0
  71. package/lib/utils/event-meeting-mapper.util.d.ts +50 -0
  72. package/package.json +30 -3
  73. package/public-api.d.ts +26 -0
@@ -0,0 +1,31 @@
1
+ import { GroupRow } from '../models/group-row.model';
2
+ import { MeetingRow } from '../models/meeting-row.model';
3
+ import { UpcomingEvent } from '../models/upcoming-event.model';
4
+ /**
5
+ * Mock upcoming-events + groups fixtures for the dashboard library.
6
+ *
7
+ * These exercise the key presentation edge cases:
8
+ * - empty/undefined `groupOrCommittee` and `roomOrLocation` (empty-field placeholder)
9
+ * - a mix of `CURRENTLY_ATTENDING` / `NOT_ATTENDING` attendance states
10
+ * - events with many meetings so per-card pagination is exercised
11
+ *
12
+ * TODO: Replace mock with real API call when BE is ready
13
+ */
14
+ export declare const DashboardUpcomingEventsMock: UpcomingEvent[];
15
+ /**
16
+ * Mock a single meeting row with an empty `meetingId` to exercise the
17
+ * non-actionable (empty/undefined id) path in the meeting row component.
18
+ *
19
+ * TODO: Replace mock with real API call when BE is ready
20
+ */
21
+ export declare const DashboardNonActionableMeetingMock: MeetingRow;
22
+ /**
23
+ * Mock groups fixtures for the dashboard "Your Groups" section.
24
+ *
25
+ * Includes rows with missing optional fields (`type`, `officerRole`,
26
+ * `affiliation`) and a spread of member levels so the member-level badge
27
+ * colour map and empty-field placeholders are exercised.
28
+ *
29
+ * TODO: Replace mock with real API call when BE is ready
30
+ */
31
+ export declare const DashboardGroupsMock: GroupRow[];
@@ -0,0 +1,2 @@
1
+ import { DashboardRouteConfig } from '../models/dashboard-route-config.model';
2
+ export declare const DashboardRoutePathsMock: DashboardRouteConfig;
@@ -0,0 +1,2 @@
1
+ import { UserPermission } from '@ieeesa-npm/models';
2
+ export declare const DashboardUserPermissionsMock: UserPermission[];
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Luxon format tokens used across the dashboard library for rendering
3
+ * event/meeting dates, times, and timezones.
4
+ *
5
+ * These tokens follow the luxon `DateTime.toFormat()` convention
6
+ * (NOT moment). New code in this library must use luxon exclusively.
7
+ *
8
+ * @see https://moment.github.io/luxon/#/formatting?id=table-of-tokens
9
+ */
10
+ export declare const DateFormats: {
11
+ /** ISO date used for request payloads, e.g. 2025-03-14. */
12
+ requestPayloadFormat: string;
13
+ /** ISO date-time used for request payloads, e.g. 2025-03-14T09:30:00. */
14
+ requestPayloadDateTimeFormat: string;
15
+ /** Human-readable date for display, e.g. 14 Mar 2025. */
16
+ displayFormat: string;
17
+ /** Human-readable long date for display, e.g. 14 March 2025. */
18
+ displayLongFormat: string;
19
+ /** 24-hour time for display, e.g. 09:30. */
20
+ timeFormat: string;
21
+ /** 12-hour time with meridiem for display, e.g. 9:30 AM. */
22
+ timeMeridiemFormat: string;
23
+ /** Short timezone abbreviation for display, e.g. EST. */
24
+ timezoneFormat: string;
25
+ /** Long timezone name for display, e.g. Eastern Standard Time. */
26
+ timezoneLongFormat: string;
27
+ };
@@ -0,0 +1,268 @@
1
+ import { EventEmitter } from '@angular/core';
2
+ import { PageEvent } from '@angular/material/paginator';
3
+ import { AttendanceActionPermissions } from '../../models/attendance-action-permissions.model';
4
+ import { AttendanceState } from '../../models/attendance-state.model';
5
+ import { MeetingRow } from '../../models/meeting-row.model';
6
+ import { PageChange } from '../../models/page-change.model';
7
+ import { UpcomingEvent, UpcomingItemKind } from '../../models/upcoming-event.model';
8
+ import * as i0 from "@angular/core";
9
+ /**
10
+ * Event_Group_Card renders a single upcoming event as a card: the status badge,
11
+ * title, day indicator, meeting-count summary sub-line, start/end date, and
12
+ * timezone (all luxon-formatted). It exposes a "View Event" action, a
13
+ * show/hide toggle for the meeting list labeled with the open-for-attendance
14
+ * count, the per-event meeting rows (one {@link MeetingAttendanceRowComponent}
15
+ * per meeting on the current page), and a per-card paginator.
16
+ *
17
+ * The component is purely presentational — it emits navigation, attendance, and
18
+ * pagination intents via `@Output()` and never performs navigation or HTTP
19
+ * itself. Meeting-row outputs (`openMeeting`/`logAttendance`/`leaveMeeting`) are
20
+ * bubbled upward unchanged so the container can delegate to the service.
21
+ * @export
22
+ * @class EventGroupCardComponent
23
+ */
24
+ export declare class EventGroupCardComponent {
25
+ /** User-facing strings sourced from `constants.json`. */
26
+ constants: any;
27
+ /** Enum reference for EVENT vs STANDALONE_MEETING comparisons in the template. */
28
+ readonly itemKinds: typeof UpcomingItemKind;
29
+ /**
30
+ * The event status slugified into a BEM modifier suffix (lowercase, spaces to
31
+ * hyphens), e.g. "In Progress" -> "in-progress", used to colour the status
32
+ * pill per status.
33
+ * @return {string} The status modifier suffix.
34
+ * @memberof EventGroupCardComponent
35
+ */
36
+ get statusModifier(): string;
37
+ /** The upcoming event rendered by this card. */
38
+ event: UpcomingEvent;
39
+ /** Host permissions gating the per-row log-attendance / leave-meeting buttons. */
40
+ permissions: AttendanceActionPermissions;
41
+ /** Map of meeting id to current attendance state, passed down to each row. */
42
+ attendanceStates: Record<string, AttendanceState>;
43
+ /** Set of meeting ids with an attendance action awaiting resolution. */
44
+ inFlightMeetingIds: ReadonlySet<string>;
45
+ /** Whether the host has determined the viewport is at/below the mobile breakpoint. */
46
+ isMobileView: boolean;
47
+ /** Emits the event id when the "View Event" button is activated (Req 6.4). */
48
+ viewEvent: EventEmitter<string>;
49
+ /** Bubbles the meeting id when a row's meeting-name link is activated (Req 6.7, 7.4). */
50
+ openMeeting: EventEmitter<string>;
51
+ /** Bubbles the meeting id when a row requests logging attendance (Req 6.7, 7.7). */
52
+ logAttendance: EventEmitter<string>;
53
+ /** Bubbles the meeting id when a row requests leaving the meeting (Req 6.7, 7.8). */
54
+ leaveMeeting: EventEmitter<string>;
55
+ /** Emits the requested page when the per-card paginator changes (Req 6.9, 3.3). */
56
+ pageChange: EventEmitter<PageChange>;
57
+ /**
58
+ * Emits the one-based page to load when the meeting list is opened (or paged)
59
+ * so the container can lazily fetch the event's child meetings from the
60
+ * backend. Standalone-meeting cards never emit this.
61
+ */
62
+ loadMeetings: EventEmitter<number>;
63
+ /** The default page size for the per-card meeting paginator. */
64
+ readonly defaultPageSize = 5;
65
+ /** The current zero-based page index of the meeting list. */
66
+ pageIndex: number;
67
+ /** The current page size of the meeting list. */
68
+ pageSize: number;
69
+ /** Whether the meeting list is currently shown (toggled open). */
70
+ isMeetingListOpen: boolean;
71
+ /**
72
+ * Whether this card renders a STANDALONE_MEETING (leaner single-meeting card
73
+ * with no child-meeting list) rather than an expandable EVENT block.
74
+ * @return {boolean} True for standalone-meeting cards.
75
+ * @memberof EventGroupCardComponent
76
+ */
77
+ get isStandalone(): boolean;
78
+ /**
79
+ * The full list of meetings for the event, defaulting to an empty list when
80
+ * the event has none.
81
+ * @return {MeetingRow[]} The event's meetings.
82
+ * @memberof EventGroupCardComponent
83
+ */
84
+ get meetings(): MeetingRow[];
85
+ /**
86
+ * The total number of meetings for the event (paginator length). Uses the
87
+ * backend `meetingCount` (the full total) rather than the length of the
88
+ * currently loaded page, so the paginator can advance through every page.
89
+ * @return {number} The total meeting count.
90
+ * @memberof EventGroupCardComponent
91
+ */
92
+ get totalMeetings(): number;
93
+ /**
94
+ * The meetings to render for the current page. The server returns exactly one
95
+ * page of meetings into `event.meetings`, so the card renders them as-is
96
+ * without local slicing (pagination is server-side).
97
+ * @return {MeetingRow[]} The meetings on the current page.
98
+ * @memberof EventGroupCardComponent
99
+ */
100
+ get pagedMeetings(): MeetingRow[];
101
+ /**
102
+ * The one-based index of the first meeting shown on the current page, or 0
103
+ * when there are no meetings.
104
+ * @return {number} The start index for the range template.
105
+ * @memberof EventGroupCardComponent
106
+ */
107
+ get rangeStart(): number;
108
+ /**
109
+ * The one-based index of the last meeting shown on the current page, clamped
110
+ * to the total meeting count.
111
+ * @return {number} The end index for the range template.
112
+ * @memberof EventGroupCardComponent
113
+ */
114
+ get rangeEnd(): number;
115
+ /**
116
+ * The paginator range label (e.g. "Showing 1-5 of 12") built from the
117
+ * `constants.json` range template with the current start/end/total values.
118
+ * @return {string} The formatted range label.
119
+ * @memberof EventGroupCardComponent
120
+ */
121
+ get rangeLabel(): string;
122
+ /**
123
+ * The meeting-count summary sub-line (e.g. "12 meetings") built from the
124
+ * `constants.json` total template with the event's meeting count.
125
+ * @return {string} The formatted meeting-count summary.
126
+ * @memberof EventGroupCardComponent
127
+ */
128
+ get meetingCountSummary(): string;
129
+ /**
130
+ * The header sub-line: the group · location line for a STANDALONE meeting, or
131
+ * the "{n} meetings scheduled across the event" summary for an EVENT when its
132
+ * meeting count is known (hidden until the count is loaded so it never shows
133
+ * "0 meetings").
134
+ * @return {string} The sub-line text, or an empty string to hide it.
135
+ * @memberof EventGroupCardComponent
136
+ */
137
+ get subtitleText(): string;
138
+ /**
139
+ * The meeting-list show/hide toggle label. When the list is hidden the label
140
+ * reads "Show Meetings ({count} open for attendance)" built from the
141
+ * `constants.json` templates and the event's open-for-attendance count; when
142
+ * the list is shown the label reads the configured hide label (Req 6.5).
143
+ * @return {string} The toggle button label.
144
+ * @memberof EventGroupCardComponent
145
+ */
146
+ get meetingListToggleLabel(): string;
147
+ /**
148
+ * The "{count} Meetings open for attendance" summary shown in the event's
149
+ * meetings bar, built from the `constants.json` template and the event's
150
+ * open-for-attendance count (Req 6.5).
151
+ * @return {string} The formatted open-for-attendance summary.
152
+ * @memberof EventGroupCardComponent
153
+ */
154
+ get openForAttendanceSummary(): string;
155
+ /**
156
+ * The {@link MeetingRow} view model for a STANDALONE_MEETING card, projected
157
+ * from the event entry so the shared {@link MeetingAttendanceRowComponent}
158
+ * renders its time/timezone block and attendance action.
159
+ * @return {MeetingRow} The standalone meeting row.
160
+ * @memberof EventGroupCardComponent
161
+ */
162
+ get standaloneMeeting(): MeetingRow;
163
+ /**
164
+ * The formatted "start – end time (timezone)" string for a STANDALONE meeting,
165
+ * mirroring the inner meeting row's TIME & TIMEZONE value.
166
+ * @return {string} The formatted time + timezone.
167
+ * @memberof EventGroupCardComponent
168
+ */
169
+ get standaloneTime(): string;
170
+ /**
171
+ * Whether the STANDALONE meeting is currently being attended (drives the pill
172
+ * and the leave action).
173
+ * @return {boolean} True when the standalone meeting is currently attending.
174
+ * @memberof EventGroupCardComponent
175
+ */
176
+ get isStandaloneAttending(): boolean;
177
+ /**
178
+ * Whether the STANDALONE meeting's Log Attendance button is shown (not
179
+ * attending and the host grants the permission).
180
+ * @return {boolean} True when the log-attendance button is visible.
181
+ * @memberof EventGroupCardComponent
182
+ */
183
+ get showStandaloneLog(): boolean;
184
+ /**
185
+ * Whether the STANDALONE meeting's Leave Meeting button is shown (attending
186
+ * and the host grants the permission).
187
+ * @return {boolean} True when the leave-meeting button is visible.
188
+ * @memberof EventGroupCardComponent
189
+ */
190
+ get showStandaloneLeave(): boolean;
191
+ /** The luxon-formatted start date of the event (ISO or epoch ms) (Req 6.2). */
192
+ get formattedStartDate(): string;
193
+ /** The luxon-formatted end date of the event (ISO or epoch ms) (Req 6.2). */
194
+ get formattedEndDate(): string;
195
+ /**
196
+ * `trackBy` for the meeting-row `*ngFor`, keyed by the stable meeting id so
197
+ * Angular reuses row components across pagination/state changes (Req 6.7, 14.4).
198
+ * @param {number} _index - The iteration index (unused).
199
+ * @param {MeetingRow} meeting - The meeting for this row.
200
+ * @return {string} The stable track key (meeting id).
201
+ * @memberof EventGroupCardComponent
202
+ */
203
+ trackByMeetingId(_index: number, meeting: MeetingRow): string;
204
+ /**
205
+ * Resolves the attendance state for a meeting from the `attendanceStates` map,
206
+ * defaulting to `NOT_ATTENDING` when the map has no entry for it.
207
+ * @param {MeetingRow} meeting - The meeting to resolve state for.
208
+ * @return {AttendanceState} The attendance state passed to the row.
209
+ * @memberof EventGroupCardComponent
210
+ */
211
+ resolveAttendanceState(meeting: MeetingRow): AttendanceState;
212
+ /**
213
+ * Resolves whether a meeting has an attendance action in flight from the
214
+ * `inFlightMeetingIds` set.
215
+ * @param {MeetingRow} meeting - The meeting to check.
216
+ * @return {boolean} True when the meeting's action is awaiting resolution.
217
+ * @memberof EventGroupCardComponent
218
+ */
219
+ resolveIsInFlight(meeting: MeetingRow): boolean;
220
+ /**
221
+ * Toggles the meeting-list visibility, lazily requesting the first page of the
222
+ * event's child meetings from the container the first time it is opened (Req 6.6).
223
+ * @memberof EventGroupCardComponent
224
+ */
225
+ onToggleMeetingList(): void;
226
+ /**
227
+ * Handles the "View Event" button, emitting the event id to the host (Req 6.4).
228
+ * @memberof EventGroupCardComponent
229
+ */
230
+ onViewEvent(): void;
231
+ /**
232
+ * Bubbles a row's meeting-name link activation upward (Req 6.7, 7.4).
233
+ * @param {string} meetingId - The id emitted by the row.
234
+ * @memberof EventGroupCardComponent
235
+ */
236
+ onOpenMeeting(meetingId: string): void;
237
+ /**
238
+ * Bubbles a row's log-attendance request upward (Req 6.7, 7.7).
239
+ * @param {string} meetingId - The id emitted by the row.
240
+ * @memberof EventGroupCardComponent
241
+ */
242
+ onLogAttendance(meetingId: string): void;
243
+ /**
244
+ * Bubbles a row's leave-meeting request upward (Req 6.7, 7.8).
245
+ * @param {string} meetingId - The id emitted by the row.
246
+ * @memberof EventGroupCardComponent
247
+ */
248
+ onLeaveMeeting(meetingId: string): void;
249
+ /**
250
+ * Handles the per-card paginator change, updating the local page state and
251
+ * emitting the requested page as a {@link PageChange} (Req 6.9, 3.3).
252
+ * @param {PageEvent} event - The Material paginator page event.
253
+ * @memberof EventGroupCardComponent
254
+ */
255
+ onPageChange(event: PageEvent): void;
256
+ /**
257
+ * Formats a date for display, preferring the epoch-milliseconds value (from
258
+ * the real API) formatted in the event's timezone and falling back to a legacy
259
+ * ISO string. Returns an empty string when neither is present.
260
+ * @param {number | undefined} epochMs - The epoch-milliseconds value.
261
+ * @param {string | undefined} isoValue - The legacy ISO fallback.
262
+ * @return {string} The formatted date or an empty string.
263
+ * @memberof EventGroupCardComponent
264
+ */
265
+ private formatDate;
266
+ static ɵfac: i0.ɵɵFactoryDeclaration<EventGroupCardComponent, never>;
267
+ static ɵcmp: i0.ɵɵComponentDeclaration<EventGroupCardComponent, "ieeesa-event-group-card", never, { "event": { "alias": "event"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "attendanceStates": { "alias": "attendanceStates"; "required": false; }; "inFlightMeetingIds": { "alias": "inFlightMeetingIds"; "required": false; }; "isMobileView": { "alias": "isMobileView"; "required": false; }; }, { "viewEvent": "viewEvent"; "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; "pageChange": "pageChange"; "loadMeetings": "loadMeetings"; }, never, never, true, never>;
268
+ }
@@ -0,0 +1,115 @@
1
+ import { EventEmitter } from '@angular/core';
2
+ import { AttendanceActionPermissions } from '../../models/attendance-action-permissions.model';
3
+ import { AttendanceState } from '../../models/attendance-state.model';
4
+ import { MeetingRow } from '../../models/meeting-row.model';
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * Meeting_Attendance_Row renders a single meeting within an event-group card:
8
+ * the meeting-name link, group/committee, room/location, date, and
9
+ * time+timezone (all luxon-formatted), together with the attendance action
10
+ * button that drives the per-meeting attendance state machine.
11
+ *
12
+ * The component is purely presentational — it emits navigation and attendance
13
+ * intents via `@Output()` and never performs navigation or HTTP itself. The
14
+ * action button delegates to the pure `resolveAttendanceAction` handler so the
15
+ * emit/guard logic is shared with the property-tested core (Property 1), and the
16
+ * displayed state only advances when the host updates `attendanceState`.
17
+ * @export
18
+ * @class MeetingAttendanceRowComponent
19
+ */
20
+ export declare class MeetingAttendanceRowComponent {
21
+ constants: any;
22
+ /** The meeting rendered by this row. */
23
+ meeting: MeetingRow;
24
+ /** The current attendance state controlling label/indicator and action. */
25
+ attendanceState: AttendanceState;
26
+ /** Whether an attendance action for this meeting is awaiting resolution. */
27
+ isInFlight: boolean;
28
+ /** Host permissions gating the log-attendance / leave-meeting buttons. */
29
+ permissions: AttendanceActionPermissions;
30
+ /**
31
+ * Renders the leaner "standalone meeting" variant used by standalone-meeting
32
+ * cards (the group/location and status live on the parent card, so the row
33
+ * only shows the TIME & TIMEZONE block and the attendance + View actions).
34
+ */
35
+ compact: boolean;
36
+ /** Emits the meeting id when the meeting-name link is activated (Req 7.4). */
37
+ openMeeting: EventEmitter<string>;
38
+ /** Emits the meeting id to request logging attendance (Req 7.7). */
39
+ logAttendance: EventEmitter<string>;
40
+ /** Emits the meeting id to request leaving the meeting (Req 7.8). */
41
+ leaveMeeting: EventEmitter<string>;
42
+ /** Expose the enum to the template for state comparisons. */
43
+ readonly AttendanceState: typeof AttendanceState;
44
+ /**
45
+ * Whether this row is actionable — a non-empty `meetingId` is required for the
46
+ * meeting-name link and action button to emit anything (Req 7.10).
47
+ * @return {boolean} True when the row has a usable meeting id.
48
+ * @memberof MeetingAttendanceRowComponent
49
+ */
50
+ get isActionable(): boolean;
51
+ /**
52
+ * Whether the row is in the currently-attending state, which shows the
53
+ * currently-attending indicator and the leave-meeting action (Req 7.5).
54
+ * @return {boolean} True when the attendance state is `CURRENTLY_ATTENDING`.
55
+ * @memberof MeetingAttendanceRowComponent
56
+ */
57
+ get isCurrentlyAttending(): boolean;
58
+ /**
59
+ * Whether the log-attendance button should be shown: only when the row is in
60
+ * the log state (not currently attending) and the host grants
61
+ * `canLogAttendance` (Req 7.6, 12.1).
62
+ * @return {boolean} True when the log-attendance button is visible.
63
+ * @memberof MeetingAttendanceRowComponent
64
+ */
65
+ get showLogAttendanceButton(): boolean;
66
+ /**
67
+ * Whether the leave-meeting button should be shown: only when the row is in
68
+ * the currently-attending state and the host grants `canLeaveMeeting`
69
+ * (Req 7.5, 12.2).
70
+ * @return {boolean} True when the leave-meeting button is visible.
71
+ * @memberof MeetingAttendanceRowComponent
72
+ */
73
+ get showLeaveMeetingButton(): boolean;
74
+ /**
75
+ * Resolves a group-or-committee / room-or-location field value, substituting
76
+ * the empty-field placeholder from `constants.json` when the value is empty or
77
+ * undefined (Req 7.2).
78
+ * @param {string | undefined} value - The raw field value from the meeting.
79
+ * @return {string} The value to display, or the empty-field placeholder.
80
+ * @memberof MeetingAttendanceRowComponent
81
+ */
82
+ resolveFieldValue(value: string | undefined): string;
83
+ /**
84
+ * Formats the meeting date for display using the shared luxon display format
85
+ * (Req 7.3). Falls back to the raw value when it cannot be parsed.
86
+ * @return {string} The formatted meeting date.
87
+ * @memberof MeetingAttendanceRowComponent
88
+ */
89
+ get formattedDate(): string;
90
+ /**
91
+ * Formats the meeting time + timezone for display using luxon (Req 7.3).
92
+ * The timezone abbreviation from the meeting model is appended to the parsed
93
+ * time. Falls back to the raw value when it cannot be parsed.
94
+ * @return {string} The formatted meeting time with timezone.
95
+ * @memberof MeetingAttendanceRowComponent
96
+ */
97
+ get formattedTime(): string;
98
+ /**
99
+ * Handles activation of the attendance action button. Delegates to the pure
100
+ * `resolveAttendanceAction` handler and emits exactly one event based on the
101
+ * resolved action: `logAttendance` for `LOG_ATTENDANCE`, `leaveMeeting` for
102
+ * `LEAVE_MEETING`, and nothing for `NONE` (empty id or in-flight)
103
+ * (Req 7.7, 7.8, 7.9, 7.10, 13.6).
104
+ * @memberof MeetingAttendanceRowComponent
105
+ */
106
+ onAttendanceAction(): void;
107
+ /**
108
+ * Handles activation of the meeting-name link. Emits the meeting id only when
109
+ * the row is actionable (non-empty meeting id) (Req 7.4, 7.10).
110
+ * @memberof MeetingAttendanceRowComponent
111
+ */
112
+ onOpenMeeting(): void;
113
+ static ɵfac: i0.ɵɵFactoryDeclaration<MeetingAttendanceRowComponent, never>;
114
+ static ɵcmp: i0.ɵɵComponentDeclaration<MeetingAttendanceRowComponent, "ieeesa-meeting-attendance-row", never, { "meeting": { "alias": "meeting"; "required": false; }; "attendanceState": { "alias": "attendanceState"; "required": false; }; "isInFlight": { "alias": "isInFlight"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "compact": { "alias": "compact"; "required": false; }; }, { "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; }, never, never, true, never>;
115
+ }
@@ -0,0 +1,177 @@
1
+ import { Legend } from '@ieeesa-npm/presentation';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Member_Level_Badge renders a single member-level value as a colored pill.
5
+ * It reuses the Presentation_Library Legend component for the pill primitive,
6
+ * sourcing the level-to-color mapping from `constants.json` (`memberLevel.colorMap`)
7
+ * with a nullish-coalescing fallback to the configured default color.
8
+ * @export
9
+ * @class MemberLevelBadgeComponent
10
+ */
11
+ export declare class MemberLevelBadgeComponent {
12
+ constants: {
13
+ welcomeHeader: {
14
+ greeting: string;
15
+ fallbackGreeting: string;
16
+ helperText: string;
17
+ jumpToLabel: string;
18
+ shortcuts: {
19
+ meetings: {
20
+ label: string;
21
+ iconUrl: string;
22
+ ariaLabel: string;
23
+ };
24
+ groups: {
25
+ label: string;
26
+ iconUrl: string;
27
+ ariaLabel: string;
28
+ };
29
+ };
30
+ };
31
+ upcomingSection: {
32
+ title: string;
33
+ viewAllLabel: string;
34
+ expandLabel: string;
35
+ collapseLabel: string;
36
+ ariaLabel: {
37
+ viewAll: string;
38
+ toggle: string;
39
+ };
40
+ emptyMessage: string;
41
+ errorMessage: string;
42
+ paginator: {
43
+ rangeTemplate: string;
44
+ };
45
+ };
46
+ eventGroupCard: {
47
+ eventBadge: string;
48
+ standaloneBadge: string;
49
+ viewLabel: string;
50
+ viewEventLabel: string;
51
+ eventDatesLabel: string;
52
+ meetingDateLabel: string;
53
+ timeTimezoneLabel: string;
54
+ meetingsLabel: string;
55
+ openForAttendanceTemplate: string;
56
+ meetingListToggle: {
57
+ showLabel: string;
58
+ showLabelPrefix: string;
59
+ showLabelSuffix: string;
60
+ hideLabel: string;
61
+ };
62
+ ariaLabel: {
63
+ view: string;
64
+ viewEvent: string;
65
+ meetingListToggle: string;
66
+ };
67
+ paginator: {
68
+ rangeTemplate: string;
69
+ totalTemplate: string;
70
+ };
71
+ };
72
+ meetingRow: {
73
+ emptyFieldPlaceholder: string;
74
+ timeTimezoneLabel: string;
75
+ viewLabel: string;
76
+ currentlyAttendingIndicator: string;
77
+ logAttendanceLabel: string;
78
+ leaveMeetingLabel: string;
79
+ ariaLabel: {
80
+ meetingNameLink: string;
81
+ logAttendance: string;
82
+ leaveMeeting: string;
83
+ };
84
+ };
85
+ groupsSection: {
86
+ title: string;
87
+ viewAllLabel: string;
88
+ expandLabel: string;
89
+ collapseLabel: string;
90
+ countSuffix: string;
91
+ emptyValue: string;
92
+ unassignedMemberLevel: string;
93
+ itemsPerPageLabel: string;
94
+ ariaLabel: {
95
+ viewAll: string;
96
+ toggle: string;
97
+ groupLink: string;
98
+ };
99
+ columns: {
100
+ group: string;
101
+ type: string;
102
+ officerRole: string;
103
+ affiliation: string;
104
+ memberLevel: string;
105
+ };
106
+ paginator: {
107
+ rangeTemplate: string;
108
+ totalTemplate: string;
109
+ };
110
+ memberLevelBadge: {
111
+ success: string;
112
+ warning: string;
113
+ };
114
+ emptyMessage: string;
115
+ errorMessage: string;
116
+ };
117
+ memberLevel: {
118
+ colorMap: {
119
+ "Voting Member": string;
120
+ Observer: string;
121
+ "Associate Member": string;
122
+ Member: string;
123
+ default: string;
124
+ };
125
+ };
126
+ attendance: {
127
+ errorMessage: string;
128
+ };
129
+ footer: {
130
+ links: {
131
+ label: string;
132
+ target: string;
133
+ }[];
134
+ copyright: string;
135
+ };
136
+ defaultRouteConfig: {
137
+ eventDetail: string;
138
+ meetingDetail: string;
139
+ groupDetail: string;
140
+ viewAllEvents: string;
141
+ viewAllGroups: string;
142
+ };
143
+ };
144
+ private memberLevelValue;
145
+ set memberLevel(value: string);
146
+ get memberLevel(): string;
147
+ /** The Legend input consumed by the Presentation_Library Legend component. */
148
+ legends: Legend[];
149
+ /**
150
+ * Builds the single-item Legend list for the supplied member level, resolving
151
+ * the pill color from the `constants.json` color map and falling back to the
152
+ * configured default color when the level has no explicit mapping.
153
+ * @param {string} memberLevel - The member-level label to render.
154
+ * @return {Legend[]} A single-element Legend array for the Legend component.
155
+ * @memberof MemberLevelBadgeComponent
156
+ */
157
+ private buildLegends;
158
+ /**
159
+ * Resolves the CSS modifier class for a member level from the `constants.json`
160
+ * color map, using the `??` fallback to the `default` entry when the level is
161
+ * missing from the map.
162
+ * @param {string} memberLevel - The member-level label to resolve a color for.
163
+ * @return {string} The CSS modifier class applied to the pill.
164
+ * @memberof MemberLevelBadgeComponent
165
+ */
166
+ private resolveColorClass;
167
+ /**
168
+ * Converts a shared-styles color token (for example `$ieeesa-color-success`)
169
+ * into a valid BEM-style CSS modifier class defined in this component's SCSS.
170
+ * @param {string} token - The color token from the color map.
171
+ * @return {string} A valid CSS class name.
172
+ * @memberof MemberLevelBadgeComponent
173
+ */
174
+ private toColorClass;
175
+ static ɵfac: i0.ɵɵFactoryDeclaration<MemberLevelBadgeComponent, never>;
176
+ static ɵcmp: i0.ɵɵComponentDeclaration<MemberLevelBadgeComponent, "ieeesa-member-level-badge", never, { "memberLevel": { "alias": "memberLevel"; "required": false; }; }, {}, never, never, true, never>;
177
+ }