@ieeesa-npm/dashboard 0.0.1 → 0.0.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 (38) hide show
  1. package/esm2022/lib/assets/constants.json +23 -6
  2. package/esm2022/lib/assets/dashboard-mock.mjs +5 -1
  3. package/esm2022/lib/assets/dashboard-route-paths.mock.mjs +7 -5
  4. package/esm2022/lib/components/event-group-card/event-group-card.component.mjs +168 -31
  5. package/esm2022/lib/components/meeting-attendance-row/meeting-attendance-row.component.mjs +25 -24
  6. package/esm2022/lib/components/upcoming-meetings-events/upcoming-meetings-events.component.mjs +103 -5
  7. package/esm2022/lib/components/welcome-header/dashboard-welcome-header.component.mjs +3 -3
  8. package/esm2022/lib/components/your-groups/your-groups.component.mjs +264 -118
  9. package/esm2022/lib/dashboard.component.mjs +54 -14
  10. package/esm2022/lib/models/event-meeting-list-item.model.mjs +2 -0
  11. package/esm2022/lib/models/event-meeting-list-payload.model.mjs +8 -0
  12. package/esm2022/lib/models/group-row.model.mjs +1 -1
  13. package/esm2022/lib/models/meeting-row.model.mjs +1 -1
  14. package/esm2022/lib/models/my-groups-view.model.mjs +2 -0
  15. package/esm2022/lib/models/upcoming-event.model.mjs +13 -2
  16. package/esm2022/lib/services/dashboard.service.mjs +229 -35
  17. package/esm2022/lib/utils/date-format.util.mjs +110 -0
  18. package/esm2022/lib/utils/event-meeting-mapper.util.mjs +96 -0
  19. package/esm2022/public-api.mjs +3 -1
  20. package/fesm2022/ieeesa-npm-dashboard.mjs +1300 -444
  21. package/fesm2022/ieeesa-npm-dashboard.mjs.map +1 -1
  22. package/lib/components/event-group-card/event-group-card.component.d.ts +100 -132
  23. package/lib/components/meeting-attendance-row/meeting-attendance-row.component.d.ts +8 -132
  24. package/lib/components/member-level-badge/member-level-badge.component.d.ts +19 -3
  25. package/lib/components/upcoming-meetings-events/upcoming-meetings-events.component.d.ts +63 -126
  26. package/lib/components/your-groups/your-groups.component.d.ts +158 -51
  27. package/lib/dashboard.component.d.ts +48 -10
  28. package/lib/models/event-meeting-list-item.model.d.ts +107 -0
  29. package/lib/models/event-meeting-list-payload.model.d.ts +40 -0
  30. package/lib/models/group-row.model.d.ts +25 -0
  31. package/lib/models/meeting-row.model.d.ts +18 -2
  32. package/lib/models/my-groups-view.model.d.ts +56 -0
  33. package/lib/models/upcoming-event.model.d.ts +40 -2
  34. package/lib/services/dashboard.service.d.ts +97 -14
  35. package/lib/utils/date-format.util.d.ts +60 -0
  36. package/lib/utils/event-meeting-mapper.util.d.ts +50 -0
  37. package/package.json +1 -1
  38. package/public-api.d.ts +2 -0
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter } from '@angular/core';
2
+ import { PageEvent } from '@angular/material/paginator';
2
3
  import { AttendanceActionPermissions } from '../../models/attendance-action-permissions.model';
3
4
  import { AttendanceState } from '../../models/attendance-state.model';
4
5
  import { DashboardSectionState } from '../../models/dashboard-section-state.model';
@@ -26,131 +27,7 @@ import * as i0 from "@angular/core";
26
27
  */
27
28
  export declare class UpcomingMeetingsEventsComponent {
28
29
  /** User-facing strings sourced from `constants.json`. */
29
- constants: {
30
- welcomeHeader: {
31
- greeting: string;
32
- fallbackGreeting: string;
33
- helperText: string;
34
- jumpToLabel: string;
35
- shortcuts: {
36
- meetings: {
37
- label: string;
38
- iconUrl: string;
39
- ariaLabel: string;
40
- };
41
- groups: {
42
- label: string;
43
- iconUrl: string;
44
- ariaLabel: string;
45
- };
46
- };
47
- };
48
- upcomingSection: {
49
- title: string;
50
- viewAllLabel: string;
51
- expandLabel: string;
52
- collapseLabel: string;
53
- ariaLabel: {
54
- viewAll: string;
55
- toggle: string;
56
- };
57
- emptyMessage: string;
58
- errorMessage: string;
59
- };
60
- eventGroupCard: {
61
- viewEventLabel: string;
62
- meetingListToggle: {
63
- showLabelPrefix: string;
64
- showLabelSuffix: string;
65
- hideLabel: string;
66
- };
67
- ariaLabel: {
68
- viewEvent: string;
69
- meetingListToggle: string;
70
- };
71
- paginator: {
72
- rangeTemplate: string;
73
- totalTemplate: string;
74
- };
75
- };
76
- meetingRow: {
77
- emptyFieldPlaceholder: string;
78
- currentlyAttendingIndicator: string;
79
- logAttendanceLabel: string;
80
- leaveMeetingLabel: string;
81
- ariaLabel: {
82
- meetingNameLink: string;
83
- logAttendance: string;
84
- leaveMeeting: string;
85
- };
86
- };
87
- groupsSection: {
88
- title: string;
89
- viewAllLabel: string;
90
- expandLabel: string;
91
- collapseLabel: string;
92
- countSuffix: string;
93
- emptyValue: 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
- /** Enum reference for template comparisons against `sectionState`. */
104
- affiliation: string;
105
- memberLevel: string;
106
- };
107
- paginator: {
108
- rangeTemplate: string;
109
- totalTemplate: string;
110
- };
111
- memberLevelBadge: {
112
- votingMember: string;
113
- default: string;
114
- };
115
- emptyMessage: string; /** Host permissions gating the per-row log-attendance / leave-meeting buttons. */
116
- errorMessage: string;
117
- };
118
- memberLevel: {
119
- colorMap: {
120
- "Voting Member": string;
121
- Observer: string;
122
- /** Map of meeting id to current attendance state, passed down to each card. */
123
- "Associate Member": string;
124
- Member: string;
125
- default: string;
126
- };
127
- };
128
- attendance: {
129
- errorMessage: string;
130
- };
131
- footer: {
132
- links: {
133
- label: string;
134
- target: string;
135
- }[];
136
- copyright: string;
137
- };
138
- defaultRouteConfig: {
139
- eventDetail: string;
140
- meetingDetail: string;
141
- groupDetail: string;
142
- /**
143
- * `trackBy` for the event-group-card `*ngFor`, keyed by the stable event id so
144
- * Angular renders exactly one card per event in input order (Req 5.5, 5.6, 14.4).
145
- * @param {number} index - The iteration index (fallback key).
146
- * @param {UpcomingEvent} event - The event for this card.
147
- * @return {string} The stable track key (event id).
148
- * @memberof UpcomingMeetingsEventsComponent
149
- */
150
- viewAllEvents: string;
151
- viewAllGroups: string;
152
- };
153
- };
30
+ constants: any;
154
31
  /** Enum reference for template comparisons against `sectionState`. */
155
32
  readonly sectionStates: typeof DashboardSectionState;
156
33
  /** The upcoming events rendered as event-group cards (Req 5.5, 5.6). */
@@ -179,8 +56,60 @@ export declare class UpcomingMeetingsEventsComponent {
179
56
  meetingPageChange: EventEmitter<{
180
57
  eventId: string;
181
58
  } & PageChange>;
59
+ /** Emits the event id + one-based page to lazily load an event's child meetings. */
60
+ loadEventMeetings: EventEmitter<{
61
+ eventId: string;
62
+ page: number;
63
+ }>;
182
64
  /** Whether the section's card list is currently expanded; starts collapsed. */
183
65
  isExpanded: boolean;
66
+ /** Section-level page size — 5 events/meetings per page per the design. */
67
+ readonly sectionPageSize = 5;
68
+ /** The current zero-based page index of the section list. */
69
+ sectionPageIndex: number;
70
+ /** The total number of events/meetings in the section (paginator length). */
71
+ get totalItems(): number;
72
+ /**
73
+ * The slice of events/meetings for the current section page (5 per page),
74
+ * used by the card `*ngFor`.
75
+ * @return {UpcomingEvent[]} The events on the current page.
76
+ * @memberof UpcomingMeetingsEventsComponent
77
+ */
78
+ get pagedEvents(): UpcomingEvent[];
79
+ /** The one-based index of the first item shown on the current page. */
80
+ get sectionRangeStart(): number;
81
+ /** The one-based index of the last item shown on the current page. */
82
+ get sectionRangeEnd(): number;
83
+ /**
84
+ * The section paginator range label (e.g. "1-5 of 20 Meetings & Events")
85
+ * built from the `constants.json` template.
86
+ * @return {string} The formatted range label.
87
+ * @memberof UpcomingMeetingsEventsComponent
88
+ */
89
+ get sectionRangeLabel(): string;
90
+ /**
91
+ * Handles the section paginator change, updating the current section page.
92
+ * @param {PageEvent} event - The Material paginator page event.
93
+ * @return {void}
94
+ * @memberof UpcomingMeetingsEventsComponent
95
+ */
96
+ onSectionPageChange(event: PageEvent): void;
97
+ /**
98
+ * Allows the host/container to open or close the section (e.g. a "Jump to"
99
+ * shortcut opens it). Writing the input mirrors the value onto the internal
100
+ * expand state while leaving the user's own toggle free to change it after.
101
+ * @memberof UpcomingMeetingsEventsComponent
102
+ */
103
+ set expanded(value: boolean);
104
+ get expanded(): boolean;
105
+ /**
106
+ * Emits the new expanded state whenever the user toggles the section, so a
107
+ * two-way `[(expanded)]` binding keeps the host's flag in sync (otherwise a
108
+ * host-opened section the user then collapses leaves the host flag stale,
109
+ * making a repeat "Jump to" a no-op).
110
+ * @memberof UpcomingMeetingsEventsComponent
111
+ */
112
+ expandedChange: EventEmitter<boolean>;
184
113
  /**
185
114
  * `trackBy` for the event-group-card `*ngFor`, keyed by the stable event id so
186
115
  * Angular renders exactly one card per event in input order (Req 5.5, 5.6, 14.4).
@@ -233,6 +162,14 @@ export declare class UpcomingMeetingsEventsComponent {
233
162
  * @memberof UpcomingMeetingsEventsComponent
234
163
  */
235
164
  onMeetingPageChange(eventId: string, page: PageChange): void;
165
+ /**
166
+ * Bubbles a card's lazy child-meeting load request upward, tagged with the
167
+ * originating event id so the container can fetch that event's meetings.
168
+ * @param {string} eventId - The event whose meetings to load.
169
+ * @param {number} page - The one-based page requested by the card.
170
+ * @memberof UpcomingMeetingsEventsComponent
171
+ */
172
+ onLoadEventMeetings(eventId: string, page: number): void;
236
173
  static ɵfac: i0.ɵɵFactoryDeclaration<UpcomingMeetingsEventsComponent, never>;
237
- static ɵcmp: i0.ɵɵComponentDeclaration<UpcomingMeetingsEventsComponent, "ieeesa-upcoming-meetings-events", never, { "events": { "alias": "events"; "required": false; }; "sectionState": { "alias": "sectionState"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "attendanceStates": { "alias": "attendanceStates"; "required": false; }; "inFlightMeetingIds": { "alias": "inFlightMeetingIds"; "required": false; }; "isMobileView": { "alias": "isMobileView"; "required": false; }; }, { "viewAll": "viewAll"; "viewEvent": "viewEvent"; "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; "meetingPageChange": "meetingPageChange"; }, never, never, true, never>;
174
+ static ɵcmp: i0.ɵɵComponentDeclaration<UpcomingMeetingsEventsComponent, "ieeesa-upcoming-meetings-events", never, { "events": { "alias": "events"; "required": false; }; "sectionState": { "alias": "sectionState"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "attendanceStates": { "alias": "attendanceStates"; "required": false; }; "inFlightMeetingIds": { "alias": "inFlightMeetingIds"; "required": false; }; "isMobileView": { "alias": "isMobileView"; "required": false; }; "expanded": { "alias": "expanded"; "required": false; }; }, { "viewAll": "viewAll"; "viewEvent": "viewEvent"; "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; "meetingPageChange": "meetingPageChange"; "loadEventMeetings": "loadEventMeetings"; "expandedChange": "expandedChange"; }, never, never, true, never>;
238
175
  }
@@ -1,26 +1,39 @@
1
1
  import { EventEmitter } from '@angular/core';
2
2
  import { PageEvent } from '@angular/material/paginator';
3
- import { PaginatorConfig, TableActions, TableColumnSchema } from '@ieeesa-npm/presentation';
3
+ import { IconButton } from '@ieeesa-npm/presentation';
4
4
  import { DashboardSectionState } from '../../models/dashboard-section-state.model';
5
- import { GroupRow } from '../../models/group-row.model';
5
+ import { GroupHierarchyNode, GroupRow } from '../../models/group-row.model';
6
6
  import { PageChange } from '../../models/page-change.model';
7
7
  import * as i0 from "@angular/core";
8
8
  /**
9
- * Groups_Section (`ieeesa-your-groups`) renders the signed-in user's groups as a
10
- * paginated table inside a collapsible card. It shows the section title and a
11
- * "{n} Groups" count, a "View All" link, and a collapse/expand toggle that
12
- * controls the table's visibility (reflected via `[attr.aria-expanded]`). When
13
- * loaded it renders the groups table with the Presentation_Library
14
- * {@link DataTableComponent} using the columns Group, Type, Officer Role,
15
- * Affiliation, and Member Level (labels sourced from `constants.json`). The
16
- * Group cell is a LINK column that emits `groupSelected(groupId)`, and the
17
- * Member Level cell renders as a colored pill via the data-table's inline-badge
18
- * mechanism (green for voting-type levels, amber otherwise).
9
+ * A single rendered table row. Either a top-level group row (`kind: 'group'`,
10
+ * carrying the full {@link GroupRow}) or a hierarchy node row (`kind:
11
+ * 'hierarchy'`) revealed step-by-step as the user drills down. `nodeIndex` is
12
+ * the node's position in the group's `hierarchy[]`, used to drive the next
13
+ * drill-down level and the per-node toggle (matching the Groups module, where
14
+ * each level reveals only its next child and that child carries its own +/−).
15
+ */
16
+ interface TableRow {
17
+ kind: 'group' | 'hierarchy';
18
+ group?: GroupRow;
19
+ node?: GroupHierarchyNode;
20
+ /** Index of this node within the group's hierarchy[] (hierarchy rows only). */
21
+ nodeIndex?: number;
22
+ level: number;
23
+ }
24
+ /**
25
+ * Groups_Section (`ieeesa-your-groups`) renders the signed-in user's groups in
26
+ * a collapsible card as a custom hierarchy table styled like the My Profile
27
+ * Find Groups tree: each group row carries a blue +/- toggle (when it has an
28
+ * ancestor hierarchy) that expands to reveal the group's hierarchy path
29
+ * (root→leaf), indented. Columns: Group, Type, Officer Role, Affiliation,
30
+ * Member Level (the member level renders as a coloured pill — green for an
31
+ * assigned level, amber for "Unassigned"). The card paginates the top-level
32
+ * groups (5 per page).
19
33
  *
20
- * The section is purely presentational: it emits navigation and pagination
21
- * intents via `@Output()` and never performs navigation or HTTP itself. The
22
- * Loader / empty-state / error regions are mutually exclusive and driven solely
23
- * by the `sectionState` input.
34
+ * Purely presentational: data arrives via `@Input`, intents leave via
35
+ * `@Output`; no API or navigation here. States (loader / empty / error / table)
36
+ * are driven by `sectionState`.
24
37
  * @export
25
38
  * @class YourGroupsComponent
26
39
  */
@@ -30,51 +43,134 @@ export declare class YourGroupsComponent {
30
43
  readonly texts: any;
31
44
  /** Enum reference for template comparisons against `sectionState`. */
32
45
  readonly sectionStates: typeof DashboardSectionState;
46
+ /** Per-level indentation step (px) for the expanded hierarchy rows. */
47
+ readonly indentPerLevel = 28;
48
+ /** Selectable "Items per page" page sizes. */
49
+ readonly pageSizeOptions: number[];
33
50
  /**
34
- * The groups rendered in the table. Defaults to the dummy fixture so the
35
- * table shows immediately while the API integration is pending; the host can
36
- * override it once real data is wired in.
51
+ * Expand (+) icon button — the SAME sprite icon the Groups package uses for
52
+ * its tree expand toggle (icon-expand-collapse-plus), rendered via the shared
53
+ * IconButtonComponent for a consistent look across the app.
37
54
  */
38
- groups: GroupRow[];
55
+ readonly expandIconButton: IconButton;
56
+ /** Collapse (−) icon button — the Groups package's icon-expand-collapse-minus. */
57
+ readonly collapseIconButton: IconButton;
39
58
  /**
40
- * The section's load/empty/error state driving the mutually-exclusive
41
- * regions. Defaults to LOADED (no loader) since the component renders dummy
42
- * data for now; the host can set LOADING/EMPTY/ERROR once the API is wired.
59
+ * Returns the +/- toggle icon button for a level, matching the Groups tree:
60
+ * the minus (collapse) icon when that level is expanded, otherwise the plus
61
+ * (expand) icon.
62
+ * @param {GroupRow} group
63
+ * @param {number} index - -1 for the group row, else the node index.
64
+ * @return {IconButton}
65
+ * @memberof YourGroupsComponent
43
66
  */
67
+ getToggleButton(group: GroupRow, index: number): IconButton;
68
+ private groupsValue;
69
+ /** The groups rendered in the table. */
70
+ set groups(value: GroupRow[]);
71
+ get groups(): GroupRow[];
72
+ /** The section's load/empty/error state driving the mutually-exclusive regions. */
44
73
  sectionState: DashboardSectionState;
45
74
  /** Total number of groups (for the "{n} Groups" count and paginator). */
46
75
  totalGroups: number;
76
+ private pageIndexValue;
47
77
  /** Current zero-based page index. */
48
- pageIndex: number;
49
- /** Current page size. */
50
- pageSize: number;
51
- /** Emits the selected group's id when its name link is clicked. */
52
- groupSelected: EventEmitter<string>;
78
+ set pageIndex(value: number);
79
+ get pageIndex(): number;
80
+ private pageSizeValue;
81
+ /** Current page size (defaults to 5 rows per page per the design). */
82
+ set pageSize(value: number);
83
+ get pageSize(): number;
53
84
  /** Emits when the "View All" link is activated. */
54
85
  viewAllGroups: EventEmitter<void>;
55
86
  /** Emits the requested page when the paginator changes. */
56
87
  pageChange: EventEmitter<PageChange>;
88
+ /**
89
+ * Emits the new expanded state whenever the user toggles the card, so a
90
+ * two-way `[(expanded)]` binding keeps the host's flag in sync. Without this,
91
+ * a host that opened the card (expanded=true) and then the user collapsing it
92
+ * would leave the host flag stale, so re-opening via the same input value
93
+ * would be a no-op.
94
+ * @memberof YourGroupsComponent
95
+ */
96
+ expandedChange: EventEmitter<boolean>;
57
97
  /** Whether the card is expanded (table visible). Starts collapsed. */
58
98
  isExpanded: boolean;
59
- /** Data-table action flags: pagination only (no search/filter/add/edit). */
60
- readonly tableActions: TableActions;
61
99
  /**
62
- * The count shown in the header subtitle, preferring the server total and
63
- * falling back to the current page length.
100
+ * Allows the host/container to open or close the card (e.g. a "Jump to"
101
+ * shortcut opens it).
102
+ * @memberof YourGroupsComponent
103
+ */
104
+ set expanded(value: boolean);
105
+ get expanded(): boolean;
106
+ /**
107
+ * Keys of the hierarchy levels currently expanded, each `"<groupId>:<index>"`.
108
+ * Index -1 is the group row itself (its toggle reveals the first hierarchy
109
+ * node); index N is the Nth hierarchy node (its toggle reveals node N+1). A
110
+ * level only reveals the NEXT node, matching the Groups module's step-by-step
111
+ * drill-down.
112
+ */
113
+ private readonly expandedKeys;
114
+ /** The flattened rows currently rendered (group rows + any revealed hierarchy rows). */
115
+ visibleRows: TableRow[];
116
+ /**
117
+ * The count shown in the header subtitle — the server total when provided,
118
+ * otherwise the number of groups.
64
119
  * @readonly
65
120
  * @memberof YourGroupsComponent
66
121
  */
67
122
  get groupCount(): number;
68
123
  /**
69
- * The paginator config derived from the total/pageSize inputs.
70
- * @readonly
124
+ * Builds the expand/collapse key for a hierarchy level. Index -1 is the group
125
+ * row itself; index N is the Nth hierarchy node.
126
+ * @param {GroupRow} group
127
+ * @param {number} index
128
+ * @return {string}
129
+ * @memberof YourGroupsComponent
130
+ */
131
+ private levelKey;
132
+ /**
133
+ * Whether a level shows a +/- toggle.
134
+ *
135
+ * - Group row (index -1): expandable when it has ANY hierarchy node, matching
136
+ * the Groups module which shows the toggle on every group that has related
137
+ * hierarchy (driven by hasChildren, true for all these groups).
138
+ * - Hierarchy node (index N): expandable only when there is a further node
139
+ * after it (step-by-step drill-down); the deepest node is a leaf, no toggle.
140
+ * @param {GroupRow} group
141
+ * @param {number} index - -1 for the group row, else the node index.
142
+ * @return {boolean}
143
+ * @memberof YourGroupsComponent
144
+ */
145
+ isLevelExpandable(group: GroupRow, index: number): boolean;
146
+ /**
147
+ * Whether the group row shows a toggle (has related hierarchy to drill into).
148
+ * @param {GroupRow} group
149
+ * @return {boolean}
150
+ * @memberof YourGroupsComponent
151
+ */
152
+ hasHierarchy(group: GroupRow): boolean;
153
+ /**
154
+ * Whether a given level is currently expanded (its next node is revealed).
155
+ * @param {GroupRow} group
156
+ * @param {number} index
157
+ * @return {boolean}
158
+ * @memberof YourGroupsComponent
159
+ */
160
+ isLevelExpanded(group: GroupRow, index: number): boolean;
161
+ /** Convenience for the group row (level -1). */
162
+ isGroupExpanded(group: GroupRow): boolean;
163
+ /**
164
+ * Toggles a level's expansion (reveals/hides its next node). Collapsing a
165
+ * level also collapses everything deeper under it so re-opening starts fresh.
166
+ * @param {GroupRow} group
167
+ * @param {number} index - -1 for the group row, else the node index.
71
168
  * @memberof YourGroupsComponent
72
169
  */
73
- get paginatorConfig(): PaginatorConfig;
74
- /** Column schema for the groups data table. */
75
- readonly columnSchema: TableColumnSchema[];
170
+ onToggleLevel(group: GroupRow, index: number): void;
76
171
  /**
77
- * Toggles the card's expanded/collapsed state (table visibility).
172
+ * Toggles the card's expanded/collapsed state (whole table visibility) and
173
+ * emits the new state so the host's two-way binding stays in sync.
78
174
  * @memberof YourGroupsComponent
79
175
  */
80
176
  onToggleExpand(): void;
@@ -84,27 +180,38 @@ export declare class YourGroupsComponent {
84
180
  */
85
181
  onViewAll(): void;
86
182
  /**
87
- * Emits the selected group's id from the data-table link click.
88
- * @param {{ row: GroupRow }} event - The data-table link-click payload.
183
+ * Re-emits the Material paginator change (page index or "Items per page"
184
+ * size) as a {@link PageChange} for the host.
185
+ * @param {PageEvent} event - The Material paginator event.
89
186
  * @memberof YourGroupsComponent
90
187
  */
91
- onGroupLinkClick(event: {
92
- row: GroupRow;
93
- }): void;
188
+ onPaginatorChange(event: PageEvent): void;
94
189
  /**
95
- * Re-emits the paginator change as a {@link PageChange}.
96
- * @param {PageEvent} event - The Material paginator event.
190
+ * Resolves the member-level pill CSS class, mirroring the My Groups profile
191
+ * tab: an assigned level renders green (success), "Unassigned" renders amber.
192
+ * @param {string} memberLevel
193
+ * @return {string}
97
194
  * @memberof YourGroupsComponent
98
195
  */
99
- onPageChange(event: PageEvent): void;
196
+ resolveBadgeClass(memberLevel: string): string;
100
197
  /**
101
- * Resolves the pill CSS class for a member level: the configured "success"
102
- * (green) class for voting-type levels, otherwise the "warning" (amber) class.
103
- * @param {string} memberLevel - The member level label.
198
+ * TrackBy for the rendered table rows.
199
+ * @param {number} index
200
+ * @param {TableRow} row
104
201
  * @return {string}
105
202
  * @memberof YourGroupsComponent
106
203
  */
107
- private resolveBadgeClass;
204
+ trackByRow(index: number, row: TableRow): string;
205
+ /**
206
+ * Rebuilds the visible rows for the current page. Each group reveals its
207
+ * hierarchy ONE level at a time (Groups-module style): the group row reveals
208
+ * node 0 only when its own level (-1) is expanded; node 0 reveals node 1 only
209
+ * when node 0's level is expanded; and so on. Each revealed node that still
210
+ * has a child carries its own +/- toggle.
211
+ * @memberof YourGroupsComponent
212
+ */
213
+ private rebuildRows;
108
214
  static ɵfac: i0.ɵɵFactoryDeclaration<YourGroupsComponent, never>;
109
- static ɵcmp: i0.ɵɵComponentDeclaration<YourGroupsComponent, "ieeesa-your-groups", never, { "groups": { "alias": "groups"; "required": false; }; "sectionState": { "alias": "sectionState"; "required": false; }; "totalGroups": { "alias": "totalGroups"; "required": false; }; "pageIndex": { "alias": "pageIndex"; "required": false; }; "pageSize": { "alias": "pageSize"; "required": false; }; }, { "groupSelected": "groupSelected"; "viewAllGroups": "viewAllGroups"; "pageChange": "pageChange"; }, never, never, true, never>;
215
+ static ɵcmp: i0.ɵɵComponentDeclaration<YourGroupsComponent, "ieeesa-your-groups", never, { "groups": { "alias": "groups"; "required": false; }; "sectionState": { "alias": "sectionState"; "required": false; }; "totalGroups": { "alias": "totalGroups"; "required": false; }; "pageIndex": { "alias": "pageIndex"; "required": false; }; "pageSize": { "alias": "pageSize"; "required": false; }; "expanded": { "alias": "expanded"; "required": false; }; }, { "viewAllGroups": "viewAllGroups"; "pageChange": "pageChange"; "expandedChange": "expandedChange"; }, never, never, true, never>;
110
216
  }
217
+ export {};
@@ -1,4 +1,4 @@
1
- import { EventEmitter, OnDestroy, OnInit } from '@angular/core';
1
+ import { ElementRef, EventEmitter, OnDestroy, OnInit } from '@angular/core';
2
2
  import { BreakpointObserverService } from '@ieeesa-npm/presentation';
3
3
  import { UserPermission } from '@ieeesa-npm/models';
4
4
  import { AlertsService } from '@ieeesa-npm/utility';
@@ -86,17 +86,30 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
86
86
  };
87
87
  emptyMessage: string;
88
88
  errorMessage: string;
89
+ paginator: {
90
+ rangeTemplate: string;
91
+ };
89
92
  };
90
93
  eventGroupCard: {
94
+ eventBadge: string;
95
+ standaloneBadge: string;
96
+ viewLabel: string;
91
97
  viewEventLabel: string;
98
+ eventDatesLabel: string;
99
+ meetingDateLabel: string;
100
+ timeTimezoneLabel: string;
101
+ meetingsLabel: string;
102
+ openForAttendanceTemplate: string;
92
103
  meetingListToggle: {
104
+ showLabel: string;
93
105
  showLabelPrefix: string;
94
106
  showLabelSuffix: string;
95
107
  hideLabel: string;
96
108
  };
97
109
  ariaLabel: {
110
+ view: string;
98
111
  viewEvent: string;
99
- meetingListToggle: string;
112
+ meetingListToggle: string; /** The resolved target route path from the active {@link DashboardRouteConfig}. */
100
113
  };
101
114
  paginator: {
102
115
  rangeTemplate: string;
@@ -105,6 +118,8 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
105
118
  };
106
119
  meetingRow: {
107
120
  emptyFieldPlaceholder: string;
121
+ timeTimezoneLabel: string;
122
+ viewLabel: string;
108
123
  currentlyAttendingIndicator: string;
109
124
  logAttendanceLabel: string;
110
125
  leaveMeetingLabel: string;
@@ -121,6 +136,8 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
121
136
  collapseLabel: string;
122
137
  countSuffix: string;
123
138
  emptyValue: string;
139
+ unassignedMemberLevel: string;
140
+ itemsPerPageLabel: string;
124
141
  ariaLabel: {
125
142
  viewAll: string;
126
143
  toggle: string;
@@ -138,8 +155,8 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
138
155
  totalTemplate: string;
139
156
  };
140
157
  memberLevelBadge: {
141
- votingMember: string;
142
- default: string;
158
+ success: string;
159
+ warning: string;
143
160
  };
144
161
  emptyMessage: string;
145
162
  errorMessage: string;
@@ -168,7 +185,6 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
168
185
  meetingDetail: string;
169
186
  groupDetail: string;
170
187
  viewAllEvents: string;
171
- /** The signed-in user's info used by the welcome header greeting (Req 11.3, 4.1). */
172
188
  viewAllGroups: string;
173
189
  };
174
190
  };
@@ -198,6 +214,17 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
198
214
  attendancePermissions: AttendanceActionPermissions;
199
215
  /** Whether the viewport is at/below the mobile breakpoint (Req 15.1, 15.2). */
200
216
  isMobileView: boolean;
217
+ /** Whether the Upcoming Meetings & Events card is expanded. Starts collapsed. */
218
+ meetingsExpanded: boolean;
219
+ /** Whether the Your Groups card is expanded. Starts collapsed. */
220
+ groupsExpanded: boolean;
221
+ /**
222
+ * Section host elements used to scroll a "Jump to" target into view. Read as
223
+ * ElementRef (not the component instance) so the native element is available
224
+ * for scrollIntoView.
225
+ */
226
+ upcomingSection?: ElementRef<HTMLElement>;
227
+ groupsSection?: ElementRef<HTMLElement>;
201
228
  /**
202
229
  * Total number of meetings across the loaded upcoming events, shown in the
203
230
  * welcome header's "Upcoming Meetings & Events" shortcut badge.
@@ -214,7 +241,7 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
214
241
  get groupsCount(): number;
215
242
  /** The current zero-based page index of the groups table. */
216
243
  groupsPageIndex: number;
217
- /** The current page size of the groups table. */
244
+ /** The current page size of the groups table (5 rows per page per the design). */
218
245
  groupsPageSize: number;
219
246
  /** Completes on destroy to tear down all subscriptions (Req 2.4, 2.5). */
220
247
  private readonly destroy$;
@@ -244,10 +271,9 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
244
271
  */
245
272
  onJumpToDateSelected(): void;
246
273
  /**
247
- * Handles a welcome-header "Jump to" shortcut, emitting the navigation intent
248
- * for the matching section so the host app routes to it: MEETINGS →
249
- * `viewAllEvents` (/events-and-meetings/view-events-meetings-list), GROUPS →
250
- * `viewAllGroups` (/groups).
274
+ * Handles a welcome-header "Jump to" shortcut: opens the matching section's
275
+ * card (so its content is visible) and smoothly scrolls it into view. It does
276
+ * NOT navigate away — the shortcut is an in-page jump to the section.
251
277
  * @param {DashboardJumpTarget} target - The selected shortcut target.
252
278
  * @return {void}
253
279
  * @memberof DashboardComponent
@@ -299,6 +325,18 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
299
325
  * @memberof DashboardComponent
300
326
  */
301
327
  onGroupsPageChange(page: PageChange): void;
328
+ /**
329
+ * Lazily loads (or paginates) the child meetings of an expanded EVENT card via
330
+ * the service, surfacing the attendance error message on failure. Each event
331
+ * paginates independently.
332
+ * @param {{ eventId: string; page: number }} request - The event id and one-based page to load.
333
+ * @return {void}
334
+ * @memberof DashboardComponent
335
+ */
336
+ onLoadEventMeetings(request: {
337
+ eventId: string;
338
+ page: number;
339
+ }): void;
302
340
  /**
303
341
  * Delegates a log-attendance request to the service, surfacing the
304
342
  * attendance-action error message via the shared {@link AlertsService} on