1- import { useState , useEffect , useCallback } from "react" ;
2- import {
3- useAnalytics ,
4- AnalyticsSummary ,
5- ArticleUsage ,
6- LowRatingAnalysis ,
7- ResponseQualityDrilldownExamples ,
8- ResponseQualitySummary ,
9- } from "../../hooks/useAnalytics" ;
10- import { useInsightsOps } from "../../hooks/useInsightsOps" ;
1+ import { useState , useEffect } from "react" ;
112import type { ResponseQualityThresholds } from "../../features/analytics/qualityThresholds" ;
123import {
134 readCurrentThresholds ,
145 subscribeToQualityThresholds ,
156} from "./qualityThresholdsState" ;
16- import type { KbGapCandidate } from "../../types/insights" ;
177import { ArticleDetailPanel } from "./ArticleDetailPanel" ;
188import { PilotDiagnosticsSection } from "./PilotDiagnosticsSection" ;
199import { RatingDistribution } from "./RatingDistribution" ;
2010import { KbUsageTable } from "./KbUsageTable" ;
2111import { ResponseQualityPanel } from "./ResponseQualityPanel" ;
12+ import { useAnalyticsLoader , type AnalyticsPeriod } from "./useAnalyticsLoader" ;
2213import "./AnalyticsTab.css" ;
2314
24- type Period = 7 | 30 | 90 | null ; // null = all time
2515type AnalyticsSection = "overview" | "pilot" ;
2616
2717interface AnalyticsTabProps {
2818 initialSection ?: AnalyticsSection ;
2919}
3020
31- const PERIODS : { label : string ; value : Period } [ ] = [
21+ const PERIODS : { label : string ; value : AnalyticsPeriod } [ ] = [
3222 { label : "7 days" , value : 7 } ,
3323 { label : "30 days" , value : 30 } ,
3424 { label : "90 days" , value : 90 } ,
@@ -39,30 +29,22 @@ export function AnalyticsTab({
3929 initialSection = "overview" ,
4030} : AnalyticsTabProps ) {
4131 const {
42- getSummary,
43- getKbUsage,
44- getLowRatingAnalysis,
45- getResponseQualitySummary,
46- getResponseQualityDrilldownExamples,
47- } = useAnalytics ( ) ;
48- const { getKbGapCandidates, updateKbGapStatus } = useInsightsOps ( ) ;
32+ summary,
33+ qualitySummary,
34+ qualityDrilldown,
35+ kbUsage,
36+ lowRatingData,
37+ gapCandidates,
38+ loading,
39+ error,
40+ period,
41+ setPeriod,
42+ updateGapStatus,
43+ } = useAnalyticsLoader ( ) ;
4944 const [ activeSection , setActiveSection ] =
5045 useState < AnalyticsSection > ( initialSection ) ;
51- const [ period , setPeriod ] = useState < Period > ( 30 ) ;
52- const [ summary , setSummary ] = useState < AnalyticsSummary | null > ( null ) ;
53- const [ qualitySummary , setQualitySummary ] =
54- useState < ResponseQualitySummary | null > ( null ) ;
55- const [ qualityDrilldown , setQualityDrilldown ] =
56- useState < ResponseQualityDrilldownExamples | null > ( null ) ;
5746 const [ qualityThresholds , setQualityThresholds ] =
5847 useState < ResponseQualityThresholds > ( ( ) => readCurrentThresholds ( ) ) ;
59- const [ kbUsage , setKbUsage ] = useState < ArticleUsage [ ] > ( [ ] ) ;
60- const [ lowRatingData , setLowRatingData ] = useState < LowRatingAnalysis | null > (
61- null ,
62- ) ;
63- const [ gapCandidates , setGapCandidates ] = useState < KbGapCandidate [ ] > ( [ ] ) ;
64- const [ loading , setLoading ] = useState ( true ) ;
65- const [ error , setError ] = useState < string | null > ( null ) ;
6648 const [ selectedArticleId , setSelectedArticleId ] = useState < string | null > (
6749 null ,
6850 ) ;
@@ -71,60 +53,6 @@ export function AnalyticsTab({
7153 setActiveSection ( initialSection ) ;
7254 } , [ initialSection ] ) ;
7355
74- const loadData = useCallback ( async ( ) => {
75- setLoading ( true ) ;
76- setError ( null ) ;
77- try {
78- const [
79- summaryData ,
80- kbData ,
81- lowRating ,
82- qualityData ,
83- qualityDrilldownData ,
84- ] = await Promise . all ( [
85- getSummary ( period ?? undefined ) ,
86- getKbUsage ( period ?? undefined ) ,
87- getLowRatingAnalysis ( period ?? undefined ) . catch ( ( ) => null ) ,
88- getResponseQualitySummary ( period ?? undefined ) . catch ( ( ) => null ) ,
89- getResponseQualityDrilldownExamples ( period ?? undefined , 6 ) . catch (
90- ( ) => null ,
91- ) ,
92- ] ) ;
93- const gaps = await getKbGapCandidates ( 12 , "open" ) . catch ( ( ) => [ ] ) ;
94- setSummary ( summaryData ) ;
95- setQualitySummary ( qualityData ) ;
96- setQualityDrilldown ( qualityDrilldownData ) ;
97- setKbUsage ( kbData ) ;
98- setLowRatingData ( lowRating ) ;
99- setGapCandidates ( gaps ) ;
100- } catch ( err ) {
101- console . error ( "Failed to load analytics:" , err ) ;
102- setError ( typeof err === "string" ? err : "Failed to load analytics data" ) ;
103- } finally {
104- setLoading ( false ) ;
105- }
106- } , [
107- period ,
108- getSummary ,
109- getKbUsage ,
110- getLowRatingAnalysis ,
111- getResponseQualitySummary ,
112- getResponseQualityDrilldownExamples ,
113- getKbGapCandidates ,
114- ] ) ;
115-
116- const handleGapStatus = useCallback (
117- async ( id : string , status : "accepted" | "resolved" | "ignored" ) => {
118- await updateKbGapStatus ( id , status ) ;
119- setGapCandidates ( ( prev ) => prev . filter ( ( g ) => g . id !== id ) ) ;
120- } ,
121- [ updateKbGapStatus ] ,
122- ) ;
123-
124- useEffect ( ( ) => {
125- loadData ( ) ;
126- } , [ loadData ] ) ;
127-
12856 useEffect ( ( ) => {
12957 setQualityThresholds ( readCurrentThresholds ( ) ) ;
13058 return subscribeToQualityThresholds ( setQualityThresholds ) ;
@@ -339,19 +267,19 @@ export function AnalyticsTab({
339267 < div className = "kb-gap-actions" >
340268 < button
341269 className = "kb-gap-btn"
342- onClick = { ( ) => handleGapStatus ( gap . id , "accepted" ) }
270+ onClick = { ( ) => updateGapStatus ( gap . id , "accepted" ) }
343271 >
344272 Accept
345273 </ button >
346274 < button
347275 className = "kb-gap-btn"
348- onClick = { ( ) => handleGapStatus ( gap . id , "resolved" ) }
276+ onClick = { ( ) => updateGapStatus ( gap . id , "resolved" ) }
349277 >
350278 Resolve
351279 </ button >
352280 < button
353281 className = "kb-gap-btn kb-gap-btn-muted"
354- onClick = { ( ) => handleGapStatus ( gap . id , "ignored" ) }
282+ onClick = { ( ) => updateGapStatus ( gap . id , "ignored" ) }
355283 >
356284 Ignore
357285 </ button >
0 commit comments