Skip to content

Commit 00f63ff

Browse files
committed
Coding Languages
1 parent a6c13f5 commit 00f63ff

File tree

3 files changed

+216
-29
lines changed

3 files changed

+216
-29
lines changed

app/saved/page.tsx

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import { Button } from '@/components/ui/button';
66
import { Star, GitFork, Tag } from 'lucide-react';
77
import { useEffect, useState } from 'react';
88

9+
interface Language {
10+
[key: string]: number;
11+
}
12+
913
interface Project {
1014
name: string;
1115
description: string;
@@ -14,8 +18,71 @@ interface Project {
1418
tags: string[];
1519
url: string;
1620
color: string;
21+
languages: Language;
1722
}
1823

24+
const languageColors: { [key: string]: string } = {
25+
Python: '#3572A5',
26+
TypeScript: '#2b7489',
27+
JavaScript: '#f1e05a',
28+
Shell: '#89e051',
29+
HTML: '#e34c26',
30+
CSS: '#563d7c',
31+
Dockerfile: '#384d54',
32+
Ruby: '#701516',
33+
PowerShell: '#012456',
34+
AutoHotkey: '#6594b9',
35+
Svelte: '#ff3e00',
36+
SCSS: '#c6538c',
37+
Scheme: '#1e4aec',
38+
"Inno Setup": '#264b99',
39+
Batchfile: '#C1F12E',
40+
Makefile: '#427819',
41+
Jinja: '#a52a22'
42+
};
43+
44+
const LanguageBar = ({ languages }: { languages: Language }) => {
45+
const totalBytes = Object.values(languages).reduce((sum, value) => sum + value, 0);
46+
47+
const percentages = Object.entries(languages).map(([name, bytes]) => ({
48+
name,
49+
percentage: (bytes / totalBytes) * 100
50+
})).sort((a, b) => b.percentage - a.percentage);
51+
52+
return (
53+
<div className="space-y-4">
54+
<h2 className="text-lg font-semibold text-white">Languages</h2>
55+
56+
<div className="h-2 w-full flex rounded-full overflow-hidden">
57+
{percentages.map(({ name, percentage }) => (
58+
<div
59+
key={name}
60+
style={{
61+
width: `${percentage}%`,
62+
backgroundColor: languageColors[name] || '#ededed'
63+
}}
64+
/>
65+
))}
66+
</div>
67+
68+
<div className="flex flex-wrap gap-4">
69+
{percentages
70+
.filter(({ percentage }) => percentage >= 2)
71+
.map(({ name, percentage }) => (
72+
<div key={name} className="flex items-center gap-2">
73+
<span
74+
className="w-3 h-3 rounded-full"
75+
style={{ backgroundColor: languageColors[name] || '#ededed' }}
76+
/>
77+
<span className="font-medium text-white">{name}</span>
78+
<span className="text-gray-400">{percentage.toFixed(1)}%</span>
79+
</div>
80+
))}
81+
</div>
82+
</div>
83+
);
84+
};
85+
1986
function getRandomGradient() {
2087
const colors = [
2188
'from-purple-500 to-pink-500',
@@ -29,7 +96,7 @@ function getRandomGradient() {
2996
}
3097

3198
export default function SavedPage() {
32-
const { removeProject } = useSaved();
99+
const { removeProject } = useSaved();
33100
const [savedProjectDetails, setSavedProjectDetails] = useState<Project[]>([]);
34101

35102
useEffect(() => {
@@ -38,11 +105,9 @@ export default function SavedPage() {
38105
const storedProjects = localStorage.getItem('savedProjects');
39106
const latestSavedProjects: string[] = storedProjects ? JSON.parse(storedProjects) : [];
40107

41-
42108
const response = await fetch('/api/projects');
43109
const allProjects: Project[] = await response.json();
44110

45-
46111
const filteredProjects = allProjects
47112
.filter((project) => latestSavedProjects.includes(project.name))
48113
.map((project) => ({ ...project, color: getRandomGradient() }));
@@ -57,10 +122,7 @@ export default function SavedPage() {
57122
}, []);
58123

59124
const handleRemove = (projectName: string) => {
60-
61125
removeProject(projectName);
62-
63-
64126
setSavedProjectDetails((prevDetails) =>
65127
prevDetails.filter((project) => project.name !== projectName)
66128
);
@@ -69,12 +131,14 @@ export default function SavedPage() {
69131
return (
70132
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900">
71133
<div className="pt-24 p-8">
72-
<div className="max-w-6xl mx-auto text-center">
134+
<div className="max-w-6xl mx-auto">
135+
<div className="text-center mb-8">
73136
<h1 className="text-4xl font-bold mb-6 bg-gradient-to-r from-blue-400 to-purple-400 text-transparent bg-clip-text">
74137
Saved Projects
75138
</h1>
139+
</div>
76140
{savedProjectDetails.length === 0 ? (
77-
<p className="text-gray-400">No projects saved yet.</p>
141+
<p className="text-gray-400 text-center">No projects saved yet.</p>
78142
) : (
79143
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
80144
{savedProjectDetails.map((project, index) => (
@@ -119,7 +183,9 @@ export default function SavedPage() {
119183
))}
120184
</div>
121185

122-
<div className="flex justify-start gap-6 text-sm text-gray-400">
186+
<LanguageBar languages={project.languages} />
187+
188+
<div className="flex justify-start gap-6 text-sm text-gray-400 mt-6">
123189
<span className="flex items-center">
124190
<Star className="h-4 w-4 mr-1.5 text-yellow-500" />
125191
{project.stars}
@@ -139,4 +205,4 @@ export default function SavedPage() {
139205
</div>
140206
</div>
141207
);
142-
}
208+
}

components/GithubProjectsPage.tsx

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
AlertDialogHeader,
1919
AlertDialogTitle,
2020
} from "@/components/ui/alert-dialog";
21+
2122
const 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+
3540
interface 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

4551
interface 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+
50118
function 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

Comments
 (0)