@@ -18,6 +18,7 @@ import {
1818 AlertDialogHeader ,
1919 AlertDialogTitle ,
2020} from "@/components/ui/alert-dialog" ;
21+
2122const DiscordIcon = ( { className = "" } ) => (
2223 < svg
2324 role = "img"
@@ -32,21 +33,88 @@ const DiscordIcon = ({ className = "" }) => (
3233 </ svg >
3334) ;
3435
36+ interface Language {
37+ [ key : string ] : number ;
38+ }
39+
3540interface Project {
3641 name : string ;
3742 description : string ;
3843 stars : string ;
3944 forks : string ;
4045 tags : string [ ] ;
4146 url : string ;
42- color : string ;
47+ color ?: string ;
48+ languages : Language ;
4349}
4450
4551interface SubmissionStatus {
4652 status : string ;
4753 message : string ;
4854}
4955
56+ const languageColors : { [ key : string ] : string } = {
57+ Python : '#3572A5' ,
58+ TypeScript : '#2b7489' ,
59+ JavaScript : '#f1e05a' ,
60+ Shell : '#89e051' ,
61+ HTML : '#e34c26' ,
62+ CSS : '#563d7c' ,
63+ Dockerfile : '#384d54' ,
64+ Ruby : '#701516' ,
65+ PowerShell : '#012456' ,
66+ AutoHotkey : '#6594b9' ,
67+ Svelte : '#ff3e00' ,
68+ SCSS : '#c6538c' ,
69+ Scheme : '#1e4aec' ,
70+ "Inno Setup" : '#264b99' ,
71+ Batchfile : '#C1F12E' ,
72+ Makefile : '#427819' ,
73+ Jinja : '#a52a22'
74+ } ;
75+
76+ const LanguageBar = ( { languages } : { languages : Language } ) => {
77+ const totalBytes = Object . values ( languages ) . reduce ( ( sum , value ) => sum + value , 0 ) ;
78+
79+ const percentages = Object . entries ( languages ) . map ( ( [ name , bytes ] ) => ( {
80+ name,
81+ percentage : ( bytes / totalBytes ) * 100
82+ } ) ) . sort ( ( a , b ) => b . percentage - a . percentage ) ;
83+
84+ return (
85+ < div className = "space-y-4" >
86+ < h2 className = "text-lg font-semibold text-white" > Languages</ h2 >
87+
88+ < div className = "h-2 w-full flex rounded-full overflow-hidden" >
89+ { percentages . map ( ( { name, percentage } ) => (
90+ < div
91+ key = { name }
92+ style = { {
93+ width : `${ percentage } %` ,
94+ backgroundColor : languageColors [ name ] || '#ededed'
95+ } }
96+ />
97+ ) ) }
98+ </ div >
99+
100+ < div className = "flex flex-wrap gap-4" >
101+ { percentages
102+ . filter ( ( { percentage } ) => percentage >= 2 )
103+ . map ( ( { name, percentage } ) => (
104+ < div key = { name } className = "flex items-center gap-2" >
105+ < span
106+ className = "w-3 h-3 rounded-full"
107+ style = { { backgroundColor : languageColors [ name ] || '#ededed' } }
108+ />
109+ < span className = "font-medium text-white" > { name } </ span >
110+ < span className = "text-gray-400" > { percentage . toFixed ( 1 ) } %</ span >
111+ </ div >
112+ ) ) }
113+ </ div >
114+ </ div >
115+ ) ;
116+ } ;
117+
50118function getRandomGradient ( ) {
51119 const colors = [
52120 'from-purple-500 to-pink-500' ,
@@ -101,7 +169,10 @@ export default function GithubProjectsPage() {
101169 const filteredProjects = projects . filter ( ( project ) =>
102170 project . name . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) ||
103171 project . description . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) ||
104- project . tags . some ( ( tag ) => tag . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) )
172+ project . tags . some ( ( tag ) => tag . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) ) ||
173+ Object . keys ( project . languages ) . some ( ( lang ) =>
174+ lang . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) )
175+ )
105176 ) ;
106177
107178 const indexOfLastProject = currentPage * projectsPerPage ;
@@ -192,14 +263,14 @@ export default function GithubProjectsPage() {
192263 < Search className = "absolute left-4 top-3.5 h-5 w-5 text-gray-400" />
193264 < Input
194265 type = "text"
195- placeholder = "Search projects by name, description, or tags ..."
266+ placeholder = "Search projects by name, description, tags or language ..."
196267 className = "pl-12 py-6 w-full bg-slate-800/50 border-slate-700 text-white placeholder:text-gray-400 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-500"
197268 value = { searchTerm }
198269 onChange = { ( e ) => setSearchTerm ( e . target . value ) }
199270 />
200271 </ div >
201272 </ div >
202- { /*Project Card*/ }
273+
203274 < div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-8" >
204275 { currentProjects . map ( ( project ) => {
205276 const isSaved = savedProjects . includes ( project . name ) ;
@@ -247,7 +318,9 @@ export default function GithubProjectsPage() {
247318 ) ) }
248319 </ div >
249320
250- < div className = "flex justify-start gap-6 text-sm text-gray-400" >
321+ < LanguageBar languages = { project . languages } />
322+
323+ < div className = "flex justify-start gap-6 text-sm text-gray-400 mt-6" >
251324 < span className = "flex items-center" >
252325 < Star className = "h-4 w-4 mr-1.5 text-yellow-500" />
253326 { project . stars }
@@ -264,7 +337,6 @@ export default function GithubProjectsPage() {
264337 } ) }
265338 </ div >
266339
267- { /* Pagination */ }
268340 < div className = "flex justify-center gap-4 mb-16" >
269341 < Button
270342 variant = "outline"
@@ -289,9 +361,7 @@ export default function GithubProjectsPage() {
289361 </ Button >
290362 </ div >
291363
292- { /* Project Request Section */ }
293364 < div className = "grid grid-cols-1 lg:grid-cols-2 gap-8 max-w-6xl mx-auto" >
294-
295365 < Card className = "bg-slate-800/50 border-slate-700 h-fit" >
296366 < CardHeader >
297367 < CardTitle className = "text-white text-xl text-center" > Request a Project</ CardTitle >
@@ -366,7 +436,6 @@ export default function GithubProjectsPage() {
366436 </ CardContent >
367437 </ Card >
368438
369- { /* Community Guidelines Card */ }
370439 < Card className = "bg-slate-800/50 border-slate-700 text-white h-fit lg:mt-0" >
371440 < CardHeader >
372441 < CardTitle className = "flex items-center gap-2" >
@@ -417,7 +486,7 @@ export default function GithubProjectsPage() {
417486 </ div >
418487 </ div >
419488 </ div >
420- { /*Discord Alert*/ }
489+
421490 < AlertDialog open = { showDiscordDialog } onOpenChange = { setShowDiscordDialog } >
422491 < AlertDialogContent className = "bg-slate-800 text-white border-slate-700" >
423492 < AlertDialogHeader >
@@ -463,5 +532,4 @@ export default function GithubProjectsPage() {
463532 </ AlertDialogContent >
464533 </ AlertDialog >
465534 </ div >
466- ) ;
467- }
535+ ) } ;
0 commit comments