11/**
22 * @file views/repos/TrackerReportsViewBeta.tsx
3- * Analytics dashboard with AI insights, velocity chart,
3+ * Stats & reports dashboard with AI insights, velocity chart,
44 * and team workload visualization.
55 *
6- * Fetches system status from /api/projects/sentinel/status.
6+ * Fetches from /api/projects/sentinel/status for live metrics .
77 */
88
99import React , { useState , useEffect } from "react" ;
@@ -12,17 +12,16 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/com
1212import { Alert , AlertDescription , AlertTitle } from "@/components/ui/alert" ;
1313import { TrendingUp , AlertTriangle , Users , Activity , CheckCircle2 , Bot , Loader2 } from "lucide-react" ;
1414
15- interface SentinelStatus {
15+ interface StatusData {
1616 totalTasks : number ;
17- availableTasks : number ;
18- claimedTasks : number ;
17+ activeTasks : number ;
1918 completedTasks : number ;
20- recentEvents : any [ ] ;
19+ blockedTasks : number ;
2120}
2221
2322export default function TrackerReportsViewBeta ( ) {
2423 const { owner, repo } = useParams ( ) ;
25- const [ status , setStatus ] = useState < SentinelStatus | null > ( null ) ;
24+ const [ status , setStatus ] = useState < StatusData | null > ( null ) ;
2625 const [ loading , setLoading ] = useState ( true ) ;
2726
2827 useEffect ( ( ) => {
@@ -34,9 +33,16 @@ export default function TrackerReportsViewBeta() {
3433 } ) ;
3534 if ( ! res . ok ) throw new Error ( "Failed to fetch" ) ;
3635 const data = await res . json ( ) ;
37- if ( ! cancelled ) setStatus ( data ) ;
36+ if ( ! cancelled ) {
37+ setStatus ( {
38+ totalTasks : data . totalTasks ?? data . taskCounts ?. total ?? 0 ,
39+ activeTasks : data . activeTasks ?? data . taskCounts ?. active ?? 0 ,
40+ completedTasks : data . completedTasks ?? data . taskCounts ?. completed ?? 0 ,
41+ blockedTasks : data . blockedTasks ?? data . taskCounts ?. blocked ?? 0 ,
42+ } ) ;
43+ }
3844 } catch {
39- // Use fallback
45+ // Use defaults
4046 } finally {
4147 if ( ! cancelled ) setLoading ( false ) ;
4248 }
@@ -45,14 +51,47 @@ export default function TrackerReportsViewBeta() {
4551 return ( ) => { cancelled = true ; } ;
4652 } , [ owner , repo ] ) ;
4753
48- const totalTasks = status ?. totalTasks ?? 42 ;
49- const completedTasks = status ?. completedTasks ?? 28 ;
50- const completionPct = totalTasks > 0 ? Math . round ( ( completedTasks / totalTasks ) * 100 ) : 0 ;
51-
5254 const workload = [
5355 { name : "Alex M." , tasks : 12 , capacity : 15 , color : "bg-indigo-500" } ,
5456 { name : "Sarah J." , tasks : 18 , capacity : 15 , color : "bg-rose-500" } ,
55- { name : "AI Agent" , tasks : status ?. claimedTasks ?? 45 , capacity : 100 , color : "bg-emerald-500" } ,
57+ { name : "AI Agent" , tasks : 45 , capacity : 100 , color : "bg-emerald-500" } ,
58+ ] ;
59+
60+ const completionPct = status
61+ ? status . totalTasks > 0
62+ ? Math . round ( ( status . completedTasks / status . totalTasks ) * 100 )
63+ : 0
64+ : 68 ;
65+
66+ const metrics = [
67+ {
68+ label : "Sprint Completion" ,
69+ value : `${ completionPct } %` ,
70+ icon : CheckCircle2 ,
71+ color : "text-emerald-400" ,
72+ sub : status ? `${ status . completedTasks } of ${ status . totalTasks } tasks` : "+12% from last sprint" ,
73+ } ,
74+ {
75+ label : "Active Tasks" ,
76+ value : status ? String ( status . activeTasks ) : "4" ,
77+ icon : Activity ,
78+ color : "text-indigo-400" ,
79+ sub : status ? "Currently in progress" : "2 at risk of delay" ,
80+ } ,
81+ {
82+ label : "Cycle Time" ,
83+ value : "2.4d" ,
84+ icon : TrendingUp ,
85+ color : "text-amber-400" ,
86+ sub : "-0.5d improvement" ,
87+ } ,
88+ {
89+ label : "Bottlenecks" ,
90+ value : status ? String ( status . blockedTasks ) : "3" ,
91+ icon : AlertTriangle ,
92+ color : "text-rose-400" ,
93+ sub : "Waiting on external APIs" ,
94+ } ,
5695 ] ;
5796
5897 if ( loading ) {
@@ -65,25 +104,19 @@ export default function TrackerReportsViewBeta() {
65104
66105 return (
67106 < div className = "h-full overflow-y-auto pr-2 space-y-6" >
68-
69107 { /* AI Callout Alert */ }
70108 < Alert className = "bg-indigo-500/10 border-indigo-500/20 text-indigo-200 shadow-xl shadow-indigo-500/5" >
71109 < Bot className = "h-4 w-4 text-indigo-400" />
72110 < AlertTitle className = "font-semibold text-indigo-300" > AI Project Insights</ AlertTitle >
73111 < AlertDescription className = "text-indigo-200/80 text-xs mt-1 leading-relaxed" >
74- Velocity has increased by 14% this sprint. However, < strong > Sarah J.</ strong > is over capacity.
75- Consider dispatching a Code Review agent to unblock her tasks currently in review.
112+ Velocity has increased by 14% this sprint. However, < strong > Sarah J.</ strong > is over
113+ capacity. Consider dispatching a Code Review agent to unblock her tasks currently in review.
76114 </ AlertDescription >
77115 </ Alert >
78116
79117 { /* Top Metrics Strip */ }
80118 < div className = "grid grid-cols-1 md:grid-cols-4 gap-4" >
81- { [
82- { label : "Sprint Completion" , value : `${ completionPct } %` , icon : CheckCircle2 , color : "text-emerald-400" , sub : `${ completedTasks } /${ totalTasks } tasks done` } ,
83- { label : "Active Epics" , value : "4" , icon : Activity , color : "text-indigo-400" , sub : "2 at risk of delay" } ,
84- { label : "Cycle Time" , value : "2.4d" , icon : TrendingUp , color : "text-amber-400" , sub : "-0.5d improvement" } ,
85- { label : "Bottlenecks" , value : String ( status ?. availableTasks ?? 3 ) , icon : AlertTriangle , color : "text-rose-400" , sub : "Unclaimed tasks" } ,
86- ] . map ( ( stat , i ) => (
119+ { metrics . map ( ( stat , i ) => (
87120 < Card key = { i } className = "bg-zinc-900/50 border-zinc-800/50 shadow-sm" >
88121 < CardContent className = "p-5" >
89122 < div className = "flex justify-between items-start mb-2" >
@@ -104,7 +137,9 @@ export default function TrackerReportsViewBeta() {
104137 < div className = "flex items-center justify-between" >
105138 < div >
106139 < CardTitle className = "text-base text-zinc-100" > Velocity & Burndown</ CardTitle >
107- < CardDescription className = "text-xs text-zinc-500" > Tasks closed over the last 14 days</ CardDescription >
140+ < CardDescription className = "text-xs text-zinc-500" >
141+ Tasks closed over the last 14 days
142+ </ CardDescription >
108143 </ div >
109144 < TrendingUp className = "w-4 h-4 text-zinc-500" />
110145 </ div >
@@ -113,7 +148,15 @@ export default function TrackerReportsViewBeta() {
113148 < div className = "h-[200px] w-full flex items-end justify-between gap-2 px-2 pt-4 border-b border-zinc-800/50 relative" >
114149 { /* Ideal line overlay */ }
115150 < svg className = "absolute inset-0 h-full w-full" preserveAspectRatio = "none" >
116- < line x1 = "0" y1 = "20" x2 = "100%" y2 = "180" stroke = "rgba(99,102,241,0.3)" strokeWidth = "2" strokeDasharray = "4 4" />
151+ < line
152+ x1 = "0"
153+ y1 = "20"
154+ x2 = "100%"
155+ y2 = "180"
156+ stroke = "rgba(99,102,241,0.3)"
157+ strokeWidth = "2"
158+ strokeDasharray = "4 4"
159+ />
117160 </ svg >
118161 { /* CSS Bar Chart */ }
119162 { [ 40 , 60 , 30 , 80 , 90 , 45 , 65 , 100 , 75 , 50 ] . map ( ( h , i ) => (
@@ -159,10 +202,9 @@ export default function TrackerReportsViewBeta() {
159202 { member . tasks } / { member . capacity } tasks
160203 </ span >
161204 </ div >
162- { /* Custom progress bar to support dynamic colors */ }
163- < div className = "h-1.5 w-full bg-zinc-800 rounded-full overflow-hidden" >
205+ < div className = "relative h-1.5 w-full overflow-hidden rounded-full bg-zinc-800" >
164206 < div
165- className = { cn ( " h-full rounded-full transition-all" , isOver ? "bg-rose-500" : member . color ) }
207+ className = { ` h-full rounded-full transition-all ${ isOver ? "bg-rose-500" : member . color } ` }
166208 style = { { width : `${ Math . min ( pct , 100 ) } %` } }
167209 />
168210 </ div >
0 commit comments