@@ -13,7 +13,7 @@ import {
1313 TabsTrigger ,
1414 Text ,
1515} from '@trycompai/design-system' ;
16- import { AlertCircle , Award , CheckCircle2 , Download } from 'lucide-react' ;
16+ import { AlertCircle , Award , CheckCircle2 , Download , Info } from 'lucide-react' ;
1717import type { FleetPolicy , Host } from '../../devices/types' ;
1818import { PolicyItem } from '../../devices/components/PolicyItem' ;
1919import { downloadTrainingCertificate } from '../actions/download-training-certificate' ;
@@ -120,102 +120,126 @@ export const EmployeeTasks = ({
120120 </ TabsContent >
121121
122122 < TabsContent value = "training" >
123- < Stack gap = "md" >
124- { /* Training Completion Summary */ }
125- { trainingVideos . length > 0 && (
126- < div
127- className = { cn (
128- 'flex items-center justify-between rounded-lg border p-4' ,
129- allTrainingComplete
130- ? 'border-primary/20 bg-primary/5'
131- : 'border-muted bg-muted/30' ,
132- ) }
133- >
134- < div className = "flex items-center gap-3" >
135- < div
136- className = { cn (
137- 'flex h-10 w-10 items-center justify-center rounded-full' ,
138- allTrainingComplete ? 'bg-primary/10' : 'bg-muted' ,
139- ) }
140- >
141- < Award
123+ { ! organization . securityTrainingStepEnabled ? (
124+ < div className = "flex items-center gap-3 rounded-lg border border-muted bg-muted/30 p-4" >
125+ < Info className = "h-5 w-5 shrink-0 text-muted-foreground" />
126+ < div >
127+ < Text weight = "medium" > Security training is managed outside of Comp AI</ Text >
128+ < Text size = "sm" variant = "muted" >
129+ Evidence for security training completion can be logged in the Security Awareness
130+ Training evidence task.
131+ </ Text >
132+ </ div >
133+ </ div >
134+ ) : (
135+ < Stack gap = "md" >
136+ { /* Training Completion Summary */ }
137+ { trainingVideos . length > 0 && (
138+ < div
139+ className = { cn (
140+ 'flex items-center justify-between rounded-lg border p-4' ,
141+ allTrainingComplete
142+ ? 'border-primary/20 bg-primary/5'
143+ : 'border-muted bg-muted/30' ,
144+ ) }
145+ >
146+ < div className = "flex items-center gap-3" >
147+ < div
142148 className = { cn (
143- 'h-5 w-5 ' ,
144- allTrainingComplete ? 'text -primary' : 'text -muted-foreground ' ,
149+ 'flex h-10 w-10 items-center justify-center rounded-full ' ,
150+ allTrainingComplete ? 'bg -primary/10 ' : 'bg -muted' ,
145151 ) }
146- />
147- </ div >
148- < div >
149- < Text weight = "medium" >
150- { allTrainingComplete
151- ? 'All Training Complete'
152- : `${ completedVideos . length } /${ trainingVideos . length } Videos Completed` }
153- </ Text >
154- { trainingCompletionDate && (
155- < Text size = "sm" variant = "muted" >
156- Completed on{ ' ' }
157- { new Date ( trainingCompletionDate ) . toLocaleDateString ( 'en-US' , {
158- year : 'numeric' ,
159- month : 'long' ,
160- day : 'numeric' ,
161- } ) }
152+ >
153+ < Award
154+ className = { cn (
155+ 'h-5 w-5' ,
156+ allTrainingComplete ? 'text-primary' : 'text-muted-foreground' ,
157+ ) }
158+ />
159+ </ div >
160+ < div >
161+ < Text weight = "medium" >
162+ { allTrainingComplete
163+ ? 'All Training Complete'
164+ : `${ completedVideos . length } /${ trainingVideos . length } Videos Completed` }
162165 </ Text >
163- ) }
166+ { trainingCompletionDate && (
167+ < Text size = "sm" variant = "muted" >
168+ Completed on{ ' ' }
169+ { new Date ( trainingCompletionDate ) . toLocaleDateString ( 'en-US' , {
170+ year : 'numeric' ,
171+ month : 'long' ,
172+ day : 'numeric' ,
173+ } ) }
174+ </ Text >
175+ ) }
176+ </ div >
164177 </ div >
178+ { allTrainingComplete && (
179+ < button
180+ onClick = { handleDownloadCertificate }
181+ className = "inline-flex items-center gap-2 rounded-lg border border-primary bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition-all duration-200 hover:bg-primary/90 hover:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/20 focus-visible:ring-offset-1 cursor-pointer"
182+ >
183+ < Download className = "h-3.5 w-3.5" />
184+ Certificate
185+ </ button >
186+ ) }
165187 </ div >
166- { allTrainingComplete && (
167- < button
168- onClick = { handleDownloadCertificate }
169- className = "inline-flex items-center gap-2 rounded-lg border border-primary bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition-all duration-200 hover:bg-primary/90 hover:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/20 focus-visible:ring-offset-1 cursor-pointer"
170- >
171- < Download className = "h-3.5 w-3.5" />
172- Certificate
173- </ button >
174- ) }
175- </ div >
176- ) }
188+ ) }
177189
178- < Stack gap = "sm" >
179- { trainingVideos . length === 0 ? (
180- < div className = "py-6 text-center" >
181- < Text variant = "muted" > No training videos required to watch.</ Text >
182- </ div >
183- ) : (
184- trainingVideos . map ( ( video ) => {
185- const isCompleted = video . completedAt !== null ;
190+ < Stack gap = "sm" >
191+ { trainingVideos . length === 0 ? (
192+ < div className = "py-6 text-center" >
193+ < Text variant = "muted" > No training videos required to watch.</ Text >
194+ </ div >
195+ ) : (
196+ trainingVideos . map ( ( video ) => {
197+ const isCompleted = video . completedAt !== null ;
186198
187- return (
188- < div
189- key = { video . id }
190- className = "flex items-center justify-between gap-2 rounded-md border p-3"
191- >
192- < Stack gap = "xs" >
193- < div className = "flex items-center gap-2" >
194- { isCompleted ? (
195- < CheckCircle2 className = "h-4 w-4 text-primary" />
196- ) : (
197- < AlertCircle className = "h-4 w-4 text-destructive" />
199+ return (
200+ < div
201+ key = { video . id }
202+ className = "flex items-center justify-between gap-2 rounded-md border p-3"
203+ >
204+ < Stack gap = "xs" >
205+ < div className = "flex items-center gap-2" >
206+ { isCompleted ? (
207+ < CheckCircle2 className = "h-4 w-4 text-primary" />
208+ ) : (
209+ < AlertCircle className = "h-4 w-4 text-destructive" />
210+ ) }
211+ < Text > { video . metadata . title } </ Text >
212+ </ div >
213+ { isCompleted && (
214+ < Text size = "xs" variant = "muted" >
215+ Completed -{ ' ' }
216+ { video . completedAt &&
217+ new Date ( video . completedAt ) . toLocaleDateString ( ) }
218+ </ Text >
198219 ) }
199- < Text > { video . metadata . title } </ Text >
200- </ div >
201- { isCompleted && (
202- < Text size = "xs" variant = "muted" >
203- Completed -{ ' ' }
204- { video . completedAt &&
205- new Date ( video . completedAt ) . toLocaleDateString ( ) }
206- </ Text >
207- ) }
208- </ Stack >
209- </ div >
210- ) ;
211- } )
212- ) }
220+ </ Stack >
221+ </ div >
222+ ) ;
223+ } )
224+ ) }
225+ </ Stack >
213226 </ Stack >
214- </ Stack >
227+ ) }
215228 </ TabsContent >
216229
217230 < TabsContent value = "device" >
218- { host ? (
231+ { ! organization . deviceAgentStepEnabled ? (
232+ < div className = "flex items-center gap-3 rounded-lg border border-muted bg-muted/30 p-4" >
233+ < Info className = "h-5 w-5 shrink-0 text-muted-foreground" />
234+ < div >
235+ < Text weight = "medium" > Device agent is managed outside of Comp AI</ Text >
236+ < Text size = "sm" variant = "muted" >
237+ Evidence for device compliance can be logged in the Secure Device and Device List
238+ evidence tasks.
239+ </ Text >
240+ </ div >
241+ </ div >
242+ ) : host ? (
219243 < Card >
220244 < CardHeader >
221245 < CardTitle > { host . computer_name } 's Policies</ CardTitle >
0 commit comments