@@ -22,6 +22,9 @@ import {
2222import Image from "next/image" ;
2323import { getAssetPath } from "@/lib/utils" ;
2424import type { User } from '@vector-institute/aieng-auth-core' ;
25+ import MeaningfulnessChart from '@/components/MeaningfulnessChart' ;
26+ import CodeConfigChart from '@/components/CodeConfigChart' ;
27+ import GeographicChart from '@/components/GeographicChart' ;
2528
2629// Types
2730interface RepoSnapshot {
@@ -108,6 +111,28 @@ interface PyPIMetrics {
108111 description ?: string ;
109112}
110113
114+ interface GeographicData {
115+ country : string ;
116+ count : number ;
117+ }
118+
119+ interface ForkSummary {
120+ total_forks : number ;
121+ active_forks : number ;
122+ meaningful_forks : number ;
123+ not_meaningful_forks : number ;
124+ meaningful_rate : number ;
125+ total_files_changed : number ;
126+ code_files : number ;
127+ config_files : number ;
128+ }
129+
130+ interface ForkAnalysis {
131+ summary : ForkSummary ;
132+ geographic_distribution : GeographicData [ ] ;
133+ last_updated : string ;
134+ }
135+
111136type SortColumn = "name" | "language" | "stars" | "forks" | "unique_visitors" | "unique_cloners" ;
112137type PyPISortColumn = "name" | "downloads_last_day" | "downloads_last_week" | "downloads_last_month" | "version" ;
113138type SortDirection = "asc" | "desc" ;
@@ -122,6 +147,7 @@ export default function AnalyticsPage({ user }: AnalyticsPageProps) {
122147 // Load data dynamically to ensure fresh data during development
123148 const [ historicalData , setHistoricalData ] = useState < HistoricalData | null > ( null ) ;
124149 const [ pypiData , setPypiData ] = useState < PyPIHistoricalData | null > ( null ) ;
150+ const [ forkData , setForkData ] = useState < ForkAnalysis | null > ( null ) ;
125151 const [ isLoading , setIsLoading ] = useState ( true ) ;
126152 const [ repoDescriptions , setRepoDescriptions ] = useState < Record < string , string > > ( { } ) ;
127153 const [ sortColumn , setSortColumn ] = useState < SortColumn > ( "unique_cloners" ) ;
@@ -182,6 +208,17 @@ export default function AnalyticsPage({ user }: AnalyticsPageProps) {
182208 } catch ( error ) {
183209 console . warn ( "No repository descriptions found:" , error ) ;
184210 }
211+
212+ // Load fork analysis data
213+ try {
214+ const forkResponse = await fetch ( `${ basePath } /data/fork_metrics.json` ) ;
215+ if ( forkResponse . ok ) {
216+ const forkMetricsData = await forkResponse . json ( ) ;
217+ setForkData ( forkMetricsData ) ;
218+ }
219+ } catch ( error ) {
220+ console . warn ( "No fork metrics data found:" , error ) ;
221+ }
185222 } catch ( error ) {
186223 console . warn ( "No historical metrics data found:" , error ) ;
187224 setHistoricalData ( null ) ;
@@ -648,6 +685,195 @@ export default function AnalyticsPage({ user }: AnalyticsPageProps) {
648685 </ div >
649686 </ section >
650687
688+ { /* Active Fork Analysis */ }
689+ < section className = "mb-12" >
690+ < h2 className = "text-2xl font-bold text-gray-900 dark:text-white mb-6 flex items-center gap-2" >
691+ < GitFork className = "w-6 h-6 text-vector-magenta" />
692+ Active Fork Analysis
693+ </ h2 >
694+ < div className = "grid grid-cols-1 lg:grid-cols-3 gap-6" >
695+ { /* Column 1 - Meaningfulness Distribution */ }
696+ < div className = "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6 shadow-sm" >
697+ < h3 className = "text-lg font-semibold text-gray-900 dark:text-white mb-4" >
698+ Meaningfulness Distribution
699+ </ h3 >
700+ < div className = "mt-4" >
701+ < MeaningfulnessChart
702+ meaningful = { forkData ?. summary . meaningful_forks || 16 }
703+ notMeaningful = { forkData ?. summary . not_meaningful_forks || 22 }
704+ />
705+ </ div >
706+ < div className = "mt-6 pt-4 border-t border-gray-200 dark:border-gray-700" >
707+ < div className = "grid grid-cols-2 gap-4 text-center" >
708+ < div >
709+ < div className = "text-2xl font-bold text-green-600 dark:text-green-400" >
710+ { forkData ?. summary . meaningful_forks || 16 }
711+ </ div >
712+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1" > Meaningful</ div >
713+ < div className = "text-xs text-gray-500 dark:text-gray-500" >
714+ ({ forkData ?. summary . meaningful_rate || 42.1 } %)
715+ </ div >
716+ </ div >
717+ < div >
718+ < div className = "text-2xl font-bold text-red-600 dark:text-red-400" >
719+ { forkData ?. summary . not_meaningful_forks || 22 }
720+ </ div >
721+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1" > Not Meaningful</ div >
722+ < div className = "text-xs text-gray-500 dark:text-gray-500" >
723+ ({ forkData ? ( 100 - forkData . summary . meaningful_rate ) . toFixed ( 1 ) : 57.9 } %)
724+ </ div >
725+ </ div >
726+ </ div >
727+ < div className = "mt-4 text-center" >
728+ < div className = "text-sm font-medium text-gray-700 dark:text-gray-300" >
729+ Active Forks Analyzed: < span className = "font-bold text-gray-900 dark:text-white" >
730+ { forkData ?. summary . active_forks || 38 }
731+ </ span >
732+ </ div >
733+ </ div >
734+ </ div >
735+ </ div >
736+
737+ { /* Column 2 - Code vs Configuration & Geographic Distribution */ }
738+ < div className = "space-y-6" >
739+ { /* Code vs Configuration */ }
740+ < div className = "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6 shadow-sm" >
741+ < h3 className = "text-lg font-semibold text-gray-900 dark:text-white mb-4" >
742+ Code vs Configuration
743+ </ h3 >
744+ < div className = "mt-4" >
745+ < CodeConfigChart
746+ codeFiles = { forkData ?. summary . code_files || 182 }
747+ configFiles = { forkData ?. summary . config_files || 70 }
748+ />
749+ </ div >
750+ < div className = "mt-6 pt-4 border-t border-gray-200 dark:border-gray-700" >
751+ < div className = "grid grid-cols-2 gap-4 text-center" >
752+ < div >
753+ < div className = "text-2xl font-bold text-indigo-600 dark:text-indigo-400" >
754+ { forkData ?. summary . code_files || 182 }
755+ </ div >
756+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1" > Code Files</ div >
757+ < div className = "text-xs text-gray-500 dark:text-gray-500" >
758+ ({ forkData ? ( ( forkData . summary . code_files / ( forkData . summary . code_files + forkData . summary . config_files ) ) * 100 ) . toFixed ( 1 ) : 72.2 } %)
759+ </ div >
760+ </ div >
761+ < div >
762+ < div className = "text-2xl font-bold text-amber-600 dark:text-amber-400" >
763+ { forkData ?. summary . config_files || 70 }
764+ </ div >
765+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1" > Config Files</ div >
766+ < div className = "text-xs text-gray-500 dark:text-gray-500" >
767+ ({ forkData ? ( ( forkData . summary . config_files / ( forkData . summary . code_files + forkData . summary . config_files ) ) * 100 ) . toFixed ( 1 ) : 27.8 } %)
768+ </ div >
769+ </ div >
770+ </ div >
771+ < div className = "mt-4 text-center" >
772+ < div className = "text-sm font-medium text-gray-700 dark:text-gray-300" >
773+ Total Files Changed: < span className = "font-bold text-gray-900 dark:text-white" >
774+ { forkData ? ( forkData . summary . code_files + forkData . summary . config_files ) : 252 }
775+ </ span >
776+ </ div >
777+ </ div >
778+ </ div >
779+ </ div >
780+
781+ { /* Geographic Distribution */ }
782+ < div className = "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6 shadow-sm" >
783+ < h3 className = "text-lg font-semibold text-gray-900 dark:text-white mb-4" >
784+ Geographic Distribution
785+ </ h3 >
786+ < div className = "mt-4" >
787+ { forkData ?. geographic_distribution && forkData . geographic_distribution . length > 0 ? (
788+ < GeographicChart data = { forkData . geographic_distribution } />
789+ ) : (
790+ < div className = "text-center py-8 text-gray-500 dark:text-gray-400" >
791+ No geographic data available
792+ </ div >
793+ ) }
794+ </ div >
795+ < div className = "mt-6 pt-4 border-t border-gray-200 dark:border-gray-700" >
796+ < div className = "text-center" >
797+ < div className = "text-sm font-medium text-gray-700 dark:text-gray-300" >
798+ Countries Represented: < span className = "font-bold text-gray-900 dark:text-white" >
799+ { forkData ?. geographic_distribution . length || 7 }
800+ </ span >
801+ </ div >
802+ </ div >
803+ </ div >
804+ </ div >
805+ </ div >
806+
807+ { /* Column 3 - Key Statistics */ }
808+ < div className = "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6 shadow-sm" >
809+ < h3 className = "text-lg font-semibold text-gray-900 dark:text-white mb-4" >
810+ Key Statistics
811+ </ h3 >
812+ < div className = "grid grid-cols-2 gap-4" >
813+ { /* Active Forks */ }
814+ < div className = "bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800 rounded-lg p-4 text-center" >
815+ < div className = "text-2xl font-bold text-indigo-600 dark:text-indigo-400" >
816+ { forkData ?. summary . active_forks || 38 }
817+ </ div >
818+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1 uppercase tracking-wide" > Active Forks</ div >
819+ </ div >
820+
821+ { /* Meaningful */ }
822+ < div className = "bg-gradient-to-br from-green-50 to-green-100 dark:from-green-900/20 dark:to-green-800/20 rounded-lg p-4 text-center" >
823+ < div className = "text-2xl font-bold text-green-600 dark:text-green-400" >
824+ { forkData ?. summary . meaningful_forks || 16 }
825+ </ div >
826+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1 uppercase tracking-wide" > Meaningful</ div >
827+ </ div >
828+
829+ { /* Not Meaningful */ }
830+ < div className = "bg-gradient-to-br from-red-50 to-red-100 dark:from-red-900/20 dark:to-red-800/20 rounded-lg p-4 text-center" >
831+ < div className = "text-2xl font-bold text-red-600 dark:text-red-400" >
832+ { forkData ?. summary . not_meaningful_forks || 22 }
833+ </ div >
834+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1 uppercase tracking-wide" > Not Meaningful</ div >
835+ </ div >
836+
837+ { /* Meaningful Rate */ }
838+ < div className = "bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800 rounded-lg p-4 text-center" >
839+ < div className = "text-2xl font-bold text-indigo-600 dark:text-indigo-400" >
840+ { forkData ?. summary . meaningful_rate || 42.1 } %
841+ </ div >
842+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1 uppercase tracking-wide" > Meaningful Rate</ div >
843+ </ div >
844+
845+ { /* New Functions */ }
846+ < div className = "bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800 rounded-lg p-4 text-center" >
847+ < div className = "text-2xl font-bold text-indigo-600 dark:text-indigo-400" > 0</ div >
848+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1 uppercase tracking-wide" > New Functions</ div >
849+ </ div >
850+
851+ { /* New Classes */ }
852+ < div className = "bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800 rounded-lg p-4 text-center" >
853+ < div className = "text-2xl font-bold text-indigo-600 dark:text-indigo-400" > 0</ div >
854+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1 uppercase tracking-wide" > New Classes</ div >
855+ </ div >
856+
857+ { /* Files Changed */ }
858+ < div className = "bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800 rounded-lg p-4 text-center" >
859+ < div className = "text-2xl font-bold text-indigo-600 dark:text-indigo-400" >
860+ { forkData ?. summary . total_files_changed || 1267 }
861+ </ div >
862+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1 uppercase tracking-wide" > Files Changed</ div >
863+ </ div >
864+
865+ { /* Code Files */ }
866+ < div className = "bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800 rounded-lg p-4 text-center" >
867+ < div className = "text-2xl font-bold text-indigo-600 dark:text-indigo-400" >
868+ { forkData ?. summary . code_files || 182 }
869+ </ div >
870+ < div className = "text-xs text-gray-600 dark:text-gray-400 mt-1 uppercase tracking-wide" > Code Files</ div >
871+ </ div >
872+ </ div >
873+ </ div >
874+ </ div >
875+ </ section >
876+
651877 { /* All Repositories Table */ }
652878 < section >
653879 < h2 className = "text-2xl font-bold text-gray-900 dark:text-white mb-6" >
0 commit comments