55 </ span >
66 </ mat-toolbar >
77</ div >
8+
89< div class ="admin-content p-4 ">
910 < mat-card class ="mb-4 top-card ">
1011 < div fxLayout ="row " fxLayoutGap ="24px " fxLayoutAlign ="start stretch ">
1314 < div class ="inactive-users ">
1415 < mat-card >
1516 < mat-card-title >
16- < span class ="title-with-badge "> Inactive Users < span matBadge ="{{ count() }} " matBadgeColor ="accent " matBadgeOverlap ="false " class ="inline-badge "> </ span >
17+ < span class ="title-with-badge ">
18+ Inactive Users
19+ < span matBadge ="{{ count() || 0 }} " matBadgeColor ="accent " matBadgeOverlap ="false " class ="inline-badge "> </ span >
1720 </ span >
1821 </ mat-card-title >
1922 < div class ="search-wrapper ">
2326 </ mat-form-field >
2427 </ div >
2528 < mat-list >
26- < mat-list-item *ngFor ="let user of inactiveUsers " (click) ="gotoUser(user) " class ="clickable ">
29+ < mat-list-item *ngFor ="let user of inactiveUsers || [] " (click) ="gotoUser(user) " class ="clickable ">
2730 < mat-icon matListIcon > person</ mat-icon >
28- < div matLine > {{ user.displayName }}</ div >
31+ < div matLine > {{ user? .displayName || 'Unknown User' }}</ div >
2932 < button mat-mini-button color ="primary " *ngIf ="hasPermission('UPDATE_USER') " (click) ="activateUser($event, user) ">
3033 < mat-icon > check</ mat-icon >
3134 < span > Activate</ span >
3841 </ div >
3942 </ mat-card >
4043 </ div >
44+
4145 <!-- Unregistered Devices -->
4246 < div class ="unregistered-devices ">
4347 < mat-card >
4448 < mat-card-title >
45- < span class ="title-with-badge "> Unregistered Devices < span matBadge ="{{ deviceCount() }} " matBadgeColor ="accent " matBadgeOverlap ="false " class ="inline-badge "> </ span >
49+ < span class ="title-with-badge ">
50+ Unregistered Devices
51+ < span matBadge ="{{ deviceCount() || 0 }} " matBadgeColor ="accent " matBadgeOverlap ="false " class ="inline-badge "> </ span >
4652 </ span >
4753 </ mat-card-title >
4854 < div class ="search-wrapper ">
5258 </ mat-form-field >
5359 </ div >
5460 < mat-list >
55- < mat-list-item *ngFor ="let d of unregisteredDevices " (click) ="gotoDevice(d) " class ="clickable ">
61+ < mat-list-item *ngFor ="let d of unregisteredDevices || [] " (click) ="gotoDevice(d) " class ="clickable ">
5662 < mat-icon matListIcon [ngClass] ="iconClass(d) "> </ mat-icon >
5763 < div class ="mat-line-horizontal ">
58- < span *ngIf ="d.user "> {{ d.user.displayName }}</ span >
59- < span class ="text-muted "> ({{ d.uid }})</ span >
64+ < span *ngIf ="d? .user "> {{ d.user? .displayName || 'Unknown User' }}</ span >
65+ < span class ="text-muted "> ({{ d? .uid || 'Unknown UID' }})</ span >
6066 </ div >
6167 < button mat-mini-button color ="primary " *ngIf ="hasPermission('UPDATE_DEVICE') " (click) ="registerDevice($event, d) ">
6268 < mat-icon > check</ mat-icon > Register
7278 </ div >
7379 </ div >
7480 </ mat-card >
81+
7582 <!-- Logins Section -->
7683 < mat-card class ="mt-5 logins ">
7784 < div class ="logins-header ">
7885 < mat-card-title > Logins</ mat-card-title >
7986 </ div >
87+
8088 < div class ="filter-toggle-wrapper ">
8189 < button mat-stroked-button color ="primary " (click) ="toggleFilters = !toggleFilters " [attr.aria-expanded] ="toggleFilters ">
8290 < mat-icon > {{ toggleFilters ? 'close' : 'filter_list' }}</ mat-icon >
8391 {{ toggleFilters ? 'Hide Filters' : 'Show Filters' }}
8492 </ button >
8593 </ div >
86- <!-- Filter Bar -->
94+
8795 < div class ="filter-bar " [ngClass] ="{ 'expanded': toggleFilters } ">
8896 < mat-form-field >
8997 < mat-label > Filter on User</ mat-label >
92100 < mat-icon > close</ mat-icon >
93101 </ button >
94102 < mat-autocomplete #userAuto ="matAutocomplete " (optionSelected) ="filterLogins() " [displayWith] ="displayUser ">
95- < mat-option *ngFor ="let u of loginSearchResults " [value] ="u ">
96- {{ u.displayName }}
103+ < mat-option *ngFor ="let u of loginSearchResults || [] " [value] ="u ">
104+ {{ u? .displayName || 'Unknown User' }}
97105 </ mat-option >
98106 </ mat-autocomplete >
99107 </ mat-form-field >
108+
100109 < mat-form-field >
101110 < mat-label > Filter on Device</ mat-label >
102111 < mat-select [(ngModel)] ="device " (selectionChange) ="filterLogins() " multiple >
103- < mat-option *ngFor ="let d of loginDeviceSearchResults " [value] ="d ">
104- {{ d.uid }} - {{ d.user?.displayName || 'Unknown User' }}
112+ < mat-option *ngFor ="let d of loginDeviceSearchResults || [] " [value] ="d ">
113+ {{ d? .uid || 'Unknown UID' }} - {{ d? .user?.displayName || 'Unknown User' }}
105114 </ mat-option >
106115 </ mat-select >
107116 < button mat-icon-button matSuffix *ngIf ="device?.length " aria-label ="Clear " (click) ="clearDeviceFilter() ">
108117 < mat-icon > close</ mat-icon >
109118 </ button >
110119 </ mat-form-field >
111- < mat-form-field >
112- < mat-label > Start Date</ mat-label >
113- < input matInput [matDatepicker] ="startPicker " [(ngModel)] ="login.startDate " (dateChange) ="dateFilterChanged() " />
114- < mat-datepicker-toggle matSuffix [for] ="startPicker "> </ mat-datepicker-toggle >
115- < mat-datepicker #startPicker > </ mat-datepicker >
116- </ mat-form-field >
117- < mat-form-field >
118- < mat-label > End Date</ mat-label >
119- < input matInput [matDatepicker] ="endPicker " [(ngModel)] ="login.endDate " (dateChange) ="dateFilterChanged() " />
120- < mat-datepicker-toggle matSuffix [for] ="endPicker "> </ mat-datepicker-toggle >
121- < mat-datepicker #endPicker > </ mat-datepicker >
122- </ mat-form-field >
120+
121+ < ng-container *ngIf ="login ">
122+ < mat-form-field >
123+ < mat-label > Start Date</ mat-label >
124+ < input matInput [matDatepicker] ="startPicker " [(ngModel)] ="login.startDate " (dateChange) ="dateFilterChanged() " />
125+ < mat-datepicker-toggle matSuffix [for] ="startPicker "> </ mat-datepicker-toggle >
126+ < mat-datepicker #startPicker > </ mat-datepicker >
127+ </ mat-form-field >
128+
129+ < mat-form-field >
130+ < mat-label > End Date</ mat-label >
131+ < input matInput [matDatepicker] ="endPicker " [(ngModel)] ="login.endDate " (dateChange) ="dateFilterChanged() " />
132+ < mat-datepicker-toggle matSuffix [for] ="endPicker "> </ mat-datepicker-toggle >
133+ < mat-datepicker #endPicker > </ mat-datepicker >
134+ </ mat-form-field >
135+ </ ng-container >
136+
123137 < div class ="results-select ">
124138 < mat-form-field >
125139 < mat-label > Results</ mat-label >
129143 </ mat-form-field >
130144 </ div >
131145 </ div >
132- < div class =" table-wrapper " >
133- < table mat-table [dataSource] =" loginPage?.logins " class =" mat-elevation-z1 full-width-table ">
134- <!-- Icon Column -- >
146+
147+ < div class =" table-wrapper " *ngIf =" loginPage ">
148+ < table mat-table [dataSource] =" loginPage.logins || [] " class =" mat-elevation-z1 full-width-table " >
135149 < ng-container matColumnDef ="icon ">
136150 < th mat-header-cell *matHeaderCellDef > </ th >
137151 < td mat-cell *matCellDef ="let login ">
138- < mat-icon [ngClass] ="iconClass(login.device) "> </ mat-icon >
152+ < mat-icon [ngClass] ="iconClass(login? .device) "> </ mat-icon >
139153 </ td >
140154 </ ng-container >
141- <!-- User Column -->
155+
142156 < ng-container matColumnDef ="user ">
143157 < th mat-header-cell *matHeaderCellDef > User</ th >
144158 < td mat-cell *matCellDef ="let login ">
145- < a (click) ="gotoUser(login.user) "> {{ login.user.displayName }}</ a >
159+ < a *ngIf =" login?.user " (click) ="gotoUser(login.user) "> {{ login.user.displayName || 'Unknown User' }}</ a >
146160 </ td >
147161 </ ng-container >
148- <!-- Device Column -->
162+
149163 < ng-container matColumnDef ="device ">
150164 < th mat-header-cell *matHeaderCellDef > Device</ th >
151165 < td mat-cell *matCellDef ="let login ">
152- < a (click) ="gotoDevice(login.device) "> {{ login.device.uid }}</ a >
166+ < a *ngIf =" login?.device " (click) ="gotoDevice(login.device) "> {{ login.device.uid || 'Unknown Device' }}</ a >
153167 </ td >
154168 </ ng-container >
155- <!-- Timestamp Column -->
169+
156170 < ng-container matColumnDef ="timestamp ">
157171 < th mat-header-cell *matHeaderCellDef > Timestamp</ th >
158172 < td mat-cell *matCellDef ="let login ">
159- {{ login.timestamp | date:'short' }}
173+ {{ login? .timestamp | date:'short' }}
160174 </ td >
161175 </ ng-container >
162- <!-- Table Rows -->
176+
163177 < tr mat-header-row *matHeaderRowDef ="['icon', 'user', 'device', 'timestamp'] "> </ tr >
164178 < tr mat-row *matRowDef ="let row; columns: ['icon', 'user', 'device', 'timestamp'] "> </ tr >
165179 </ table >
166180 </ div >
167- <!-- Pagination -->
181+
168182 < div class ="d-flex justify-content-end mt-3 pagination-controls ">
169- < button mat-button (click) ="pageLogin(loginPage.prev) " [disabled] ="!showPrevious "> ← Previous</ button >
170- < button mat-button (click) ="pageLogin(loginPage.next) " [disabled] ="!showNext "> Next →</ button >
183+ < button mat-button (click) ="pageLogin(loginPage? .prev) " [disabled] ="!showPrevious "> ← Previous</ button >
184+ < button mat-button (click) ="pageLogin(loginPage? .next) " [disabled] ="!showNext "> Next →</ button >
171185 </ div >
172186 </ mat-card >
173- </ div >
187+ </ div >
0 commit comments