@@ -19,6 +19,7 @@ import {
1919 DropdownMenuItem ,
2020 DropdownMenuTrigger ,
2121} from '@trycompai/ui/dropdown-menu' ;
22+ import { Tooltip , TooltipContent , TooltipProvider , TooltipTrigger } from '@trycompai/ui/tooltip' ;
2223import { parseRolesString } from '@/lib/permissions' ;
2324import type { Role } from '@db' ;
2425import {
@@ -33,7 +34,7 @@ import {
3334 TableRow ,
3435 Text ,
3536} from '@trycompai/design-system' ;
36- import { Checkmark , Edit , Laptop , OverflowMenuVertical , TrashCan } from '@trycompai/design-system/icons' ;
37+ import { Checkmark , Edit , Information , Laptop , OverflowMenuVertical , TrashCan } from '@trycompai/design-system/icons' ;
3738
3839import { toast } from 'sonner' ;
3940import { MultiRoleCombobox } from './MultiRoleCombobox' ;
@@ -52,7 +53,7 @@ interface MemberRowProps {
5253 isCurrentUserOwner : boolean ;
5354 customRoles ?: CustomRoleOption [ ] ;
5455 taskCompletion ?: TaskCompletion ;
55- deviceStatus ?: 'compliant' | 'non-compliant' | 'not-installed' ;
56+ deviceStatus ?: 'compliant' | 'non-compliant' | 'stale' | ' not-installed';
5657 isDeviceStatusLoading ?: boolean ;
5758}
5859
@@ -87,6 +88,34 @@ function parseRoles(role: Role | Role[] | string): string[] {
8788 return parseRolesString ( role ) ;
8889}
8990
91+ type DeviceStatus = 'compliant' | 'non-compliant' | 'stale' | 'not-installed' ;
92+
93+ function getDeviceStatusDotClass ( status : DeviceStatus ) : string {
94+ switch ( status ) {
95+ case 'compliant' :
96+ return 'bg-green-500' ;
97+ case 'non-compliant' :
98+ return 'bg-yellow-500' ;
99+ case 'stale' :
100+ return 'bg-gray-400' ;
101+ case 'not-installed' :
102+ return 'bg-red-400' ;
103+ }
104+ }
105+
106+ function getDeviceStatusLabel ( status : DeviceStatus ) : string {
107+ switch ( status ) {
108+ case 'compliant' :
109+ return 'Compliant' ;
110+ case 'non-compliant' :
111+ return 'Non-Compliant' ;
112+ case 'stale' :
113+ return 'Stale' ;
114+ case 'not-installed' :
115+ return 'Not Installed' ;
116+ }
117+ }
118+
90119export function MemberRow ( {
91120 member,
92121 onRemove,
@@ -251,27 +280,37 @@ export function MemberRow({
251280 ) : (
252281 < div className = "flex items-center gap-2" >
253282 < span
254- className = { `inline-block h-2 w-2 rounded-full ${
255- deviceStatus === 'compliant'
256- ? 'bg-green-500'
257- : deviceStatus === 'non-compliant'
258- ? 'bg-yellow-500'
259- : 'bg-red-400'
260- } `}
283+ className = { `inline-block h-2 w-2 rounded-full ${ getDeviceStatusDotClass ( deviceStatus ) } ` }
261284 />
262285 < span
263286 className = { `text-sm ${
264- deviceStatus === 'not-installed'
287+ deviceStatus === 'not-installed' || deviceStatus === 'stale'
265288 ? 'text-muted-foreground'
266289 : 'text-foreground'
267290 } `}
268291 >
269- { deviceStatus === 'compliant'
270- ? 'Compliant'
271- : deviceStatus === 'non-compliant'
272- ? 'Non-Compliant'
273- : 'Not Installed' }
292+ { getDeviceStatusLabel ( deviceStatus ) }
274293 </ span >
294+ { deviceStatus === 'stale' && (
295+ < TooltipProvider >
296+ < Tooltip >
297+ < TooltipTrigger asChild >
298+ < button
299+ type = "button"
300+ aria-label = "What does Stale mean?"
301+ className = "inline-flex items-center text-muted-foreground hover:text-foreground"
302+ onClick = { ( e ) => e . stopPropagation ( ) }
303+ >
304+ < Information size = { 14 } />
305+ </ button >
306+ </ TooltipTrigger >
307+ < TooltipContent className = "max-w-xs text-xs" >
308+ This device's CompAI agent hasn't reported in recently, so we can't verify
309+ its current compliance. Ask the employee to update or reinstall the agent.
310+ </ TooltipContent >
311+ </ Tooltip >
312+ </ TooltipProvider >
313+ ) }
275314 </ div >
276315 ) }
277316 </ TableCell >
0 commit comments