1- " use client" ;
1+ ' use client' ;
22
33import {
44 AlertCircle ,
@@ -10,15 +10,15 @@ import {
1010 MessageSquare ,
1111 Shield ,
1212 XCircle ,
13- } from " lucide-react" ;
14- import Link from " next/link" ;
15- import { useParams } from " next/navigation" ;
16- import { useCallback , useEffect , useState } from " react" ;
13+ } from ' lucide-react' ;
14+ import Link from ' next/link' ;
15+ import { useParams } from ' next/navigation' ;
16+ import { useCallback , useEffect , useState } from ' react' ;
1717
18- import type { Finding } from " @/components/audits/finding-card" ;
19- import { FindingList } from " @/components/audits/finding-list" ;
20- import { SeverityChart } from " @/components/audits/severity-chart" ;
21- import { apiGet , apiPatch } from " @/lib/api-helpers" ;
18+ import type { Finding } from ' @/components/audits/finding-card' ;
19+ import { FindingList } from ' @/components/audits/finding-list' ;
20+ import { SeverityChart } from ' @/components/audits/severity-chart' ;
21+ import { apiGet , apiPatch } from ' @/lib/api-helpers' ;
2222
2323interface AuditData {
2424 id : string ;
@@ -46,14 +46,14 @@ const statusIcon: Record<string, React.ElementType> = {
4646} ;
4747
4848const statusColor : Record < string , string > = {
49- COMPLETED : " text-emerald-500" ,
50- VERIFIED : " text-violet-500" ,
51- SCANNING : " text-blue-500" ,
52- FAILED : " text-red-500" ,
53- PENDING : " text-amber-500" ,
49+ COMPLETED : ' text-emerald-500' ,
50+ VERIFIED : ' text-violet-500' ,
51+ SCANNING : ' text-blue-500' ,
52+ FAILED : ' text-red-500' ,
53+ PENDING : ' text-amber-500' ,
5454} ;
5555
56- const SEVERITY_ORDER = [ " CRITICAL" , " HIGH" , " MEDIUM" , " LOW" , " GAS" , " INFORMATIONAL" ] ;
56+ const SEVERITY_ORDER = [ ' CRITICAL' , ' HIGH' , ' MEDIUM' , ' LOW' , ' GAS' , ' INFORMATIONAL' ] ;
5757
5858export default function AuditDetailPage ( ) {
5959 const params = useParams ( ) ;
@@ -67,15 +67,13 @@ export default function AuditDetailPage() {
6767 setLoading ( true ) ;
6868 setError ( null ) ;
6969 try {
70- const json = await apiGet < { success : boolean ; data : AuditData } > (
71- `/api/v1/audits/${ auditId } ` ,
72- ) ;
70+ const json = await apiGet < { success : boolean ; data : AuditData } > ( `/api/v1/audits/${ auditId } ` ) ;
7371 if ( ! json . success || ! json . data ) {
74- throw new Error ( " Failed to load audit" ) ;
72+ throw new Error ( ' Failed to load audit' ) ;
7573 }
7674 setAudit ( json . data ) ;
7775 } catch ( err ) {
78- setError ( err instanceof Error ? err . message : " Failed to load audit" ) ;
76+ setError ( err instanceof Error ? err . message : ' Failed to load audit' ) ;
7977 } finally {
8078 setLoading ( false ) ;
8179 }
@@ -92,17 +90,15 @@ export default function AuditDetailPage() {
9290 // Optimistic update
9391 setAudit ( {
9492 ...audit ,
95- findings : audit . findings . map ( ( f ) =>
96- f . id === findingId ? { ...f , status : newStatus } : f ,
97- ) ,
93+ findings : audit . findings . map ( ( f ) => ( f . id === findingId ? { ...f , status : newStatus } : f ) ) ,
9894 } ) ;
9995
10096 try {
10197 await apiPatch ( `/api/v1/audits/findings/${ findingId } ` , {
10298 status : newStatus ,
10399 } ) ;
104100 } catch ( err ) {
105- console . error ( " Failed to update finding status:" , err ) ;
101+ console . error ( ' Failed to update finding status:' , err ) ;
106102 // Revert on failure
107103 void fetchAudit ( ) ;
108104 }
@@ -134,9 +130,7 @@ export default function AuditDetailPage() {
134130 < AlertCircle className = "text-destructive h-10 w-10" />
135131 < div className = "text-center" >
136132 < h2 className = "text-lg font-semibold" > Failed to Load Audit</ h2 >
137- < p className = "text-muted-foreground mt-1 text-sm" >
138- { error ?? "Audit not found" }
139- </ p >
133+ < p className = "text-muted-foreground mt-1 text-sm" > { error ?? 'Audit not found' } </ p >
140134 </ div >
141135 < div className = "flex gap-3" >
142136 < Link
@@ -173,7 +167,7 @@ export default function AuditDetailPage() {
173167 ? formatDuration ( audit . startedAt , audit . completedAt )
174168 : null ;
175169
176- const completedDate = audit . completedAt ?. split ( "T" ) [ 0 ] ?? null ;
170+ const completedDate = audit . completedAt ?. split ( 'T' ) [ 0 ] ?? null ;
177171
178172 return (
179173 < div className = "space-y-6" >
@@ -188,10 +182,7 @@ export default function AuditDetailPage() {
188182 < div className = "flex-1" >
189183 < h1 className = "text-2xl font-bold tracking-tight" > Audit Detail</ h1 >
190184 < p className = "text-muted-foreground mt-1" >
191- < Link
192- href = { `/dashboard/projects/${ audit . project . id } ` }
193- className = "hover:text-primary"
194- >
185+ < Link href = { `/dashboard/projects/${ audit . project . id } ` } className = "hover:text-primary" >
195186 { audit . project . name }
196187 </ Link >
197188 </ p >
@@ -213,46 +204,41 @@ export default function AuditDetailPage() {
213204 < div className = "grid gap-4 sm:grid-cols-2 md:grid-cols-5" >
214205 { [
215206 {
216- label : " Security Score" ,
217- value : audit . securityScore !== null ? `${ audit . securityScore } /100` : "—" ,
207+ label : ' Security Score' ,
208+ value : audit . securityScore !== null ? `${ audit . securityScore } /100` : '—' ,
218209 color :
219210 audit . securityScore !== null
220211 ? audit . securityScore >= 80
221- ? " text-emerald-500"
212+ ? ' text-emerald-500'
222213 : audit . securityScore >= 50
223- ? " text-amber-500"
224- : " text-red-500"
225- : " text-muted-foreground" ,
214+ ? ' text-amber-500'
215+ : ' text-red-500'
216+ : ' text-muted-foreground' ,
226217 } ,
227218 {
228- label : " Status" ,
219+ label : ' Status' ,
229220 value : audit . status ,
230- color : statusColor [ audit . status ] ?? "" ,
221+ color : statusColor [ audit . status ] ?? '' ,
231222 icon : StatusIcon ,
232223 } ,
233224 {
234- label : " Findings" ,
225+ label : ' Findings' ,
235226 value : audit . findings . length ,
236- color : " text-violet-500" ,
227+ color : ' text-violet-500' ,
237228 } ,
238229 {
239- label : " Duration" ,
240- value : duration ?? "—" ,
241- color : " text-blue-500" ,
230+ label : ' Duration' ,
231+ value : duration ?? '—' ,
232+ color : ' text-blue-500' ,
242233 } ,
243234 {
244- label : " Completed" ,
245- value : completedDate ?? "—" ,
246- color : " text-muted-foreground" ,
235+ label : ' Completed' ,
236+ value : completedDate ?? '—' ,
237+ color : ' text-muted-foreground' ,
247238 } ,
248239 ] . map ( ( stat ) => (
249- < div
250- key = { stat . label }
251- className = "bg-card rounded-xl border p-4 shadow-sm"
252- >
253- < p className = "text-muted-foreground text-xs font-medium" >
254- { stat . label }
255- </ p >
240+ < div key = { stat . label } className = "bg-card rounded-xl border p-4 shadow-sm" >
241+ < p className = "text-muted-foreground text-xs font-medium" > { stat . label } </ p >
256242 < p className = { `mt-1 text-2xl font-bold ${ stat . color } ` } >
257243 { stat . icon && < stat . icon className = "mr-1 inline h-5 w-5" /> }
258244 { stat . value }
@@ -266,28 +252,23 @@ export default function AuditDetailPage() {
266252 { /* Findings with filters */ }
267253 < div className = "lg:col-span-3" >
268254 < div className = "mb-4 flex flex-wrap items-center justify-between gap-3" >
269- < h2 className = "text-xl font-bold" >
270- Findings ({ audit . findings . length } )
271- </ h2 >
255+ < h2 className = "text-xl font-bold" > Findings ({ audit . findings . length } )</ h2 >
272256 < div className = "flex flex-wrap gap-1.5" >
273257 { Object . entries ( severityCounts )
274- . sort (
275- ( a , b ) =>
276- SEVERITY_ORDER . indexOf ( a [ 0 ] ) - SEVERITY_ORDER . indexOf ( b [ 0 ] ) ,
277- )
258+ . sort ( ( a , b ) => SEVERITY_ORDER . indexOf ( a [ 0 ] ) - SEVERITY_ORDER . indexOf ( b [ 0 ] ) )
278259 . map ( ( [ severity , count ] ) => {
279260 const severityBadgeColors : Record < string , string > = {
280- CRITICAL : " bg-red-500/10 text-red-500" ,
281- HIGH : " bg-orange-500/10 text-orange-500" ,
282- MEDIUM : " bg-yellow-500/10 text-yellow-500" ,
283- LOW : " bg-green-500/10 text-green-500" ,
284- GAS : " bg-blue-500/10 text-blue-500" ,
285- INFORMATIONAL : " bg-muted text-muted-foreground" ,
261+ CRITICAL : ' bg-red-500/10 text-red-500' ,
262+ HIGH : ' bg-orange-500/10 text-orange-500' ,
263+ MEDIUM : ' bg-yellow-500/10 text-yellow-500' ,
264+ LOW : ' bg-green-500/10 text-green-500' ,
265+ GAS : ' bg-blue-500/10 text-blue-500' ,
266+ INFORMATIONAL : ' bg-muted text-muted-foreground' ,
286267 } ;
287268 return (
288269 < span
289270 key = { severity }
290- className = { `inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium ${ severityBadgeColors [ severity ] ?? "" } ` }
271+ className = { `inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium ${ severityBadgeColors [ severity ] ?? '' } ` }
291272 >
292273 { severity } { count }
293274 </ span >
@@ -315,32 +296,24 @@ export default function AuditDetailPage() {
315296 { audit . commitHash && (
316297 < div className = "flex items-center justify-between" >
317298 < span className = "text-muted-foreground" > Commit</ span >
318- < span className = "font-mono text-xs" >
319- { audit . commitHash . slice ( 0 , 10 ) } ...
320- </ span >
299+ < span className = "font-mono text-xs" > { audit . commitHash . slice ( 0 , 10 ) } ...</ span >
321300 </ div >
322301 ) }
323302 { audit . reportHash && (
324303 < div className = "flex items-center justify-between" >
325304 < span className = "text-muted-foreground" > Report Hash</ span >
326- < span className = "font-mono text-xs" >
327- { audit . reportHash . slice ( 0 , 10 ) } ...
328- </ span >
305+ < span className = "font-mono text-xs" > { audit . reportHash . slice ( 0 , 10 ) } ...</ span >
329306 </ div >
330307 ) }
331308 { audit . transactionHash && (
332309 < div className = "flex items-center justify-between" >
333310 < span className = "text-muted-foreground" > Tx Hash</ span >
334- < span className = "font-mono text-xs" >
335- { audit . transactionHash . slice ( 0 , 10 ) } ...
336- </ span >
311+ < span className = "font-mono text-xs" > { audit . transactionHash . slice ( 0 , 10 ) } ...</ span >
337312 </ div >
338313 ) }
339314 < div className = "flex items-center justify-between" >
340315 < span className = "text-muted-foreground" > Created</ span >
341- < span className = "text-xs" >
342- { new Date ( audit . createdAt ) . toLocaleDateString ( ) }
343- </ span >
316+ < span className = "text-xs" > { new Date ( audit . createdAt ) . toLocaleDateString ( ) } </ span >
344317 </ div >
345318 </ div >
346319 </ div >
@@ -383,7 +356,7 @@ function formatDuration(start: string, end: string): string {
383356 const diffMs = endDate . getTime ( ) - startDate . getTime ( ) ;
384357 const mins = Math . floor ( diffMs / 60000 ) ;
385358
386- if ( mins < 1 ) return " <1 min" ;
359+ if ( mins < 1 ) return ' <1 min' ;
387360 if ( mins < 60 ) return `${ mins } min` ;
388361 const hours = Math . floor ( mins / 60 ) ;
389362 const remainingMins = mins % 60 ;
0 commit comments