Skip to content

Commit 7505346

Browse files
committed
floating Discord promotion card
1 parent 7be699f commit 7505346

File tree

7 files changed

+188
-95
lines changed

7 files changed

+188
-95
lines changed

app/api/project-requests/route.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export async function POST(request: Request) {
4242
timestamp: new Date().toISOString(),
4343
footer: {
4444
text: "Codegems",
45-
icon_url: "https://www.codegems.xyz/icon.png" // Replace with your actual icon URL
45+
icon_url: "https://www.codegems.xyz/icon.png"
4646
}
4747
}],
4848
};

app/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Footer from '@/components/Footer';
66
import { Analytics } from "@vercel/analytics/react"
77
import { Toaster } from "@/components/ui/toaster"
88
import { SpeedInsights } from "@vercel/speed-insights/next"
9+
import DiscordPromo from '@/components/DiscordPromo';
910

1011
export const metadata: Metadata = {
1112
title: 'Code Gems',
@@ -41,6 +42,7 @@ export default function RootLayout({
4142
<SavedProvider>
4243
{children}
4344
</SavedProvider>
45+
<DiscordPromo />
4446
<Footer />
4547
<Toaster />
4648
<Analytics />

app/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import GithubProjectsPage from '@/components/GithubProjectsPage'
2+
import DiscordPromo from '@/components/DiscordPromo';
23

34
export default function Home() {
45
return <GithubProjectsPage />

app/saved/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ export default function SavedPage() {
3838
const storedProjects = localStorage.getItem('savedProjects');
3939
const latestSavedProjects: string[] = storedProjects ? JSON.parse(storedProjects) : [];
4040

41-
// Fetch all projects from the database
41+
4242
const response = await fetch('/api/projects');
4343
const allProjects: Project[] = await response.json();
4444

45-
// Filter projects to include only saved ones and assign random colors
45+
4646
const filteredProjects = allProjects
4747
.filter((project) => latestSavedProjects.includes(project.name))
4848
.map((project) => ({ ...project, color: getRandomGradient() }));
@@ -54,13 +54,13 @@ export default function SavedPage() {
5454
};
5555

5656
fetchSavedProjects();
57-
}, []); // Fetch saved projects only once when the component mounts
57+
}, []);
5858

5959
const handleRemove = (projectName: string) => {
60-
// Remove the project from context
60+
6161
removeProject(projectName);
6262

63-
// Update local state to reflect the change instantly
63+
6464
setSavedProjectDetails((prevDetails) =>
6565
prevDetails.filter((project) => project.name !== projectName)
6666
);

components/DiscordPromo.tsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"use client"
2+
3+
import React, { useState } from 'react';
4+
import { Card, CardContent } from '@/components/ui/card';
5+
import { Button } from '@/components/ui/button';
6+
import { X, Users, Bell, Star } from 'lucide-react';
7+
8+
const DiscordIcon = ({ className = "" }) => (
9+
<svg
10+
role="img"
11+
viewBox="0 0 24 24"
12+
xmlns="http://www.w3.org/2000/svg"
13+
className={className}
14+
width="24"
15+
height="24"
16+
fill="currentColor"
17+
>
18+
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/>
19+
</svg>
20+
);
21+
22+
const DiscordPromo = () => {
23+
const [isMinimized, setIsMinimized] = useState(false);
24+
25+
26+
const handleJoinDiscord = () => {
27+
window.open('https://discord.gg/QtnFGDQj5S', '_blank');
28+
};
29+
30+
if (isMinimized) {
31+
return (
32+
<div className="fixed bottom-4 right-4 z-50">
33+
<Button
34+
className="bg-purple-600 hover:bg-purple-700 text-white rounded-full p-3 shadow-lg"
35+
onClick={() => setIsMinimized(false)}
36+
>
37+
<DiscordIcon className="w-6 h-6" />
38+
</Button>
39+
</div>
40+
);
41+
}
42+
43+
return (
44+
<div className="fixed bottom-4 right-4 z-50">
45+
<Card className="w-64 bg-slate-800/95 border-slate-700 backdrop-blur">
46+
<CardContent className="p-4">
47+
<div className="flex justify-between items-start mb-4">
48+
<div className="flex items-center gap-2">
49+
<DiscordIcon className="w-6 h-6 text-purple-500" />
50+
<span className="font-semibold text-white">Join Our Community</span>
51+
</div>
52+
<div className="flex gap-1">
53+
<Button
54+
variant="ghost"
55+
size="sm"
56+
className="h-6 w-6 p-0 text-gray-400 hover:text-white"
57+
onClick={() => setIsMinimized(true)}
58+
>
59+
<X className="h-4 w-4" />
60+
</Button>
61+
</div>
62+
</div>
63+
64+
<div className="space-y-3 mb-4">
65+
<div className="flex items-center gap-2 text-gray-300">
66+
<Users className="w-4 h-4 text-purple-500" />
67+
<span className="text-sm">Code Beginner Friendly</span>
68+
</div>
69+
<div className="flex items-center gap-2 text-gray-300">
70+
<Bell className="w-4 h-4 text-purple-500" />
71+
<span className="text-sm">Daily updates & discussions</span>
72+
</div>
73+
<div className="flex items-center gap-2 text-gray-300">
74+
<Star className="w-4 h-4 text-purple-500" />
75+
<span className="text-sm">Exclusive content & features</span>
76+
</div>
77+
</div>
78+
79+
<Button
80+
className="w-full bg-purple-500 hover:bg-purple-600 text-white"
81+
onClick={handleJoinDiscord}
82+
>
83+
Join Discord Server
84+
</Button>
85+
</CardContent>
86+
</Card>
87+
</div>
88+
);
89+
};
90+
91+
export default DiscordPromo;

0 commit comments

Comments
 (0)