From 987e17dd1999f22dfd73245845621617820ec1cd Mon Sep 17 00:00:00 2001 From: ahaandesai27 Date: Sat, 6 Sep 2025 14:33:16 +0530 Subject: [PATCH 01/32] added resources for webdev and appdev --- app/api/resources/[domain]/route.ts | 220 +++++++++++++++++++++++++++- app/dashboard/[domain]/page.tsx | 3 +- app/sitemap.xml/route.ts | 42 ------ components/ResourceTable.tsx | 2 + config/navigation.ts | 29 +++- data/resources/web.json | 16 +- middleware.ts | 20 +-- 7 files changed, 257 insertions(+), 75 deletions(-) delete mode 100644 app/sitemap.xml/route.ts diff --git a/app/api/resources/[domain]/route.ts b/app/api/resources/[domain]/route.ts index dee1a55..3273e31 100644 --- a/app/api/resources/[domain]/route.ts +++ b/app/api/resources/[domain]/route.ts @@ -4,11 +4,219 @@ import { NextRequest } from 'next/server'; export const runtime = 'edge'; const resources = { - "cp": [], - "dev": [], - "eth": [], - "ai": [], - "proj-x": [] + "web": { + "Frontend": [ + { + "name": "CodeWithHarry Web Dev Playlist for HTML, CSS, JS", + "description": "HTML+CSS+JS+Basic Backend", + "tags": ["HTML", "CSS", "JS", "Basic Backend"], + "link": "https://youtube.com/playlist?list=PLu0W_9lII9agiCUZYRsvtGTXdxkzPyItg" + }, + { + "name": "TailWind CSS CWH", + "description": "Covers Tailwind in depth, must watch for CSS Haters", + "tags": ["Tailwind CSS", "CSS"], + "link": "https://www.youtube.com/playlist?list=PLu0W_9lII9ahwFDuExCpPFHAK829Wto2O" + }, + { + "name": "Kevin Powell YT Channel for CSS", + "description": "CSS God", + "tags": ["CSS"], + "link": "https://www.youtube.com/kepowob" + }, + { + "name": "CodingAddict JS Fundamentals", + "description": "Detailed JS Course, highly recommended", + "tags": ["JavaScript"], + "link": "https://youtu.be/2Ji-clqUYnA" + }, + { + "name": "CodingAddict JS Projects", + "description": "Corresponding Projects course for the above course", + "tags": ["JavaScript", "Projects"], + "link": "https://youtu.be/Kp3HGwlXwCk" + }, + { + "name": "CodingAddict ReactJS", + "description": "Detailed ReactJS Course up to date, highly recommended", + "tags": ["ReactJS"], + "link": "https://youtu.be/iZhV0bILFb0" + }, + { + "name": "CodingAddict ReactJS Projects", + "description": "Corresponding Projects course for the above course", + "tags": ["ReactJS", "Projects"], + "link": "https://youtu.be/ly3m6mv5qvg" + }, + { + "name": "React Net Ninja", + "description": "A bit outdated but still gold", + "tags": ["ReactJS"], + "link": "https://www.youtube.com/playlist?list=PL4cUxeGkcC9gZD-Tvwfod2gaISzfRiP9d" + }, + { + "name": "Jack Herrington React Introduction", + "description": "Not detailed but a solid intro", + "tags": ["ReactJS"], + "link": "https://youtube.com/playlist?list=PLNqp92_EXZBKa1U7JbgUwBnDk3XzYDvXe" + }, + { + "name": "CodeWithHarry React Playlist", + "description": "Detailed ReactJS Course Desi Bhasha me", + "tags": ["ReactJS", "Hindi"], + "link": "https://youtube.com/playlist?list=PLu0W_9lII9agx66oZnT6IyhcMIbUMNMdt" + }, + { + "name": "NamasteJS", + "description": "Amazing JS Course, a season 2.0 for this is in progress too", + "tags": ["JavaScript"], + "link": "https://youtube.com/playlist?list=PLlasXeu85E9cQ32gLCvAvr9vNaUccPVNP" + }, + { + "name": "Techgun YouTube Channel HTML, CSS, JS", + "description": "Tutorial with conceptual explanation in Hindi", + "tags": ["HTML", "CSS", "JavaScript", "Hindi"], + "link": "https://youtube.com/playlist?list=PLjpp5kBQLNTSdLVVjU_kea8J8lP24ZseT" + }, + { + "name": "Next.js 13 & 14 Course", + "link": "https://www.youtube.com/watch?v=843nec-IvW0", + "description": "Learn Next.js App Router, Server Components, and more", + "tags": ["Next.js", "React", "Full Stack"] + } + ], + "Backend": [ + { + "name": "CodeWithHarry Pug and NodeJS", + "description": "Backend Part of CWH’s Webdev Playlist", + "tags": ["NodeJS", "Pug", "CWH"], + "link": "https://www.youtube.com/playlist?list=PLobAq7hWqZWGTfhj4jNQAVzJd_y6iTErQ" + }, + { + "name": "NodeJs Playlist By Thapa Technical", + "description": "Includes Node, Express, Mongo & Auth Desi Bhasha me", + "tags": ["NodeJS", "ExpressJS", "MongoDB", "Authentication", "Hindi"], + "link": "https://www.youtube.com/playlist?list=PLwGdqUZWnOp00IbeN0OtL9dmnasipZ9x8" + }, + { + "name": "CodingAddict NodeJS and ExpressJS", + "description": "Detailed NodeJS Course, Highly recommended", + "tags": ["NodeJS", "ExpressJS"], + "link": "https://youtu.be/TNV0_7QRDwY" + }, + { + "name": "CodingAddict NodeJS Project with MongoDB", + "description": "Corresponding Projects Course for the above course, covers an intro to MongoDB and Mongoose", + "tags": ["NodeJS", "MongoDB", "Mongoose", "Projects"], + "link": "https://youtu.be/jIsj0upCBAM" + }, + { + "name": "Corey Schafer Flask Playlist", + "description": "The classic Flask course, might be a bit outdated but still relevant", + "tags": ["Flask", "Python"], + "link": "https://www.youtube.com/playlist?list=PL-osiE80TeTs4UjLw5MM6OjgkjFeUxCYH" + }, + { + "name": "CodeWithHarry Flask Playlist", + "description": "Exhaustive course for Flask", + "tags": ["Flask", "Python", "CWH"], + "link": "https://youtube.com/playlist?list=PLu0W_9lII9agAiWp6Y41ueUKx1VcTRxmf" + }, + { + "name": "Traversy Media 7 Hour Course", + "description": "Prereqs: Python", + "tags": ["Django", "Python"], + "link": "https://youtu.be/PtQiiknWUcI" + }, + { + "name": "CodingEntrepreneus Django Playlist", + "description": "Prereqs: Python. This course covers everything about Django", + "tags": ["Django", "Python"], + "link": "https://www.youtube.com/playlist?list=PLEsfXFp6DpzRMby_cSoWTFw8zaMdTEXgL" + } + ], + "DevOps": [ + { + "name": "Docker & Kubernetes", + "link": "https://www.youtube.com/watch?v=Wf2eSG3owoA", + "description": "Learn containerization and orchestration", + "tags": ["Docker", "Kubernetes", "DevOps"] + } + ] + }, + "appdev": { + "Flutter": [ + { + "name": "Flutter Tutorial by The Net Ninja", + "link": "https://www.youtube.com/playlist?list=PL4cUxeGkcC9jLYyp2Aoh6hcWuxFDX6PBJ", + "description": "Basic Concepts + 2 Mini Projects", + "tags": ["Flutter", "Beginner", "Projects"] + }, + { + "name": "Dart and Flutter Detailed Course by FreeCodeCamp and Vandad", + "link": "https://youtu.be/VPvVD8t02U8", + "description": "Includes literally everything A-Z up to date - even covers Firebase. Most recommended", + "tags": ["Flutter", "Dart", "Comprehensive", "Firebase"] + }, + { + "name": "Codepur Flutter", + "link": "https://www.youtube.com/watch?v=j-LOab_PzzU", + "description": "Covers Basics of Flutter + 1 Project", + "tags": ["Flutter", "Beginner", "Hindi"] + } + ], + "React Native": [ + { + "name": "React Native Tutorial", + "type": "youtube", + "link": "https://www.youtube.com/watch?v=0-S5a0eXPoc", + "description": "Build mobile apps with React Native", + "tags": ["React Native", "Mobile", "JavaScript"] + } + ], + "Android": [ + { + "name": "CodeWithHarry Appdev Basics in Java", + "link": "https://youtu.be/mXjZQX3UzOs", + "description": "Highly recommended for beginners", + "tags": ["Android", "Java", "Beginner"] + }, + { + "name": "Philipp Lackner Kotlin Basics", + "link": "https://youtube.com/playlist?list=PLQkwcJG4YTCRSQikwhtoApYs9ij_Hc5Z9", + "description": "Philipp Lackner is THE GOD for Kotlin", + "tags": ["Android", "Kotlin", "Beginner"] + }, + { + "name": "Philipp Lackner Android Fundamentals", + "link": "https://youtube.com/playlist?list=PLQkwcJG4YTCTq1raTb5iMuxnEB06J1VHX", + "description": "Covers core Android development concepts", + "tags": ["Android", "Kotlin", "Fundamentals"] + }, + { + "name": "Kotlin Tutorial By Smartherd ( Basic Concepts )", + "link": "https://www.youtube.com/playlist?list=PLlxmoA0rQ-LwgK1JsnMsakYNACYGa1cjR", + "description": "Beginner-friendly Kotlin basics", + "tags": ["Android", "Kotlin", "Beginner"] + }, + { + "name": "Android Basics in Kotlin course | Android Developers", + "link": "https://developer.android.com/courses/android-basics-kotlin/course?authuser=2", + "description": "Google’s Official Course", + "tags": ["Android", "Kotlin", "Official"] + }, + { + "name": "Kotlin Basics By CheezyCode", + "link": "https://youtube.com/playlist?list=PLRKyZvuMYSIMW3-rSOGCkPlO1z_IYJy3G", + "description": "Hindi m h, extremely useful for kotlin beginners", + "tags": ["Android", "Kotlin", "Hindi", "Beginner"] + } + ], + "iOS": [] + }, + "dsa-cp": {}, + "blockchain": {}, + "ml": {}, }; export async function GET( @@ -18,7 +226,7 @@ export async function GET( try { const domain = params.domain; const domainResources = resources[domain as keyof typeof resources] || []; - + return NextResponse.json(domainResources); } catch { return NextResponse.json( diff --git a/app/dashboard/[domain]/page.tsx b/app/dashboard/[domain]/page.tsx index 51baff0..96d5bca 100644 --- a/app/dashboard/[domain]/page.tsx +++ b/app/dashboard/[domain]/page.tsx @@ -26,7 +26,7 @@ export default function DomainPage() { (d: Domain) => d.resources === params.domain ); - if (!currentDomain) return null; + if (!currentDomain) return
{params.domain}
return (
@@ -74,6 +74,7 @@ export default function DomainPage() {
+ {/* This does multiple network requests for each category, must optimise by only one network request*/} - - ${routes.map(route => ` - - ${baseUrl}${route.url ? `/${route.url}` : ''} - ${lastMod} - ${route.freq} - ${route.priority} - `).join('')} -` - - return xml.trim() -} - -export async function GET() { - const xml = generateSitemapXML() - - return new NextResponse(xml, { - headers: { - 'Content-Type': 'application/xml', - 'Cache-Control': 'public, max-age=3600', - }, - }) -} diff --git a/components/ResourceTable.tsx b/components/ResourceTable.tsx index 3fac7b5..6720db6 100644 --- a/components/ResourceTable.tsx +++ b/components/ResourceTable.tsx @@ -24,9 +24,11 @@ export default function ResourceTable({ category, domain }: ResourceTableProps) const [error, setError] = useState(null); useEffect(() => { + // file name: data/resources/{domain}.json const fetchResources = async () => { try { setIsLoading(true); + console.log(category, domain); const response = await fetch(`/api/resources/${domain}`); if (!response.ok) { throw new Error('Failed to fetch resources'); diff --git a/config/navigation.ts b/config/navigation.ts index 4d02e96..efa1250 100644 --- a/config/navigation.ts +++ b/config/navigation.ts @@ -1,4 +1,7 @@ -import { Book, Brain, Code2, GraduationCap } from "lucide-react"; +import { Book, Brain, Code2, GraduationCap + , Blocks + , Smartphone + } from "lucide-react"; export const domains = [ { @@ -6,7 +9,7 @@ export const domains = [ resources: "web", icon: Code2, description: "Frontend, Backend, and Full Stack Development Resources", - categories: ["Frontend", "Backend", "DevOps", "Mobile"], + categories: ["Frontend", "Backend", "DevOps"], gradient: "from-blue-500 to-cyan-500", }, { @@ -18,15 +21,31 @@ export const domains = [ gradient: "from-purple-500 to-pink-500", }, { - name: "Competitive Programming", - resources: "cp", + name: "DSA & CP", + resources: "dsa-cp", icon: Book, description: "DSA, Algorithms, and Contest Preparation", categories: ["DSA", "Algorithms", "Contest Prep", "Practice"], gradient: "from-orange-500 to-red-500", }, { - name: "Academics", + name: "Blockchain", + resources: "blockchain", + icon: Blocks, + description: "Web3, Smart Contracts and Decentralized Applications", + categories: ["Smart Contracts", "dApps", "Web3", "Cryptocurrency"], + gradient: "from-yellow-500 to-amber-600", + }, + { + name: "App Development", + resources: "appdev", + icon: Smartphone, + description: "Android, iOS, and Cross-Platform App Development Resources", + categories: ["Flutter", "React Native", "Android", "iOS"], + gradient: "from-indigo-500 to-purple-600", + }, + { + name: "Interview Resources", resources: "academics", icon: GraduationCap, description: "Year-wise Academic Resources and Materials", diff --git a/data/resources/web.json b/data/resources/web.json index 86deb5b..b5cef2a 100644 --- a/data/resources/web.json +++ b/data/resources/web.json @@ -1,5 +1,5 @@ { - "Frontend": [ + "frontend": [ { "name": "React.js Fundamentals", "type": "youtube", @@ -15,7 +15,7 @@ "tags": ["Next.js", "React", "Full Stack"] } ], - "Backend": [ + "backend": [ { "name": "Node.js Complete Guide", "type": "youtube", @@ -24,7 +24,7 @@ "tags": ["Node.js", "Express", "Backend"] } ], - "DevOps": [ + "devOps": [ { "name": "Docker & Kubernetes", "type": "youtube", @@ -33,13 +33,7 @@ "tags": ["Docker", "Kubernetes", "DevOps"] } ], - "Mobile": [ - { - "name": "React Native Tutorial", - "type": "youtube", - "link": "https://www.youtube.com/watch?v=0-S5a0eXPoc", - "description": "Build mobile apps with React Native", - "tags": ["React Native", "Mobile", "JavaScript"] - } + "mobile": [ + ] } diff --git a/middleware.ts b/middleware.ts index ac89651..d102045 100644 --- a/middleware.ts +++ b/middleware.ts @@ -3,19 +3,19 @@ import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; export async function middleware(request: NextRequest) { - const token = await getToken({ req: request }); + // const token = await getToken({ req: request }); - if (!token && request.nextUrl.pathname.startsWith("/dashboard")) { - const signInUrl = new URL("/auth/signin", request.url); - signInUrl.searchParams.set("callbackUrl", request.nextUrl.pathname); - return NextResponse.redirect(signInUrl); - } + // if (!token && request.nextUrl.pathname.startsWith("/dashboard")) { + // const signInUrl = new URL("/auth/signin", request.url); + // signInUrl.searchParams.set("callbackUrl", request.nextUrl.pathname); + // return NextResponse.redirect(signInUrl); + // } - if (token && !token.email?.endsWith('.vjti.ac.in')) { - return NextResponse.redirect(new URL("/auth/error", request.url)); - } + // if (token && !token.email?.endsWith('.vjti.ac.in')) { + // return NextResponse.redirect(new URL("/auth/error", request.url)); + // } - return NextResponse.next(); + // return NextResponse.next(); } export const config = { From 0f93c0d913e47ff8e1f084a46122a5dafada2eb9 Mon Sep 17 00:00:00 2001 From: ahaandesai27 Date: Sat, 6 Sep 2025 20:44:21 +0530 Subject: [PATCH 02/32] Added more resources, created more domains, improved responsiveness of overview page and implemented sidebar hiding at smaller viewports --- app/api/resources/[domain]/route.ts | 216 +----------- app/dashboard/layout.tsx | 32 +- app/dashboard/page.tsx | 51 +-- components/ResourceTable.tsx | 50 +-- components/Sidebar.tsx | 38 ++- config/navigation.ts | 34 +- data/resources.json | 500 ++++++++++++++++++++++++++++ 7 files changed, 627 insertions(+), 294 deletions(-) create mode 100644 data/resources.json diff --git a/app/api/resources/[domain]/route.ts b/app/api/resources/[domain]/route.ts index 3273e31..1dd0c28 100644 --- a/app/api/resources/[domain]/route.ts +++ b/app/api/resources/[domain]/route.ts @@ -1,223 +1,9 @@ import { NextResponse } from 'next/server'; import { NextRequest } from 'next/server'; +import resources from '@/data/resources.json'; export const runtime = 'edge'; -const resources = { - "web": { - "Frontend": [ - { - "name": "CodeWithHarry Web Dev Playlist for HTML, CSS, JS", - "description": "HTML+CSS+JS+Basic Backend", - "tags": ["HTML", "CSS", "JS", "Basic Backend"], - "link": "https://youtube.com/playlist?list=PLu0W_9lII9agiCUZYRsvtGTXdxkzPyItg" - }, - { - "name": "TailWind CSS CWH", - "description": "Covers Tailwind in depth, must watch for CSS Haters", - "tags": ["Tailwind CSS", "CSS"], - "link": "https://www.youtube.com/playlist?list=PLu0W_9lII9ahwFDuExCpPFHAK829Wto2O" - }, - { - "name": "Kevin Powell YT Channel for CSS", - "description": "CSS God", - "tags": ["CSS"], - "link": "https://www.youtube.com/kepowob" - }, - { - "name": "CodingAddict JS Fundamentals", - "description": "Detailed JS Course, highly recommended", - "tags": ["JavaScript"], - "link": "https://youtu.be/2Ji-clqUYnA" - }, - { - "name": "CodingAddict JS Projects", - "description": "Corresponding Projects course for the above course", - "tags": ["JavaScript", "Projects"], - "link": "https://youtu.be/Kp3HGwlXwCk" - }, - { - "name": "CodingAddict ReactJS", - "description": "Detailed ReactJS Course up to date, highly recommended", - "tags": ["ReactJS"], - "link": "https://youtu.be/iZhV0bILFb0" - }, - { - "name": "CodingAddict ReactJS Projects", - "description": "Corresponding Projects course for the above course", - "tags": ["ReactJS", "Projects"], - "link": "https://youtu.be/ly3m6mv5qvg" - }, - { - "name": "React Net Ninja", - "description": "A bit outdated but still gold", - "tags": ["ReactJS"], - "link": "https://www.youtube.com/playlist?list=PL4cUxeGkcC9gZD-Tvwfod2gaISzfRiP9d" - }, - { - "name": "Jack Herrington React Introduction", - "description": "Not detailed but a solid intro", - "tags": ["ReactJS"], - "link": "https://youtube.com/playlist?list=PLNqp92_EXZBKa1U7JbgUwBnDk3XzYDvXe" - }, - { - "name": "CodeWithHarry React Playlist", - "description": "Detailed ReactJS Course Desi Bhasha me", - "tags": ["ReactJS", "Hindi"], - "link": "https://youtube.com/playlist?list=PLu0W_9lII9agx66oZnT6IyhcMIbUMNMdt" - }, - { - "name": "NamasteJS", - "description": "Amazing JS Course, a season 2.0 for this is in progress too", - "tags": ["JavaScript"], - "link": "https://youtube.com/playlist?list=PLlasXeu85E9cQ32gLCvAvr9vNaUccPVNP" - }, - { - "name": "Techgun YouTube Channel HTML, CSS, JS", - "description": "Tutorial with conceptual explanation in Hindi", - "tags": ["HTML", "CSS", "JavaScript", "Hindi"], - "link": "https://youtube.com/playlist?list=PLjpp5kBQLNTSdLVVjU_kea8J8lP24ZseT" - }, - { - "name": "Next.js 13 & 14 Course", - "link": "https://www.youtube.com/watch?v=843nec-IvW0", - "description": "Learn Next.js App Router, Server Components, and more", - "tags": ["Next.js", "React", "Full Stack"] - } - ], - "Backend": [ - { - "name": "CodeWithHarry Pug and NodeJS", - "description": "Backend Part of CWH’s Webdev Playlist", - "tags": ["NodeJS", "Pug", "CWH"], - "link": "https://www.youtube.com/playlist?list=PLobAq7hWqZWGTfhj4jNQAVzJd_y6iTErQ" - }, - { - "name": "NodeJs Playlist By Thapa Technical", - "description": "Includes Node, Express, Mongo & Auth Desi Bhasha me", - "tags": ["NodeJS", "ExpressJS", "MongoDB", "Authentication", "Hindi"], - "link": "https://www.youtube.com/playlist?list=PLwGdqUZWnOp00IbeN0OtL9dmnasipZ9x8" - }, - { - "name": "CodingAddict NodeJS and ExpressJS", - "description": "Detailed NodeJS Course, Highly recommended", - "tags": ["NodeJS", "ExpressJS"], - "link": "https://youtu.be/TNV0_7QRDwY" - }, - { - "name": "CodingAddict NodeJS Project with MongoDB", - "description": "Corresponding Projects Course for the above course, covers an intro to MongoDB and Mongoose", - "tags": ["NodeJS", "MongoDB", "Mongoose", "Projects"], - "link": "https://youtu.be/jIsj0upCBAM" - }, - { - "name": "Corey Schafer Flask Playlist", - "description": "The classic Flask course, might be a bit outdated but still relevant", - "tags": ["Flask", "Python"], - "link": "https://www.youtube.com/playlist?list=PL-osiE80TeTs4UjLw5MM6OjgkjFeUxCYH" - }, - { - "name": "CodeWithHarry Flask Playlist", - "description": "Exhaustive course for Flask", - "tags": ["Flask", "Python", "CWH"], - "link": "https://youtube.com/playlist?list=PLu0W_9lII9agAiWp6Y41ueUKx1VcTRxmf" - }, - { - "name": "Traversy Media 7 Hour Course", - "description": "Prereqs: Python", - "tags": ["Django", "Python"], - "link": "https://youtu.be/PtQiiknWUcI" - }, - { - "name": "CodingEntrepreneus Django Playlist", - "description": "Prereqs: Python. This course covers everything about Django", - "tags": ["Django", "Python"], - "link": "https://www.youtube.com/playlist?list=PLEsfXFp6DpzRMby_cSoWTFw8zaMdTEXgL" - } - ], - "DevOps": [ - { - "name": "Docker & Kubernetes", - "link": "https://www.youtube.com/watch?v=Wf2eSG3owoA", - "description": "Learn containerization and orchestration", - "tags": ["Docker", "Kubernetes", "DevOps"] - } - ] - }, - "appdev": { - "Flutter": [ - { - "name": "Flutter Tutorial by The Net Ninja", - "link": "https://www.youtube.com/playlist?list=PL4cUxeGkcC9jLYyp2Aoh6hcWuxFDX6PBJ", - "description": "Basic Concepts + 2 Mini Projects", - "tags": ["Flutter", "Beginner", "Projects"] - }, - { - "name": "Dart and Flutter Detailed Course by FreeCodeCamp and Vandad", - "link": "https://youtu.be/VPvVD8t02U8", - "description": "Includes literally everything A-Z up to date - even covers Firebase. Most recommended", - "tags": ["Flutter", "Dart", "Comprehensive", "Firebase"] - }, - { - "name": "Codepur Flutter", - "link": "https://www.youtube.com/watch?v=j-LOab_PzzU", - "description": "Covers Basics of Flutter + 1 Project", - "tags": ["Flutter", "Beginner", "Hindi"] - } - ], - "React Native": [ - { - "name": "React Native Tutorial", - "type": "youtube", - "link": "https://www.youtube.com/watch?v=0-S5a0eXPoc", - "description": "Build mobile apps with React Native", - "tags": ["React Native", "Mobile", "JavaScript"] - } - ], - "Android": [ - { - "name": "CodeWithHarry Appdev Basics in Java", - "link": "https://youtu.be/mXjZQX3UzOs", - "description": "Highly recommended for beginners", - "tags": ["Android", "Java", "Beginner"] - }, - { - "name": "Philipp Lackner Kotlin Basics", - "link": "https://youtube.com/playlist?list=PLQkwcJG4YTCRSQikwhtoApYs9ij_Hc5Z9", - "description": "Philipp Lackner is THE GOD for Kotlin", - "tags": ["Android", "Kotlin", "Beginner"] - }, - { - "name": "Philipp Lackner Android Fundamentals", - "link": "https://youtube.com/playlist?list=PLQkwcJG4YTCTq1raTb5iMuxnEB06J1VHX", - "description": "Covers core Android development concepts", - "tags": ["Android", "Kotlin", "Fundamentals"] - }, - { - "name": "Kotlin Tutorial By Smartherd ( Basic Concepts )", - "link": "https://www.youtube.com/playlist?list=PLlxmoA0rQ-LwgK1JsnMsakYNACYGa1cjR", - "description": "Beginner-friendly Kotlin basics", - "tags": ["Android", "Kotlin", "Beginner"] - }, - { - "name": "Android Basics in Kotlin course | Android Developers", - "link": "https://developer.android.com/courses/android-basics-kotlin/course?authuser=2", - "description": "Google’s Official Course", - "tags": ["Android", "Kotlin", "Official"] - }, - { - "name": "Kotlin Basics By CheezyCode", - "link": "https://youtube.com/playlist?list=PLRKyZvuMYSIMW3-rSOGCkPlO1z_IYJy3G", - "description": "Hindi m h, extremely useful for kotlin beginners", - "tags": ["Android", "Kotlin", "Hindi", "Beginner"] - } - ], - "iOS": [] - }, - "dsa-cp": {}, - "blockchain": {}, - "ml": {}, -}; export async function GET( request: NextRequest, diff --git a/app/dashboard/layout.tsx b/app/dashboard/layout.tsx index 19ff1c8..260c23d 100644 --- a/app/dashboard/layout.tsx +++ b/app/dashboard/layout.tsx @@ -1,19 +1,45 @@ + "use client"; +import { useState } from "react"; import { Sidebar } from "@/components/Sidebar"; +import { Menu } from "lucide-react"; export default function DashboardLayout({ children, }: { children: React.ReactNode; }) { + const [sidebarOpen, setSidebarOpen] = useState(false); + + // Callback to close sidebar only on mobile + const handleSidebarLinkClick = () => { + if (window.innerWidth < 1024) setSidebarOpen(false); + }; + return (
-
+ {/* Sidebar for large screens */} +
- -
+ + {/* Sidebar popup for small screens */} +
+ +
+ + + +
{children}
diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index dab6750..d8906e6 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -4,8 +4,6 @@ import { useSession } from "next-auth/react"; import { usePathname } from "next/navigation"; import { motion } from "framer-motion"; import { Card } from "@/components/ui/card"; -// import { ScrollArea } from "@/components/ui/scroll-area"; -// import ResourceTable from "@/components/ResourceTable"; import { domains } from "@/config/navigation"; import Link from "next/link"; import { cn } from "@/lib/utils"; @@ -14,20 +12,16 @@ export default function Dashboard() { const { data: session } = useSession(); const pathname = usePathname(); const currentDomain = domains.find( - domain => `/dashboard/${domain.resources}` === pathname + (domain) => `/dashboard/${domain.resources}` === pathname ); return (
- - + @@ -35,36 +29,43 @@ export default function Dashboard() { Welcome back, {session?.user?.name?.split(" ")[0]}!

- Explore {currentDomain?.name || "educational"} resources curated just for you. + Explore {currentDomain?.name || "educational"} resources curated just + for you.

- {domains.map((domain) => ( - - -
-
+ + +
+
-
+

{domain.name}

{domain.description}

-
+
{domain.categories.map((category) => (
); -} \ No newline at end of file +} diff --git a/components/ResourceTable.tsx b/components/ResourceTable.tsx index 6720db6..d54e850 100644 --- a/components/ResourceTable.tsx +++ b/components/ResourceTable.tsx @@ -34,7 +34,7 @@ export default function ResourceTable({ category, domain }: ResourceTableProps) throw new Error('Failed to fetch resources'); } const data = await response.json(); - + // Get resources for the specific category from the nested structure const categoryResources = data[category] || []; setResources(categoryResources); @@ -54,45 +54,49 @@ export default function ResourceTable({ category, domain }: ResourceTableProps) if (!resources.length) return
No resources found.
; return ( - +
- Name - Description - Tags - Action + Name + Description + {domain !== "basics" && ( + Tags + )} + Action {resources.map((resource, index) => ( - - + {resource.name} - + {resource.description} - -
- {resource.tags.map((tag) => ( - - {tag} - - ))} -
-
- + {domain !== "basics" && ( + +
+ {resource.tags.map((tag) => ( + + {tag} + + ))} +
+
+ )} + @@ -75,16 +102,11 @@ const Navbar = () => { )} - - Community - - - Blog - + {session ? ( -
setIsProfileOpen(true)} onMouseLeave={() => setIsProfileOpen(false)}> +
- - -
+
+ {/* Custom Tab Bar */} +
{currentDomain.categories.map((category: string) => ( -
-
-
-

- {category} -

-
- - {/* This does multiple network requests for each category, must optimise by only one network request*/} - - -
+ ))}
- + + + {/* Tab Content */} + + + +
diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index d8906e6..67555f0 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -62,22 +62,23 @@ export default function Dashboard() {

{domain.name}

-

+

{domain.description}

-
- {domain.categories.map((category) => ( - - {category} - - ))} -
+ {/*
+ {domain.categories.map((category) => ( + + {category} + + ))} +
*/}
+ ))} diff --git a/components/ResourceTable.tsx b/components/ResourceTable.tsx index d54e850..2e6b346 100644 --- a/components/ResourceTable.tsx +++ b/components/ResourceTable.tsx @@ -1,5 +1,6 @@ "use client"; + import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; import { ExternalLink } from "lucide-react"; diff --git a/config/navigation.ts b/config/navigation.ts index a3840b4..14b3e3e 100644 --- a/config/navigation.ts +++ b/config/navigation.ts @@ -1,8 +1,11 @@ -import { Book, Brain, Code2, GraduationCap - , Blocks - , Smartphone - , Laptop - } from "lucide-react"; +import { + Book, Brain, Code2, GraduationCap + , Blocks + , Smartphone + , Laptop, + Shield, + Briefcase +} from "lucide-react"; export const domains = [ { @@ -18,7 +21,7 @@ export const domains = [ resources: "web", icon: Laptop, description: "Frontend, Backend, and Full Stack Development Resources", - categories: ["Frontend", "Backend", "DevOps"], + categories: ["Frontend", "Backend", "WebScraping", "DevOps"], gradient: "from-blue-500 to-cyan-500", }, { @@ -26,7 +29,7 @@ export const domains = [ resources: "ml", icon: Brain, description: "AI, Deep Learning, and Data Science Resources", - categories: ["AIML Fundamentals", "Deep Learning", "Data Science", "NLP", "CV"], + categories: ["AIML Fundamentals", "Deep Learning", "Data Science", "NLP", "CV", "GenAI"], gradient: "from-purple-500 to-pink-500", }, { @@ -46,24 +49,31 @@ export const domains = [ gradient: "from-yellow-500 to-amber-600", }, { - name: "App Development", - resources: "appdev", - icon: Smartphone, - description: "Android, iOS, and Cross-Platform App Development Resources", - categories: ["Flutter", "React Native", "Android", "iOS"], - gradient: "from-indigo-500 to-purple-600", + name: "App Development", + resources: "appdev", + icon: Smartphone, + description: "Android, iOS, and Cross-Platform App Development Resources", + categories: ["Flutter", "React Native", "Android", "iOS"], + gradient: "from-indigo-500 to-purple-600", }, { - name: "Interview Resources", - resources: "academics", - icon: GraduationCap, - description: "Resources for Internship and Placement Interviews.", - categories: [ - "Interview Experiences", - "CS Fundamentals", - "Behavioral Questions" - ], - gradient: "from-green-400 to-emerald-600", -} + name: "Cybersecurity", + resources: "cybersec", + icon: Shield, + description: "Learn and practice cybersecurity skills including general concepts, web exploitation, and hands-on tutorials.", + categories: ["General Skills", "Web Exploitation", "Books & Tutorials"], + gradient: "from-indigo-500 to-purple-600", + }, + { + name: "Interview Resources", + resources: "interview", + icon: Briefcase, + description: "Resources for Internship and Placement Interviews.", + categories: [ + "CS Fundamentals", + "Interview Experiences", + ], + gradient: "from-indigo-500 to-purple-600", + } ]; diff --git a/data/resources.json b/data/resources.json index cdeacbb..818c460 100644 --- a/data/resources.json +++ b/data/resources.json @@ -249,6 +249,38 @@ "description": "Learn containerization and orchestration", "tags": ["Docker", "Kubernetes", "DevOps"] } + ], + "WebScraping": [ + { + "name": "Web Scraping with Python - Beautiful Soup Crash Course", + "link": "https://youtu.be/XVv6mJpFOb0?si=32NxBy8wNUNEhFnc4", + "description": "BeautifulSoup is suitable for small scraping projects, do begin with this before considering Scrapy", + "tags": ["Python", "Beautiful Soup"] + }, + { + "name": "Scrapy Playlist - Basics of Scrapy", + "link": "https://youtube.com/playlist?list=PLhTjy8cBISEqkN-5Ku_kXG4QW33sxQo0t&si=Nl-Cd6X9FvmPPFPC", + "description": "Personally used this to get familiar with the framework", + "tags": ["Scrapy", "Python"] + }, + { + "name": "Scrapy Course – Python Web Scraping for Beginners", + "link": "https://youtu.be/mBoX_JCKZTE?si=dB2BTEPBhWjD74sP", + "description": "A very new tutorial, haven’t tried it personally - But FreeCodeCamp courses are always reliable!", + "tags": ["Scrapy", "Python", "FreeCodeCamp"] + }, + { + "name": "Python Automation and Testing", + "link": "https://drive.google.com/drive/folders/1w1Xy60T_1u-KVzvt0NlMYuguqf87miK0?usp=share_link", + "description": "An introductory course from LinkedIn Premium Learning Resources", + "tags": ["Python", "Automation"] + }, + { + "name": "Using Python for Automation", + "link": "https://drive.google.com/drive/folders/15uhFWzwki-d_GOYfL6k28JhfulUmsZQc?usp=share_link", + "description": "Also from LinkedIn Premium Learning Resources", + "tags": ["Python", "Automation"] + } ] }, "appdev": { @@ -334,7 +366,9 @@ } ] }, - "dsa-cp": {}, + "dsa-cp": { + + }, "blockchain": { "Web3": [ { @@ -406,6 +440,12 @@ "link": "https://www.coursera.org/specializations/deep-learning", "description": "Course by Andrew Ng, Highly Recommended. Covers CNNs, RNNs as well.", "tags": ["Neural Networks", "Deep Learning", "CNN", "RNN"] + }, + { + "name": "Pytorch", + "link": "https://www.youtube.com/watch?v=V_xro1bcAuA&t=2598s", + "description": "Daniel Bourke", + "tags": ["Pytorch"] } ], "Data Science": [ @@ -494,7 +534,281 @@ "tags": ["Data Science", "Matplotlib", "Tutorial"] } ], - "NLP": [], - "CV": [] + "NLP": [ + { + "name": "NLP (Crash Course)", + "link": "https://www.youtube.com/playlist?list=PLw3N0OFSAYSEC_XokEcX8uzJmEZSoNGuS", + "description": "T15", + "tags": ["NLP", "Crash Course"] + }, + { + "name": "NLP (In depth Course) - Coursera NLP Course by DeepLearning.AI", + "link": "https://www.coursera.org/specializations/natural-language-processing", + "description": "Highly recommended course for Introduction to neural networks and deep learning", + "tags": ["NLP", "Deep Learning", "Coursera"] + }, + { + "name": "Recommender Systems - University of Minnesota", + "link": "https://www.coursera.org/specializations/recommender-systems", + "description": "Consult ML team before starting", + "tags": ["Recommender Systems", "ML"] + }, + { + "name": "Langchain - Basics", + "link": "https://www.youtube.com/playlist?list=PLqZXAkvF1bPNQER9mLmDbntNfSpzdDIU5", + "description": "Basics", + "tags": ["Langchain", "Agentic AI"] + }, + { + "name": "Langchain - Applications", + "link": "https://www.youtube.com/playlist?list=PL8motc6AQftkp6hksbpzRps_NQvEKYOky", + "description": "Applications", + "tags": ["Langchain", "Agentic AI"] + } + ], + "CV": [ + { + "name": "Introduction to OpenCV", + "link": "https://www.youtube.com/watch?si=ZDgZXA19y9tFXZ_o&v=WQeoO7MI0Bs&feature=youtu.be&ab_channel=Murtaza%27sWorkshop-RoboticsandAI", + "description": "Applicative based introduction to CV", + "tags": ["Computer Vision", "OpenCV"] + }, + { + "name": "Deep Learning for Computer Vision", + "link": "https://www.youtube.com/watch?v=IA3WxTTPXqQ&ab_channel=freeCodeCamp.org", + "description": "Long detailed CV guide", + "tags": ["Computer Vision", "Deep Learning"] + } + ], + "GenAI": [ + { + "name": "LLM from Scratch", + "link": "https://www.youtube.com/watch?v=UU1WVnMk4E8&t=607s", + "description": null, + "tags": ["Generative AI", "LLM"] + }, + { + "name": "Generative AI full course", + "link": "https://www.youtube.com/watch?v=mEsleV16qdo&t=2730s", + "description": null, + "tags": ["Generative AI"] + }, + { + "name": "Vector Databases", + "link": "https://www.youtube.com/watch?v=8KrTO9bS91s", + "description": null, + "tags": ["Generative AI", "Vector Databases"] + }, + { + "name": "LLama from scratch", + "link": "https://www.youtube.com/watch?v=oM4VmoabDAI", + "description": null, + "tags": ["Generative AI", "LLaMA"] + }, + { + "name": "RAG from scratch", + "link": "https://www.youtube.com/watch?v=sVcwVQRHIc8", + "description": null, + "tags": ["Generative AI", "RAG"] + } + ] + }, + "cybersec": { + "General Skills": [ + { + "name": "VMware Installation Guide", + "link": "https://youtu.be/66qMLGCGP5s?feature=shared", + "description": null, + "tags": ["Cybersecurity", "Setup"] + }, + { + "name": "Kali Linux - ISO File", + "link": "https://www.kali.org/get-kali/#kali-installer-images", + "description": null, + "tags": ["Cybersecurity", "Setup", "Kali Linux"] + }, + { + "name": "Configuring Kali Linux", + "link": "https://youtu.be/U0AMu3rznc4?feature=shared", + "description": null, + "tags": ["Cybersecurity", "Setup", "Kali Linux"] + }, + { + "name": "Kali Linux Commands Speedrun", + "link": "https://youtu.be/gd7BXuUQ91w?feature=shared", + "description": null, + "tags": ["Cybersecurity", "General Skills", "Kali Linux"] + }, + { + "name": "Solve Bandit", + "link": "https://overthewire.org/wargames/bandit/", + "description": "Solve Bandit after learning Linux commands properly", + "tags": ["Cybersecurity", "General Skills", "Linux Commands"] + }, + { + "name": "Tryhackme Rooms", + "link": "https://tryhackme.com/r/hacktivities", + "description": "Choose basic rooms like NMAP, Linux, etc.", + "tags": ["Cybersecurity", "General Skills", "TryHackMe"] + }, + { + "name": "PicoCTF General Challenges", + "link": "https://play.picoctf.org/practice?category=5&page=1", + "description": null, + "tags": ["Cybersecurity", "General Skills", "PicoCTF"] + } + ], + "Web Exploitation": [ + { + "name": "Portswigger Labs", + "link": "https://portswigger.net/web-security/learning-paths", + "description": null, + "tags": ["Cybersecurity", "Web Exploitation", "Portswigger"] + }, + { + "name": "Natas Wargame (OverTheWire)", + "link": "https://overthewire.org/wargames/natas/", + "description": null, + "tags": ["Cybersecurity", "Web Exploitation", "OverTheWire"] + }, + { + "name": "Web Application Vulnerabilities Explained by Nahamsec", + "link": "https://youtube.com/playlist?list=PLKAaMVNxvLmBtguL9K62x6vEQJDe5r50G&feature=shared", + "description": null, + "tags": ["Cybersecurity", "Web Exploitation", "Vulnerabilities"] + }, + { + "name": "Tryhackme Rooms", + "link": "https://tryhackme.com/r/hacktivities", + "description": null, + "tags": ["Cybersecurity", "Web Exploitation", "TryHackMe"] + }, + { + "name": "PicoCTF Web Challenges", + "link": "https://play.picoctf.org/practice?category=1&page=1", + "description": null, + "tags": ["Cybersecurity", "Web Exploitation", "PicoCTF"] + } + ], + "Books & Tutorials": [ + { + "name": "Penetration Testing: A Hands-On Introduction by Georgia Weidman", + "link": "https://www.amazon.com/Penetration-Testing-Hands-Introduction-Ethical/dp/1593275641", + "description": null, + "tags": ["Cybersecurity", "Books & Tutorials", "Penetration Testing"] + }, + { + "name": "CTF Field Guide by Trail of Bits", + "link": null, + "description": null, + "tags": ["Cybersecurity", "Books & Tutorials", "CTF"] + }, + { + "name": "Open Security Training", + "link": "http://opensecuritytraining.info", + "description": "Free courses for cybersecurity topics.", + "tags": ["Cybersecurity", "Books & Tutorials"] + }, + { + "name": "Hack The Box Academy", + "link": "https://academy.hackthebox.com", + "description": "Detailed courses for hacking skills. (Best Academy, but paid)", + "tags": ["Cybersecurity", "Books & Tutorials", "Hack The Box"] + }, + { + "name": "Hackers101", + "link": "https://www.hackers101.com", + "description": "Learn to hack with their free courses.", + "tags": ["Cybersecurity", "Books & Tutorials"] + } + ] + }, + "interview": { + "CS Fundamentals": [ + { + "name": "Striver OS", + "link": "https://takeuforward.org/operating-system/most-asked-operating-system-interview-questions", + "description": "Operating Systems Sheet by Striver", + "tags": [ + "Operating Systems" + ] + }, + { + "name": "Striver DBMS", + "link": "https://takeuforward.org/dbms/most-asked-dbms-interview-questions", + "description": "DBMS sheet by Striver", + "tags": [ + "Database Management Systems" + ] + }, + { + "name": "Striver CN", + "link": "", + "description": "Computer Network sheet by Striver", + "tags": [ + "Computer Network" + ] + }, + { + "name": "Love Babbar OOP", + "link": "https://whimsical.com/object-oriented-programming-cheatsheet-by-love-babbar-YbSgLatbWQ4R5paV7EgqFw", + "description": "Object-Oriented Programming cheatsheet by Love Babbar", + "tags": [ + "Object-Oriented Programming", + "OOP" + ] + }, + { + "name": "Love Babbar DBMS", + "link": "https://whimsical.com/dbms-roadmap-by-love-babbar-FmUi8ffVop33t3MmpVxPCo", + "description": "Database Management Systems roadmap by Love Babbar", + "tags": [ + "Database Management Systems", + "DBMS" + ] + }, + { + "name": "Love Babbar OS", + "link": "https://whimsical.com/operating-system-cheatsheet-by-love-babbar-S9tuWBCSQfzoBRF5EDNinQ", + "description": "Operating Systems cheatsheet by Love Babbar", + "tags": [ + "Operating Systems", + "OS" + ] + }, + { + "name": "Exponent System Design Interview Prep", + "link": "https://www.youtube.com/playlist?list=PLrtCHHeadkHp92TyPt1Fj452_VGLipJnL", + "description": "A comprehensive playlist covering various system design interview questions and solutions.", + "tags": [ + "System Design", + "Interview Preparation" + ] + }, + { + "name": "System Design Interview - Exponent", + "link": "https://www.youtube.com/watch?v=07BVxmVFDGY&list=PLMCXHnjXnTnvo6alSjVkgxV-VH6EPyvoX&index=32", + "description": "Detailed walkthrough of system design problems and their solutions by Exponent.", + "tags": [ + "System Design", + "Interview Preparation" + ] + }, + { + "name": "LLD Playlist by Coder Army", + "link": "https://www.youtube.com/playlist?list=PLQEaRBV9gAFvzp6XhcNFpk1WdOcyVo9qT", + "description": "Recommended playlist for Low Level Design questions.", + "tags": ["Low Level Design", "System Design"] + } + ], + "Interview Experiences": [ + { + "name": "Drive Link", + "link": "https://drive.google.com/drive/u/2/folders/1BCKFtr9FWDI0iJ74bTYJdsYS74uKBq98", + "description": "Contains all internship and placement interview experiences by students.", + "tags": ["Interview Preparation", "Interview Experiences"] + } + ] } } + diff --git a/data/resources/academics.json b/data/resources_old/academics.json similarity index 100% rename from data/resources/academics.json rename to data/resources_old/academics.json diff --git a/data/resources/cp.json b/data/resources_old/cp.json similarity index 100% rename from data/resources/cp.json rename to data/resources_old/cp.json diff --git a/data/resources/ml.json b/data/resources_old/ml.json similarity index 100% rename from data/resources/ml.json rename to data/resources_old/ml.json diff --git a/data/resources/web.json b/data/resources_old/web.json similarity index 100% rename from data/resources/web.json rename to data/resources_old/web.json From 0084acaa363865da0eccb2c0e238b2699e9ceb86 Mon Sep 17 00:00:00 2001 From: Prathamesh Sankhe <144032313+PMS61@users.noreply.github.com> Date: Mon, 22 Sep 2025 14:44:05 +0530 Subject: [PATCH 05/32] feat: add Participant Management component with CRUD functionality - Implemented ParticipantManagement component for viewing and managing event participants. - Added filtering and searching capabilities for participants. - Included modals for viewing and editing participant details. - Created CSV export functionality for participant data. - Developed UI components for dialogs and text areas. - Defined types for events and participants to ensure type safety. - Updated next-auth types to include user admin status. --- .codacy/codacy.yaml | 15 + app/admin-dashboard/page.tsx | 177 ++++++ components/admin/AdminStats.tsx | 145 +++++ components/admin/EventManagement.tsx | 469 ++++++++++++++++ components/admin/ParticipantManagement.tsx | 613 +++++++++++++++++++++ components/ui/dialog.tsx | 120 ++++ components/ui/textarea.tsx | 23 + types/events.ts | 60 ++ types/next-auth.d.ts | 23 + 9 files changed, 1645 insertions(+) create mode 100644 .codacy/codacy.yaml create mode 100644 app/admin-dashboard/page.tsx create mode 100644 components/admin/AdminStats.tsx create mode 100644 components/admin/EventManagement.tsx create mode 100644 components/admin/ParticipantManagement.tsx create mode 100644 components/ui/dialog.tsx create mode 100644 components/ui/textarea.tsx create mode 100644 types/events.ts create mode 100644 types/next-auth.d.ts diff --git a/.codacy/codacy.yaml b/.codacy/codacy.yaml new file mode 100644 index 0000000..15365c7 --- /dev/null +++ b/.codacy/codacy.yaml @@ -0,0 +1,15 @@ +runtimes: + - dart@3.7.2 + - go@1.22.3 + - java@17.0.10 + - node@22.2.0 + - python@3.11.11 +tools: + - dartanalyzer@3.7.2 + - eslint@8.57.0 + - lizard@1.17.31 + - pmd@7.11.0 + - pylint@3.3.6 + - revive@1.7.0 + - semgrep@1.78.0 + - trivy@0.66.0 diff --git a/app/admin-dashboard/page.tsx b/app/admin-dashboard/page.tsx new file mode 100644 index 0000000..afe3f04 --- /dev/null +++ b/app/admin-dashboard/page.tsx @@ -0,0 +1,177 @@ +"use client"; + +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { motion } from "framer-motion"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Calendar, Users, Settings, BarChart3 } from "lucide-react"; +import EventManagement from "@/components/admin/EventManagement"; +import ParticipantManagement from "@/components/admin/ParticipantManagement"; +import AdminStats from "@/components/admin/AdminStats"; +import { Event, EventWithStats } from "@/types/events"; + +// Mock data - replace with actual API calls +const mockEvents: EventWithStats[] = [ + { + id: "1", + title: "AI Workshop Series", + description: "Hands-on workshop on implementing neural networks from scratch", + date: "2024-01-15", + time: "10:00", + location: "Virtual", + maxParticipants: 100, + registrationStatus: "open", + category: "workshop", + organizer: "AI Group", + tags: ["AI", "Machine Learning", "Neural Networks"], + requirements: ["Basic Python knowledge", "Laptop with Python installed"], + createdAt: "2024-01-01T00:00:00Z", + updatedAt: "2024-01-01T00:00:00Z", + participantCount: 45, + stats: { + total: 45, + confirmed: 42, + attended: 0, + cancelled: 3 + } + }, + { + id: "2", + title: "Blockchain Hackathon", + description: "48-hour hackathon focused on DeFi and Web3 solutions", + date: "2024-02-10", + time: "09:00", + location: "Innovation Hub", + maxParticipants: 80, + registrationStatus: "upcoming", + category: "hackathon", + organizer: "ETH Club", + tags: ["Blockchain", "Web3", "DeFi"], + requirements: ["Team of 2-4 members", "Basic blockchain knowledge"], + createdAt: "2024-01-05T00:00:00Z", + updatedAt: "2024-01-10T00:00:00Z", + participantCount: 32, + stats: { + total: 32, + confirmed: 30, + attended: 0, + cancelled: 2 + } + } +]; + +export default function AdminDashboard() { + const router = useRouter(); + const [events, setEvents] = useState(mockEvents); + const [activeTab, setActiveTab] = useState("overview"); + + const handleCreateEvent = (eventData: Event) => { + const newEvent: EventWithStats = { + ...eventData, + id: Math.random().toString(36).substr(2, 9), + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + participantCount: 0, + stats: { + total: 0, + confirmed: 0, + attended: 0, + cancelled: 0 + } + }; + setEvents(prev => [newEvent, ...prev]); + }; + + const handleUpdateEvent = (eventId: string, updates: Partial) => { + setEvents(prev => prev.map(event => + event.id === eventId + ? { ...event, ...updates, updatedAt: new Date().toISOString() } + : event + )); + }; + + const handleDeleteEvent = (eventId: string) => { + setEvents(prev => prev.filter(event => event.id !== eventId)); + }; + + return ( +
+ {/* Header */} +
+
+
+
+

+ Admin Dashboard +

+

+ Manage events and participants +

+
+
+ + Welcome, Admin + + +
+
+
+
+ + {/* Main Content */} +
+ + + + + Overview + + + + Events + + + + Participants + + + + + + + + + + + + + + + + + + + + +
+
+ ); +} diff --git a/components/admin/AdminStats.tsx b/components/admin/AdminStats.tsx new file mode 100644 index 0000000..283032a --- /dev/null +++ b/components/admin/AdminStats.tsx @@ -0,0 +1,145 @@ +"use client"; + +import { motion } from "framer-motion"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Calendar, Users, TrendingUp, AlertCircle } from "lucide-react"; +import { EventWithStats } from "@/types/events"; + +interface AdminStatsProps { + events: EventWithStats[]; +} + +export default function AdminStats({ events }: AdminStatsProps) { + const totalEvents = events.length; + const activeEvents = events.filter(e => e.registrationStatus === 'open').length; + const totalParticipants = events.reduce((sum, event) => sum + event.participantCount, 0); + const upcomingEvents = events.filter(e => new Date(e.date) > new Date()).length; + + const stats = [ + { + title: "Total Events", + value: totalEvents, + icon: Calendar, + color: "emerald", + description: "All time events created" + }, + { + title: "Active Events", + value: activeEvents, + icon: TrendingUp, + color: "blue", + description: "Currently accepting registrations" + }, + { + title: "Total Participants", + value: totalParticipants, + icon: Users, + color: "purple", + description: "Across all events" + }, + { + title: "Upcoming Events", + value: upcomingEvents, + icon: AlertCircle, + color: "orange", + description: "Events scheduled for future" + } + ]; + + const recentEvents = events + .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) + .slice(0, 5); + + return ( +
+ {/* Stats Grid */} +
+ {stats.map((stat, index) => ( + + + +
+
+

{stat.title}

+

{stat.value}

+

{stat.description}

+
+
+ +
+
+
+
+
+ ))} +
+ + {/* Recent Events */} + + + + + + Recent Events + + + + {recentEvents.length > 0 ? ( +
+ {recentEvents.map((event) => ( +
+
+

{event.title}

+

{event.description}

+
+ {new Date(event.date).toLocaleDateString()} + {event.location} + + {event.registrationStatus} + +
+
+
+
+

{event.participantCount}

+

Participants

+
+ {event.maxParticipants && ( +
+

+ {Math.round((event.participantCount / event.maxParticipants) * 100)}% +

+

Filled

+
+ )} +
+
+ ))} +
+ ) : ( +
+ +

No events created yet

+
+ )} +
+
+
+
+ ); +} \ No newline at end of file diff --git a/components/admin/EventManagement.tsx b/components/admin/EventManagement.tsx new file mode 100644 index 0000000..40fbe9a --- /dev/null +++ b/components/admin/EventManagement.tsx @@ -0,0 +1,469 @@ +"use client"; + +import { useState } from "react"; +import { motion } from "framer-motion"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Badge } from "@/components/ui/badge"; +import { + Plus, + Calendar, + MapPin, + Users, + Edit, + Trash2, + Clock, + Tag, + X +} from "lucide-react"; +import { Event, EventWithStats, EventFormData } from "@/types/events"; + +interface EventManagementProps { + events: EventWithStats[]; + onCreateEvent: (event: Event) => void; + onUpdateEvent: (eventId: string, updates: Partial) => void; + onDeleteEvent: (eventId: string) => void; +} + +export default function EventManagement({ + events, + onCreateEvent, + onUpdateEvent, + onDeleteEvent +}: EventManagementProps) { + const [showCreateForm, setShowCreateForm] = useState(false); + const [editingEvent, setEditingEvent] = useState(null); + const [formData, setFormData] = useState({ + title: "", + description: "", + date: "", + time: "", + location: "", + maxParticipants: 100, + category: "workshop", + tags: [], + requirements: [] + }); + const [newTag, setNewTag] = useState(""); + const [newRequirement, setNewRequirement] = useState(""); + + const resetForm = () => { + setFormData({ + title: "", + description: "", + date: "", + time: "", + location: "", + maxParticipants: 100, + category: "workshop", + tags: [], + requirements: [] + }); + setNewTag(""); + setNewRequirement(""); + setShowCreateForm(false); + setEditingEvent(null); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + + const eventData: Event = { + id: editingEvent || "", + title: formData.title, + description: formData.description, + date: formData.date, + time: formData.time, + location: formData.location, + maxParticipants: formData.maxParticipants, + registrationStatus: "upcoming", + category: formData.category, + organizer: "Admin", + tags: formData.tags, + requirements: formData.requirements, + imageUrl: formData.imageUrl, + createdAt: "", + updatedAt: "" + }; + + if (editingEvent) { + onUpdateEvent(editingEvent, eventData); + } else { + onCreateEvent(eventData); + } + + resetForm(); + }; + + const handleEdit = (event: EventWithStats) => { + setFormData({ + title: event.title, + description: event.description, + date: event.date, + time: event.time || "", + location: event.location, + maxParticipants: event.maxParticipants || 100, + category: event.category, + tags: event.tags, + requirements: event.requirements || [], + imageUrl: event.imageUrl + }); + setEditingEvent(event.id); + setShowCreateForm(true); + }; + + const addTag = () => { + if (newTag.trim() && !formData.tags.includes(newTag.trim())) { + setFormData(prev => ({ + ...prev, + tags: [...prev.tags, newTag.trim()] + })); + setNewTag(""); + } + }; + + const removeTag = (tagToRemove: string) => { + setFormData(prev => ({ + ...prev, + tags: prev.tags.filter(tag => tag !== tagToRemove) + })); + }; + + const addRequirement = () => { + if (newRequirement.trim() && !formData.requirements.includes(newRequirement.trim())) { + setFormData(prev => ({ + ...prev, + requirements: [...prev.requirements, newRequirement.trim()] + })); + setNewRequirement(""); + } + }; + + const removeRequirement = (reqToRemove: string) => { + setFormData(prev => ({ + ...prev, + requirements: prev.requirements.filter(req => req !== reqToRemove) + })); + }; + + return ( +
+ {/* Header */} +
+
+

Event Management

+

Create and manage community events

+
+ +
+ + {/* Create/Edit Form */} + {showCreateForm && ( + + + + + {editingEvent ? "Edit Event" : "Create New Event"} + + + +
+
+
+ + setFormData(prev => ({ ...prev, title: e.target.value }))} + placeholder="Enter event title" + className="bg-neutral-800/50 border-neutral-700 text-neutral-200" + required + /> +
+
+ + +
+
+ +
+ +