@@ -13,6 +13,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@
1313import { Sheet , SheetContent , SheetHeader , SheetTitle , SheetTrigger } from "@/components/ui/sheet" ;
1414import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from "@/components/ui/select" ;
1515import { Tooltip as UITooltip , TooltipContent , TooltipTrigger } from "@/components/ui/tooltip" ;
16+ import { Dialog , DialogContent , DialogHeader , DialogTitle } from "@/components/ui/dialog" ;
1617import { DeploymentFooter } from "@/components/DeploymentFooter" ;
1718import {
1819 AggregatedData ,
@@ -21,6 +22,7 @@ import {
2122 DailyModelData ,
2223 PowerUserSummary ,
2324 PowerUserDailyBreakdown ,
25+ ExceededRequestDetail ,
2426 aggregateDataByDay ,
2527 parseCSV ,
2628 getModelUsageSummary ,
@@ -29,7 +31,9 @@ import {
2931 getPowerUserDailyData ,
3032 COPILOT_PLANS ,
3133 getPowerUserDailyBreakdown ,
32- getLastDateFromData
34+ getLastDateFromData ,
35+ getExceededRequestDetails ,
36+ getUserExceededRequestSummary
3337} from "@/lib/utils" ;
3438
3539function App ( ) {
@@ -46,6 +50,9 @@ function App() {
4650 const [ selectedPlan , setSelectedPlan ] = useState < string > ( COPILOT_PLANS . BUSINESS ) ; // Default to Business
4751 const [ isProcessing , setIsProcessing ] = useState ( false ) ;
4852 const [ visibleBars , setVisibleBars ] = useState ( [ 'compliantRequests' , 'exceedingRequests' ] ) ;
53+ const [ showExceededDetails , setShowExceededDetails ] = useState ( false ) ;
54+ const [ exceededDetailsData , setExceededDetailsData ] = useState < ExceededRequestDetail [ ] > ( [ ] ) ;
55+ const [ selectedDate , setSelectedDate ] = useState < string | null > ( null ) ;
4956 const fileInputRef = useRef < HTMLInputElement > ( null ) ;
5057
5158 const handlePowerUserSelect = useCallback ( ( userName : string | null ) => {
@@ -355,6 +362,19 @@ function App() {
355362 }
356363 } ;
357364
365+ const handleExceedingBarClick = ( barData ) => {
366+ if ( ! data || ! selectedPowerUser ) return ;
367+
368+ // Get the date from the clicked bar for display purposes
369+ const clickedDate = barData . date ;
370+ setSelectedDate ( clickedDate ) ;
371+
372+ // Get exceeded request details for the selected power user across ALL dates
373+ const exceededDetails = getExceededRequestDetails ( data , null , selectedPowerUser ) ;
374+ setExceededDetailsData ( exceededDetails ) ;
375+ setShowExceededDetails ( true ) ;
376+ } ;
377+
358378 const CustomLegend = ( { payload } ) => {
359379 // Define all possible bars
360380 const allPossibleBars = [ 'compliantRequests' , 'exceedingRequests' ] ;
@@ -608,6 +628,11 @@ function App() {
608628 - { selectedPowerUser }
609629 </ span >
610630 ) }
631+ { selectedPowerUser && (
632+ < div className = "text-xs text-muted-foreground font-normal mt-1" >
633+ 💡 Click on red bars to see all exceeded request details for this user
634+ </ div >
635+ ) }
611636 </ h3 >
612637 { selectedPowerUser && (
613638 < Button
@@ -730,6 +755,8 @@ function App() {
730755 name = "Exceeding Requests"
731756 stackId = "requests"
732757 fill = "#ef4444"
758+ onClick = { handleExceedingBarClick }
759+ style = { { cursor : selectedPowerUser ? 'pointer' : 'default' } }
733760 onMouseOver = { ( e ) => console . log ( 'Hovered Exceeding' , e ) }
734761 />
735762 ) }
@@ -1020,6 +1047,122 @@ function App() {
10201047 </ div >
10211048 </ div >
10221049 ) }
1050+
1051+ { /* Exceeded Request Details Dialog */ }
1052+ < Dialog open = { showExceededDetails } onOpenChange = { setShowExceededDetails } >
1053+ < DialogContent className = "w-[98vw] max-w-none max-h-[85vh] overflow-y-auto" style = { { width : '98vw' , maxWidth : 'none' } } >
1054+ < DialogHeader >
1055+ < DialogTitle >
1056+ Exceeded Request Details
1057+ { selectedPowerUser && ` - ${ selectedPowerUser } ` }
1058+ </ DialogTitle >
1059+ </ DialogHeader >
1060+
1061+ < div className = "space-y-6" >
1062+ { exceededDetailsData . length > 0 ? (
1063+ < >
1064+ { /* Summary Card */ }
1065+ { selectedPowerUser && data && (
1066+ < Card className = "p-4" >
1067+ < h3 className = "text-md font-medium mb-3" > User Summary</ h3 >
1068+ { ( ( ) => {
1069+ const userSummary = getUserExceededRequestSummary ( data , selectedPowerUser ) ;
1070+ return (
1071+ < div className = "grid grid-cols-2 md:grid-cols-4 gap-4" >
1072+ < div >
1073+ < div className = "text-sm text-muted-foreground" > Total Days with Exceeded Requests</ div >
1074+ < div className = "text-lg font-bold" > { userSummary . totalExceededDays } </ div >
1075+ </ div >
1076+ < div >
1077+ < div className = "text-sm text-muted-foreground" > Total Exceeded Requests</ div >
1078+ < div className = "text-lg font-bold" > { userSummary . totalExceededRequests . toLocaleString ( ) } </ div >
1079+ </ div >
1080+ < div >
1081+ < div className = "text-sm text-muted-foreground" > Average Exceeded per Day</ div >
1082+ < div className = "text-lg font-bold" > { userSummary . averageExceededPerDay . toFixed ( 1 ) } </ div >
1083+ </ div >
1084+ { userSummary . worstDay && (
1085+ < div >
1086+ < div className = "text-sm text-muted-foreground" > Worst Day</ div >
1087+ < div className = "text-sm font-bold" > { userSummary . worstDay . date } </ div >
1088+ < div className = "text-xs text-muted-foreground" >
1089+ { userSummary . worstDay . exceededRequests } exceeded of { userSummary . worstDay . totalRequests } total
1090+ </ div >
1091+ </ div >
1092+ ) }
1093+ </ div >
1094+ ) ;
1095+ } ) ( ) }
1096+ </ Card >
1097+ ) }
1098+
1099+ { /* Detailed Table */ }
1100+ < Card className = "p-4" >
1101+ < h3 className = "text-md font-medium mb-3" >
1102+ All Exceeded Request Days ({ exceededDetailsData . length } days)
1103+ </ h3 >
1104+ < div className = "overflow-auto" style = { { minWidth : '100%' } } >
1105+ < Table className = "min-w-full" >
1106+ < TableHeader >
1107+ < TableRow >
1108+ < TableHead className = "min-w-[120px]" > Date</ TableHead >
1109+ < TableHead className = "text-right min-w-[140px]" > Exceeded Requests</ TableHead >
1110+ < TableHead className = "text-right min-w-[160px]" > Total Requests (Day)</ TableHead >
1111+ < TableHead className = "text-right min-w-[150px]" > Compliant Requests</ TableHead >
1112+ < TableHead className = "min-w-[200px]" > Models Used</ TableHead >
1113+ < TableHead className = "min-w-[200px]" > Exceeding by Model</ TableHead >
1114+ </ TableRow >
1115+ </ TableHeader >
1116+ < TableBody >
1117+ { exceededDetailsData . map ( ( detail , index ) => (
1118+ < TableRow key = { `${ detail . user } -${ detail . date } -${ index } ` } >
1119+ < TableCell > { detail . date } </ TableCell >
1120+ < TableCell className = "text-right text-red-600 font-medium" >
1121+ { detail . exceededRequests . toLocaleString ( ) }
1122+ </ TableCell >
1123+ < TableCell className = "text-right" >
1124+ { detail . totalRequestsOnDay . toLocaleString ( ) }
1125+ </ TableCell >
1126+ < TableCell className = "text-right text-green-600" >
1127+ { detail . compliantRequestsOnDay . toLocaleString ( ) }
1128+ </ TableCell >
1129+ < TableCell >
1130+ < div className = "flex flex-wrap gap-1" >
1131+ { detail . modelsUsed . map ( ( model , idx ) => (
1132+ < span
1133+ key = { idx }
1134+ className = "inline-block bg-secondary px-2 py-1 rounded text-xs"
1135+ >
1136+ { model }
1137+ </ span >
1138+ ) ) }
1139+ </ div >
1140+ </ TableCell >
1141+ < TableCell >
1142+ < div className = "space-y-1" >
1143+ { Object . entries ( detail . exceedingByModel ) . map ( ( [ model , requests ] ) => (
1144+ < div key = { model } className = "text-xs" >
1145+ < span className = "font-medium" > { model } :</ span > { requests . toLocaleString ( ) }
1146+ </ div >
1147+ ) ) }
1148+ </ div >
1149+ </ TableCell >
1150+ </ TableRow >
1151+ ) ) }
1152+ </ TableBody >
1153+ </ Table >
1154+ </ div >
1155+ </ Card >
1156+ </ >
1157+ ) : (
1158+ < Card className = "p-8 text-center" >
1159+ < p className = "text-muted-foreground" > No exceeded request details found for the selected criteria.</ p >
1160+ </ Card >
1161+ ) }
1162+ </ div >
1163+ </ DialogContent >
1164+ </ Dialog >
1165+
10231166 < Toaster position = "top-right" />
10241167 < DeploymentFooter />
10251168 </ div >
0 commit comments