diff --git a/app/api/mentors/route.ts b/app/api/mentors/route.ts new file mode 100644 index 00000000..8a034b63 --- /dev/null +++ b/app/api/mentors/route.ts @@ -0,0 +1,48 @@ +import { NextResponse } from "next/server"; +import { createClient } from "@supabase/supabase-js"; + +// Force Node.js runtime for API routes +export const runtime = 'nodejs'; + +// Create Supabase client function to avoid build-time initialization +function getSupabaseClient() { + return createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.SUPABASE_SERVICE_ROLE_KEY! + ); +} + +// GET: List all approved mentors +export async function GET(req: Request) { + const { searchParams } = new URL(req.url); + const expertise = searchParams.get('expertise'); + const type = searchParams.get('type'); + const search = searchParams.get('search'); + + const supabase = getSupabaseClient(); + let query = supabase + .from("mentor_applications") + .select("id, first_name, last_name, company, occupation, expertise, expertise_areas, mentoring_types, linkedin, availability, created_at") + .eq("status", "approved") + .order("created_at", { ascending: false }); + + if (expertise && expertise !== 'all') { + query = query.contains('expertise_areas', [expertise]); + } + + if (type && type !== 'all') { + query = query.contains('mentoring_types', [type]); + } + + if (search) { + query = query.or(`first_name.ilike.%${search}%,last_name.ilike.%${search}%,company.ilike.%${search}%,occupation.ilike.%${search}%`); + } + + const { data, error } = await query; + + if (error) { + return NextResponse.json({ error: error.message }, { status: 500 }); + } + + return NextResponse.json({ mentors: data }); +} diff --git a/app/api/seed-real-mentors/route.ts b/app/api/seed-real-mentors/route.ts new file mode 100644 index 00000000..81eed419 --- /dev/null +++ b/app/api/seed-real-mentors/route.ts @@ -0,0 +1,100 @@ +import { NextResponse } from "next/server"; +import { createClient } from "@supabase/supabase-js"; + +export const runtime = 'nodejs'; + +function getSupabaseClient() { + return createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.SUPABASE_SERVICE_ROLE_KEY! + ); +} + +const REAL_MENTORS = [ + { + first_name: "Deepak", + last_name: "Pandey", + email: "deepak@codeunia.com", + phone: "", + location: "India", + occupation: "Founder & Tech Lead", + company: "Codeunia", + experience: "Full-stack engineer turned founder. Built Codeunia's platform from the ground up. Deep experience in scaling ed-tech products and engineering teams.", + expertise: "Full Stack Development, System Architecture, Startup Engineering, Product Strategy", + linkedin: "https://www.linkedin.com/in/848deepak/", + expertise_areas: ["system-design", "web-development", "cloud-computing"], + mentoring_types: ["career-advice", "project-guidance", "system-design"], + availability: "flexible", + commitment: "occasional", + motivation: "Helping developers bridge the gap between coding tutorials and building production-ready software.", + previous_mentoring: "Guided 100+ students in their transition to professional software engineering roles.", + teaching_style: "Focus on first principles and architectural thinking.", + status: "approved" + }, + { + first_name: "Parisha", + last_name: "Sharma", + email: "parisha@codeunia.com", + phone: "", + location: "India", + occupation: "Co-Founder & Operations Lead", + company: "Codeunia", + experience: "Specialist in tech operations and team dynamics. Expert in helping developers navigate their career paths, negotiate offers, and build leadership skills.", + expertise: "Tech Management, Career Strategy, Soft Skills, Agile Methodologies", + linkedin: "https://www.linkedin.com/in/parishasharma93/", + expertise_areas: ["ui-ux", "project-management"], // Mapped to closest available or generic + mentoring_types: ["career-advice", "interview-prep", "one-on-one"], + availability: "weekends", + commitment: "regular", + motivation: "Ensuring developers have the soft skills and strategic mindset needed to succeed in the industry.", + previous_mentoring: "Career coach for early-stage professionals.", + teaching_style: "Empathetic, structured, and goal-oriented coaching.", + status: "approved" + }, + { + first_name: "Akshay", + last_name: "Kumar", + email: "akshay.allen26200@gmail.com", + phone: "", + location: "India", + occupation: "Web Development Lead", + company: "Codeunia", + experience: "Senior Frontend Engineer with a focus on performance and user experience. Architected the core learning platform using Next.js and React Server Components.", + expertise: "Advanced React, Next.js, Frontend Architecture, Web Performance", + linkedin: "https://www.linkedin.com/in/akshaykumar0611/", + expertise_areas: ["web-development", "ui-ux", "system-design"], + mentoring_types: ["code-reviews", "project-guidance", "one-on-one"], + availability: "evenings", + commitment: "intensive", + motivation: "Passionate about writing clean, maintainable code and teaching modern web standards.", + previous_mentoring: "Lead code reviewer and technical mentor for Codeunia interns.", + teaching_style: "Hands-on pair programming and detailed code reviews.", + status: "approved" + } +]; + +export async function GET() { + const supabase = getSupabaseClient(); + + // 1. Delete existing mentors to reset data + const { error: deleteError } = await supabase + .from("mentor_applications") + .delete() + .neq("id", "00000000-0000-0000-0000-000000000000"); + + if (deleteError) { + return NextResponse.json({ error: deleteError.message }, { status: 500 }); + } + + // 2. Insert refined mentors + const { data, error } = await supabase + .from("mentor_applications") + .insert(REAL_MENTORS) + .select(); + + if (error) { + return NextResponse.json({ error: error.message }, { status: 500 }); + } + + return NextResponse.json({ success: true, count: data.length, data }); +} diff --git a/app/protected/mentorship/components/MentorCard.tsx b/app/protected/mentorship/components/MentorCard.tsx new file mode 100644 index 00000000..6343d928 --- /dev/null +++ b/app/protected/mentorship/components/MentorCard.tsx @@ -0,0 +1,140 @@ +"use client"; + +import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { Button } from "@/components/ui/button"; +import { Briefcase, Linkedin, Clock, GraduationCap } from "lucide-react"; +import { RequestDialog } from "./RequestDialog"; + +export interface Mentor { + id: string; + first_name: string; + last_name: string; + company: string; + occupation: string; + expertise: string; + expertise_areas: string[]; + mentoring_types: string[]; + linkedin: string; + availability: string; + created_at: string; +} + +interface MentorCardProps { + mentor: Mentor; +} + +const EXPERTISE_LABELS: Record = { + "web-development": "Web Dev", + "mobile-development": "Mobile Dev", + "ai-ml": "AI & ML", + "data-science": "Data Science", + "cybersecurity": "Cybersecurity", + "blockchain": "Blockchain", + "ui-ux": "UI/UX", + "devops": "DevOps", + "game-development": "Game Dev", + "cloud-computing": "Cloud", + "system-design": "System Design", + "algorithms": "Algorithms", +}; + +const IMAGE_MAP: Record = { + "Deepak Pandey": "/images/team/deepak.jpeg", + "Parisha Sharma": "/images/team/parisha.jpeg", + "Akshay Kumar": "/images/team/akshay.jpg", +}; + +export function MentorCard({ mentor }: MentorCardProps) { + const initials = `${mentor.first_name[0]}${mentor.last_name[0]}`; + const fullName = `${mentor.first_name} ${mentor.last_name}`; + const imageSrc = IMAGE_MAP[fullName] || `https://api.dicebear.com/7.x/avataaars/svg?seed=${mentor.id}`; + + return ( + + +
+
+ + + + {initials} + + +
+

+ {fullName} +

+
+ + {mentor.occupation} at {mentor.company} +
+ {mentor.linkedin && ( + + + LinkedIn Profile + + )} +
+
+
+
+ + +
+

+ {mentor.expertise} +

+
+ +
+
+ {mentor.expertise_areas?.slice(0, 4).map((area) => ( + + {EXPERTISE_LABELS[area] || area} + + ))} + {mentor.expertise_areas?.length > 4 && ( + + +{mentor.expertise_areas.length - 4} more + + )} +
+
+ +
+
+ + {mentor.availability} +
+
+ + {mentor.mentoring_types?.length || 0} Types +
+
+
+ + + + Request Mentorship + + } + /> + +
+ ); +} diff --git a/app/protected/mentorship/components/MentorshipFilters.tsx b/app/protected/mentorship/components/MentorshipFilters.tsx new file mode 100644 index 00000000..822ad81d --- /dev/null +++ b/app/protected/mentorship/components/MentorshipFilters.tsx @@ -0,0 +1,98 @@ +"use client"; + +import { Input } from "@/components/ui/input"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { Search, Filter } from "lucide-react"; + +interface MentorshipFiltersProps { + search: string; + setSearch: (value: string) => void; + expertise: string; + setExpertise: (value: string) => void; + type: string; + setType: (value: string) => void; +} + +const EXPERTISE_OPTIONS = [ + { value: "all", label: "All Expertise" }, + { value: "web-development", label: "Web Development" }, + { value: "mobile-development", label: "Mobile Development" }, + { value: "ai-ml", label: "AI & Machine Learning" }, + { value: "data-science", label: "Data Science" }, + { value: "cybersecurity", label: "Cybersecurity" }, + { value: "blockchain", label: "Blockchain" }, + { value: "ui-ux", label: "UI/UX Design" }, + { value: "devops", label: "DevOps" }, + { value: "game-development", label: "Game Development" }, + { value: "cloud-computing", label: "Cloud Computing" }, + { value: "system-design", label: "System Design" }, + { value: "algorithms", label: "Algorithms" }, +]; + +const TYPE_OPTIONS = [ + { value: "all", label: "All Mentoring Types" }, + { value: "one-on-one", label: "One-on-One" }, + { value: "group-sessions", label: "Group Sessions" }, + { value: "code-reviews", label: "Code Reviews" }, + { value: "project-guidance", label: "Project Guidance" }, + { value: "career-advice", label: "Career Advice" }, + { value: "interview-prep", label: "Interview Prep" }, +]; + +export function MentorshipFilters({ + search, + setSearch, + expertise, + setExpertise, + type, + setType, +}: MentorshipFiltersProps) { + return ( +
+
+ + setSearch(e.target.value)} + className="pl-10" + /> +
+ +
+
+ +
+ +
+ +
+
+
+ ); +} diff --git a/app/protected/mentorship/components/RequestDialog.tsx b/app/protected/mentorship/components/RequestDialog.tsx new file mode 100644 index 00000000..f3b49ffa --- /dev/null +++ b/app/protected/mentorship/components/RequestDialog.tsx @@ -0,0 +1,84 @@ +"use client"; + +import { useState } from "react"; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; +import { toast } from "sonner"; +import { Loader2, Send } from "lucide-react"; + +interface RequestDialogProps { + mentorName: string; + mentorId: string; + trigger?: React.ReactNode; +} + +export function RequestDialog({ mentorName, mentorId, trigger }: RequestDialogProps) { + const [open, setOpen] = useState(false); + const [message, setMessage] = useState(""); + const [loading, setLoading] = useState(false); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + + // Simulate API call + await new Promise((resolve) => setTimeout(resolve, 1500)); + + // In a real app, you would send this to an API endpoint + console.log("Request sent to", mentorId, "with message:", message); + + toast.success(`Request sent to ${mentorName}!`, { + description: "They will receive your message and get back to you soon.", + }); + + setLoading(false); + setOpen(false); + setMessage(""); + }; + + return ( + + + {trigger || } + + + + Connect with {mentorName} + + Send a message to introduce yourself and explain why you'd like to connect. + + +
+
+ +