11import { PageHeader } from '@vibe/shared' ;
22import { Badge , Card , CardGrid } from '@vibe/ui' ;
3- import { GitBranch , Star , Package , Users , ExternalLink } from 'lucide-react' ;
3+ import { GitBranch , Star , Package , Users , ExternalLink , Clock , TrendingUp } from 'lucide-react' ;
4+ import { useState } from 'react' ;
45import dependentsData from '../../../../data/dependents.json' ;
56import { PageContainer } from '../components/layout/PageContainer' ;
67
@@ -9,42 +10,65 @@ interface Dependent {
910 stars : number ;
1011}
1112
13+ interface DependentsCollection {
14+ topDependents : Dependent [ ] ;
15+ latestDependents : Dependent [ ] ;
16+ }
17+
1218interface DependentsData {
1319 [ repo : string ] : {
14- [ pkg : string ] : Dependent [ ] ;
20+ [ pkg : string ] : DependentsCollection | Dependent [ ] ; // Support both old and new format
1521 } ;
1622}
1723
1824interface PackageData {
1925 repo : string ;
2026 package : string ;
21- dependents : Dependent [ ] ;
27+ topDependents : Dependent [ ] ;
28+ latestDependents : Dependent [ ] ;
2229}
2330
2431function DependentsPage ( ) {
32+ const [ viewMode , setViewMode ] = useState < 'top' | 'latest' > ( 'top' ) ;
2533 const data = dependentsData as DependentsData ;
2634
2735 // Flatten the data structure to get all packages
2836 const allPackages : PackageData [ ] = [ ] ;
2937 Object . entries ( data ) . forEach ( ( [ repo , packages ] ) => {
30- Object . entries ( packages ) . forEach ( ( [ pkg , dependents ] ) => {
31- allPackages . push ( {
32- repo,
33- package : pkg ,
34- dependents
35- } ) ;
38+ Object . entries ( packages ) . forEach ( ( [ pkg , deps ] ) => {
39+ // Handle both old format (array) and new format (object with topDependents/latestDependents)
40+ if ( Array . isArray ( deps ) ) {
41+ // Old format - treat as topDependents
42+ allPackages . push ( {
43+ repo,
44+ package : pkg ,
45+ topDependents : deps ,
46+ latestDependents : [ ]
47+ } ) ;
48+ } else {
49+ // New format
50+ allPackages . push ( {
51+ repo,
52+ package : pkg ,
53+ topDependents : deps . topDependents || [ ] ,
54+ latestDependents : deps . latestDependents || [ ]
55+ } ) ;
56+ }
3657 } ) ;
3758 } ) ;
3859
39- // Calculate stats
60+ // Calculate stats based on current view mode
4061 const totalRepos = Object . keys ( data ) . length ;
4162 const totalPackages = allPackages . length ;
42- const totalDependents = allPackages . reduce ( ( sum , pkg ) => sum + pkg . dependents . length , 0 ) ;
4363
44- // Get top dependent across all packages
64+ const currentDependents = viewMode === 'top' ? 'topDependents' : 'latestDependents' ;
65+ const totalDependents = allPackages . reduce ( ( sum , pkg ) => sum + pkg [ currentDependents ] . length , 0 ) ;
66+
67+ // Get top dependent across all packages for current view
4568 const allDependents : Array < Dependent & { package : string ; repo : string } > = [ ] ;
46- allPackages . forEach ( ( { repo, package : pkg , dependents } ) => {
47- dependents . forEach ( dep => {
69+ allPackages . forEach ( ( { repo, package : pkg , topDependents, latestDependents } ) => {
70+ const deps = viewMode === 'top' ? topDependents : latestDependents ;
71+ deps . forEach ( dep => {
4872 allDependents . push ( { ...dep , package : pkg , repo } ) ;
4973 } ) ;
5074 } ) ;
@@ -55,11 +79,41 @@ function DependentsPage() {
5579 < PageHeader
5680 icon = { < GitBranch className = 'text-purple-600 dark:text-purple-400' /> }
5781 title = 'GitHub Dependents'
58- subtitle = ' Top repositories and packages that depend on our projects'
82+ subtitle = { viewMode === 'top' ? ' Top repositories by stars that depend on our projects' : 'Most recent repositories that depend on our projects' }
5983 action = {
60- < Badge variant = 'info' size = 'md' >
61- { totalDependents } Total Dependents
62- </ Badge >
84+ < div className = 'flex items-center gap-4' >
85+ < div className = 'flex rounded-lg bg-slate-100 dark:bg-slate-800 p-1' >
86+ < button
87+ onClick = { ( ) => setViewMode ( 'top' ) }
88+ className = { `px-3 py-1 rounded-md text-sm font-medium transition-all ${
89+ viewMode === 'top'
90+ ? 'bg-white dark:bg-slate-700 text-purple-600 dark:text-purple-400 shadow-sm'
91+ : 'text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-200'
92+ } `}
93+ >
94+ < span className = 'flex items-center gap-1' >
95+ < TrendingUp className = 'w-3.5 h-3.5' />
96+ Top by Stars
97+ </ span >
98+ </ button >
99+ < button
100+ onClick = { ( ) => setViewMode ( 'latest' ) }
101+ className = { `px-3 py-1 rounded-md text-sm font-medium transition-all ${
102+ viewMode === 'latest'
103+ ? 'bg-white dark:bg-slate-700 text-purple-600 dark:text-purple-400 shadow-sm'
104+ : 'text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-200'
105+ } `}
106+ >
107+ < span className = 'flex items-center gap-1' >
108+ < Clock className = 'w-3.5 h-3.5' />
109+ Most Recent
110+ </ span >
111+ </ button >
112+ </ div >
113+ < Badge variant = 'info' size = 'md' >
114+ { totalDependents } { viewMode === 'top' ? 'Top' : 'Latest' } Dependents
115+ </ Badge >
116+ </ div >
63117 }
64118 />
65119
@@ -110,7 +164,9 @@ function DependentsPage() {
110164
111165 { /* All Packages in 2 Column Grid */ }
112166 < div className = 'grid grid-cols-1 lg:grid-cols-2 gap-6' >
113- { allPackages . map ( ( { repo, package : pkg , dependents } ) => (
167+ { allPackages . map ( ( { repo, package : pkg , topDependents, latestDependents } ) => {
168+ const dependents = viewMode === 'top' ? topDependents : latestDependents ;
169+ return (
114170 < Card key = { `${ repo } /${ pkg } ` } className = 'p-6' >
115171 < div className = 'mb-4 flex items-center justify-between' >
116172 < div className = 'flex items-center gap-2' >
@@ -173,7 +229,8 @@ function DependentsPage() {
173229 </ table >
174230 </ div >
175231 </ Card >
176- ) ) }
232+ ) ;
233+ } ) }
177234 </ div >
178235 </ PageContainer >
179236 ) ;
0 commit comments