import { useState, useEffect } from "react"; import { Link } from "react-router-dom"; import Layout from "@/components/Layout"; import SEO from "@/components/SEO"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Badge } from "@/components/ui/badge"; import { Progress } from "@/components/ui/progress"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Switch } from "@/components/ui/switch"; import { User, Briefcase, GraduationCap, Link as LinkIcon, FileText, ArrowLeft, Plus, Trash2, Loader2, Save, CheckCircle2, } from "lucide-react"; import { useAuth } from "@/contexts/AuthContext"; import { aethexToast } from "@/lib/aethex-toast"; interface WorkHistory { company: string; position: string; start_date: string; end_date: string; current: boolean; description: string; } interface Education { institution: string; degree: string; field: string; start_year: number; end_year: number; current: boolean; } interface ProfileData { headline: string; bio: string; resume_url: string; portfolio_urls: string[]; work_history: WorkHistory[]; education: Education[]; skills: string[]; availability: string; desired_rate: number; rate_type: string; location: string; remote_preference: string; is_public: boolean; profile_completeness: number; } const DEFAULT_PROFILE: ProfileData = { headline: "", bio: "", resume_url: "", portfolio_urls: [], work_history: [], education: [], skills: [], availability: "", desired_rate: 0, rate_type: "hourly", location: "", remote_preference: "", is_public: false, profile_completeness: 0, }; export default function CandidateProfile() { const { session } = useAuth(); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [profile, setProfile] = useState(DEFAULT_PROFILE); const [newSkill, setNewSkill] = useState(""); const [newPortfolio, setNewPortfolio] = useState(""); useEffect(() => { if (session?.access_token) { fetchProfile(); } }, [session?.access_token]); const fetchProfile = async () => { try { const response = await fetch("/api/candidate/profile", { headers: { Authorization: `Bearer ${session?.access_token}` }, }); if (response.ok) { const data = await response.json(); if (data.profile) { setProfile({ ...DEFAULT_PROFILE, ...data.profile, portfolio_urls: Array.isArray(data.profile.portfolio_urls) ? data.profile.portfolio_urls : [], work_history: Array.isArray(data.profile.work_history) ? data.profile.work_history : [], education: Array.isArray(data.profile.education) ? data.profile.education : [], skills: Array.isArray(data.profile.skills) ? data.profile.skills : [], }); } } } catch (error) { console.error("Error fetching profile:", error); } finally { setLoading(false); } }; const saveProfile = async () => { if (!session?.access_token) return; setSaving(true); try { const response = await fetch("/api/candidate/profile", { method: "POST", headers: { Authorization: `Bearer ${session.access_token}`, "Content-Type": "application/json", }, body: JSON.stringify(profile), }); if (!response.ok) throw new Error("Failed to save profile"); const data = await response.json(); setProfile((prev) => ({ ...prev, profile_completeness: data.profile.profile_completeness, })); aethexToast.success("Profile saved successfully!"); } catch (error) { console.error("Error saving profile:", error); aethexToast.error("Failed to save profile"); } finally { setSaving(false); } }; const addSkill = () => { if (newSkill.trim() && !profile.skills.includes(newSkill.trim())) { setProfile((prev) => ({ ...prev, skills: [...prev.skills, newSkill.trim()], })); setNewSkill(""); } }; const removeSkill = (skill: string) => { setProfile((prev) => ({ ...prev, skills: prev.skills.filter((s) => s !== skill), })); }; const addPortfolio = () => { if (newPortfolio.trim() && !profile.portfolio_urls.includes(newPortfolio.trim())) { setProfile((prev) => ({ ...prev, portfolio_urls: [...prev.portfolio_urls, newPortfolio.trim()], })); setNewPortfolio(""); } }; const removePortfolio = (url: string) => { setProfile((prev) => ({ ...prev, portfolio_urls: prev.portfolio_urls.filter((u) => u !== url), })); }; const addWorkHistory = () => { setProfile((prev) => ({ ...prev, work_history: [ ...prev.work_history, { company: "", position: "", start_date: "", end_date: "", current: false, description: "", }, ], })); }; const updateWorkHistory = (index: number, field: string, value: any) => { setProfile((prev) => ({ ...prev, work_history: prev.work_history.map((item, i) => i === index ? { ...item, [field]: value } : item, ), })); }; const removeWorkHistory = (index: number) => { setProfile((prev) => ({ ...prev, work_history: prev.work_history.filter((_, i) => i !== index), })); }; const addEducation = () => { setProfile((prev) => ({ ...prev, education: [ ...prev.education, { institution: "", degree: "", field: "", start_year: new Date().getFullYear(), end_year: new Date().getFullYear(), current: false, }, ], })); }; const updateEducation = (index: number, field: string, value: any) => { setProfile((prev) => ({ ...prev, education: prev.education.map((item, i) => i === index ? { ...item, [field]: value } : item, ), })); }; const removeEducation = (index: number) => { setProfile((prev) => ({ ...prev, education: prev.education.filter((_, i) => i !== index), })); }; if (loading) { return (
); } return (
{/* Background effects */}
{/* Header */}

Edit Profile

Build your candidate profile to stand out

{/* Profile Completeness */}
Profile Completeness {profile.profile_completeness}%
{profile.profile_completeness === 100 && (
Profile complete!
)}
{/* Tabs */} Basic Info Experience Education Links {/* Basic Info Tab */} Basic Information Your headline and summary
setProfile((prev) => ({ ...prev, headline: e.target.value, })) } placeholder="e.g., Senior Full Stack Developer | React & Node.js" className="bg-slate-700/50 border-slate-600 text-slate-100" />