@@ -9,10 +9,12 @@ import { OrganizationsView } from './views/OrganizationsView'
99import { ModelsView } from './views/ModelsView'
1010import { ReportGuideView } from './views/ReportGuideView'
1111import { FaqView } from './views/FaqView'
12+ import { ProductsView } from './views/ProductsView'
1213import { QuickStatsAggregator , type QuickStatsResult } from './pipeline/aggregators/quickStatsAggregator'
1314import { ReportContextAggregator , type ReportContextResult } from './pipeline/aggregators/reportContextAggregator'
1415import { DailyUsageAggregator , type DailyUsageData } from './pipeline/aggregators/dailyUsageAggregator'
1516import { ModelUsageAggregator , type ModelUsageResult } from './pipeline/aggregators/modelUsageAggregator'
17+ import { ProductUsageAggregator , type ProductUsageResult } from './pipeline/aggregators/productUsageAggregator'
1618import { CostCenterAggregator , type CostCenterResult } from './pipeline/aggregators/costCenterAggregator'
1719import { OrganizationAggregator , type OrganizationResult } from './pipeline/aggregators/organizationAggregator'
1820import { UserUsageAggregator , type UserUsageResult } from './pipeline/aggregators/userUsageAggregator'
@@ -55,9 +57,10 @@ function App() {
5557 const [ fileName , setFileName ] = useState < string | null > ( null )
5658 const [ dragActive , setDragActive ] = useState ( false )
5759 const [ dailyUsageData , setDailyUsageData ] = useState < DailyUsageData [ ] > ( [ ] )
58- const [ activeView , setActiveView ] = useState < 'overview' | 'users' | 'userDetails' | 'costCenters' | 'orgs' | 'models' | 'guide' | 'faq' > ( 'overview' )
60+ const [ activeView , setActiveView ] = useState < 'overview' | 'users' | 'userDetails' | 'costCenters' | 'orgs' | 'models' | 'products' | ' guide' | 'faq' > ( 'overview' )
5961 const [ userUsage , setUserUsage ] = useState < UserUsageResult | null > ( null )
6062 const [ modelUsage , setModelUsage ] = useState < ModelUsageResult | null > ( null )
63+ const [ productUsage , setProductUsage ] = useState < ProductUsageResult | null > ( null )
6164 const [ selectedUsername , setSelectedUsername ] = useState < string > ( '' )
6265 const [ costCenters , setCostCenters ] = useState < CostCenterResult | null > ( null )
6366 const [ orgs , setOrgs ] = useState < OrganizationResult | null > ( null )
@@ -71,6 +74,7 @@ function App() {
7174 setDailyUsageData ( [ ] )
7275 setUserUsage ( null )
7376 setModelUsage ( null )
77+ setProductUsage ( null )
7478 setSelectedUsername ( '' )
7579 setCostCenters ( null )
7680 setOrgs ( null )
@@ -82,6 +86,7 @@ function App() {
8286 const contextAggregator = new ReportContextAggregator ( )
8387 const dailyAggregator = new DailyUsageAggregator ( )
8488 const modelAggregator = new ModelUsageAggregator ( )
89+ const productAggregator = new ProductUsageAggregator ( )
8590 const costCenterAggregator = new CostCenterAggregator ( )
8691 const orgAggregator = new OrganizationAggregator ( )
8792 const userAggregator = new UserUsageAggregator ( )
@@ -91,6 +96,7 @@ function App() {
9196 contextAggregator ,
9297 dailyAggregator ,
9398 modelAggregator ,
99+ productAggregator ,
94100 costCenterAggregator ,
95101 orgAggregator ,
96102 userAggregator ,
@@ -102,6 +108,7 @@ function App() {
102108
103109 const nextModelUsage = modelAggregator . result ( )
104110 setModelUsage ( nextModelUsage )
111+ setProductUsage ( productAggregator . result ( ) )
105112
106113 setCostCenters ( costCenterAggregator . result ( ) )
107114 setOrgs ( orgAggregator . result ( ) )
@@ -292,6 +299,17 @@ function App() {
292299 </ button >
293300 ) }
294301
302+ < button
303+ type = "button"
304+ className = { `sidebar__item ${ activeView === 'products' ? 'sidebar__item--active' : '' } ` }
305+ onClick = { ( ) => setActiveView ( 'products' ) }
306+ >
307+ < svg className = "sidebar__icon" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" strokeWidth = "1.5" strokeLinecap = "round" strokeLinejoin = "round" aria-hidden = "true" focusable = "false" >
308+ < path d = "M3 9h18M3 15h18M9 3v18M15 3v18" />
309+ </ svg >
310+ < span className = "sidebar__label" > Products</ span >
311+ </ button >
312+
295313 { orgs && orgs . organizations . length > 0 && (
296314 < button
297315 type = "button"
@@ -321,6 +339,8 @@ function App() {
321339 </ button >
322340 ) }
323341
342+ < hr className = "sidebar__divider" />
343+
324344 < button
325345 type = "button"
326346 className = { `sidebar__item ${ activeView === 'guide' ? 'sidebar__item--active' : '' } ` }
@@ -554,6 +574,10 @@ function App() {
554574 < div className = "view-content" >
555575 < CostCentersView data = { costCenters ?? { costCenters : [ ] } } rangeStart = { rangeStart } />
556576 </ div >
577+ ) : activeView === 'products' ? (
578+ < div className = "view-content" >
579+ < ProductsView data = { productUsage ?? { products : [ ] } } />
580+ </ div >
557581 ) : activeView === 'guide' ? (
558582 < div className = "view-content" >
559583 < ReportGuideView />
0 commit comments