diff --git a/backend/projects/urls.py b/backend/projects/urls.py index d441ef4..08ba440 100644 --- a/backend/projects/urls.py +++ b/backend/projects/urls.py @@ -1,11 +1,12 @@ from django.urls import path -from .views import ProjectCRUDView, get_projects, toggle_follow, toggle_like, project_member_hander +from .views import ProjectCRUDView, get_projects, toggle_follow, toggle_like, project_member_hander, check_like_status urlpatterns = [ path('', get_projects, name='get_projects'), # Fetch all projects path('create/', ProjectCRUDView.as_view(), name='project-create'), # Create project path('/', ProjectCRUDView.as_view(), name='project-detail'), # Read, Update, Delete project by ID - path('like/', toggle_like, name='toggle_like'), - path('follow/', toggle_follow, name='toggle_follow'), - path('member/manage/', project_member_hander, name='project-member-handler'), + path('like//', toggle_like, name='toggle_like'), + path('follow//', toggle_follow, name='toggle_follow'), + path('member/manage//', project_member_hander, name='project-member-handler'), + path('likes/check///', check_like_status, name='check_like_status') ] diff --git a/backend/projects/views.py b/backend/projects/views.py index bbb9224..36ad92c 100644 --- a/backend/projects/views.py +++ b/backend/projects/views.py @@ -155,3 +155,14 @@ def project_member_hander(request, project_id): except User.DoesNotExist: return Response({'error': 'User not found'}, status=404) +@api_view(['GET']) +@permission_classes([AllowAny]) +def check_like_status(request, user_id, project_id): + try: + project = get_object_or_404(Project, id=project_id) + user = get_object_or_404(User, id=user_id) + + liked = Like.objects.filter(project=project, user=user).exists() + return Response({'liked': liked}, status=status.HTTP_200_OK) + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) diff --git a/backend/userauth/admin.py b/backend/userauth/admin.py index bde25d4..9367300 100644 --- a/backend/userauth/admin.py +++ b/backend/userauth/admin.py @@ -10,4 +10,8 @@ class UserAdmin(admin.ModelAdmin): ) search_fields = ('username', 'email', 'first_name', 'last_name') list_filter = ('location',) +<<<<<<< HEAD + filter_horizontal = ('projects', 'owned') +======= filter_horizontal = ('projects',) +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 diff --git a/backend/userauth/models.py b/backend/userauth/models.py index 23c384b..fdfd0a0 100644 --- a/backend/userauth/models.py +++ b/backend/userauth/models.py @@ -9,10 +9,14 @@ class User(models.Model): email = models.EmailField(unique=True, blank=True, null=True) first_name = models.CharField(max_length=255, default="") last_name = models.CharField(max_length=255, default="") +<<<<<<< HEAD + colleges = ArrayField(models.CharField(max_length=225), blank=True, null=True) +======= college = models.CharField(max_length=255, default="") major = models.CharField(max_length=255, default="") grad_date = models.CharField(max_length=255, default="") about_me = models.TextField(max_length=500, blank=True, null=True) +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 followers = models.IntegerField(default=0) likes = models.IntegerField(default=0) roles = models.JSONField(default=list) diff --git a/backend/userauth/urls.py b/backend/userauth/urls.py index d1253fd..4acbb4f 100644 --- a/backend/userauth/urls.py +++ b/backend/userauth/urls.py @@ -1,9 +1,17 @@ from django.urls import path +<<<<<<< HEAD +from .views import UsersCRUDView, check_if_onboarded +======= from .views import UsersCRUDView, check_if_onboarded, fetch_by_uuid +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 urlpatterns = [ path('onboard/', UsersCRUDView.as_view(), name='onboard-user'), # Create user path('onboard/check/', check_if_onboarded, name="onboard-check"), # Check if user onboarded +<<<<<<< HEAD + path('/', UsersCRUDView.as_view(), name='user'), # Read, Update, Delete user by ID +======= path('/', UsersCRUDView.as_view(), name='user'), # Read, Update, Delete user by ID path('fetch//', fetch_by_uuid, name='uuid-fetch'), +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 ] diff --git a/backend/userauth/views.py b/backend/userauth/views.py index 14aff4b..71aaf91 100644 --- a/backend/userauth/views.py +++ b/backend/userauth/views.py @@ -6,6 +6,60 @@ from .serializers import UserSerializer from rest_framework.permissions import AllowAny from rest_framework.decorators import api_view, permission_classes +<<<<<<< HEAD + +@api_view(['GET']) +@permission_classes([AllowAny]) +def check_if_onboarded(request, clerk_id): + if User.objects.filter(auth_id=clerk_id).exists(): + return Response({"message": "User already onboarded"}) + else: + return Response({"message": "User not onboarded yet!"}) + +# DRF CRUD views for Users model +class UsersCRUDView(APIView): + permission_classes = [AllowAny] + # Onboard a new user (POST) + def post(self, request): + serializer = UserSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response({ + "message": "User successfully onboarded", + "data": serializer.data + }, status=status.HTTP_201_CREATED) + else: + print(serializer.errors) + error_details = { + "message": "Invalid user data provided.", + "errors": serializer.errors, + } + return Response(error_details, status=status.HTTP_400_BAD_REQUEST) + + # Get a single user by ID (GET) + def get(self, request, pk): + user = get_object_or_404(User, pk=pk) + serializer = UserSerializer(user) + return Response(serializer.data) + + # Update an existing user by ID (PUT) + def put(self, request, pk): + user = get_object_or_404(User, pk=pk) + serializer = UserSerializer(user, data=request.data, partial=True) + if serializer.is_valid(): + serializer.save() + return Response({ + "message": "User successfully updated!", + "data": serializer.data + }, status=status.HTTP_201_CREATED) + else: + print(serializer.errors) + error_details = { + "message": "Invalid user data provided.", + "errors": serializer.errors, + } + return Response(error_details, status=status.HTTP_400_BAD_REQUEST) +======= @api_view(['GET']) @permission_classes([AllowAny]) @@ -80,3 +134,4 @@ def put(self, request, clerk_id): return Response(error_details, status=status.HTTP_400_BAD_REQUEST) +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 diff --git a/frontend/bitmatch/package-lock.json b/frontend/bitmatch/package-lock.json index 94d3783..afe1927 100644 --- a/frontend/bitmatch/package-lock.json +++ b/frontend/bitmatch/package-lock.json @@ -9,7 +9,10 @@ "version": "0.0.0", "dependencies": { "@clerk/clerk-react": "^5.24.0", +<<<<<<< HEAD +======= "@google/genai": "^0.10.0", +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-label": "^2.1.2", diff --git a/frontend/bitmatch/package.json b/frontend/bitmatch/package.json index 68d6e6f..0d0af61 100644 --- a/frontend/bitmatch/package.json +++ b/frontend/bitmatch/package.json @@ -11,7 +11,10 @@ }, "dependencies": { "@clerk/clerk-react": "^5.24.0", +<<<<<<< HEAD +======= "@google/genai": "^0.10.0", +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-label": "^2.1.2", diff --git a/frontend/bitmatch/src/App.jsx b/frontend/bitmatch/src/App.jsx index d99e804..b4fa804 100644 --- a/frontend/bitmatch/src/App.jsx +++ b/frontend/bitmatch/src/App.jsx @@ -15,7 +15,10 @@ import ProjectListPage from "./views/ProjectListPage"; import ProjectDetailPage from "./views/IndividualProjectPage"; import AddProjectPage from "./views/AddProjectPage"; import ProfilePage from "./views/ProfilePage"; +<<<<<<< HEAD +======= import AboutPage from "./views/AboutPage"; +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 import OnboardPage from "./views/OnboardPage"; import InterestPage from "./components/onboarding/Interest"; @@ -34,9 +37,14 @@ function AppRoutes() { const pathname = location.pathname; const isLanding = pathname === "/" && !isSignedIn; const isOnboard = pathname.startsWith("/onboard"); +<<<<<<< HEAD + + const shouldUseContainer = !isLanding && !isOnboard; +======= const isAbout = pathname.startsWith("/about"); const shouldUseContainer = !isLanding && !isOnboard && !isAbout; +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 const layoutClass = shouldUseContainer ? "container mx-auto px-4 py-16 pb-6 min-h-screen" @@ -89,7 +97,11 @@ function AppRoutes() { } /> >>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 element={ @@ -98,6 +110,18 @@ function AppRoutes() { /> {/* Onboarding */} +<<<<<<< HEAD + }> + } /> + } /> + } /> + } /> + } /> + + + + +======= +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 ); diff --git a/frontend/bitmatch/src/components/navbar.jsx b/frontend/bitmatch/src/components/navbar.jsx index c37b4b5..90ff922 100644 --- a/frontend/bitmatch/src/components/navbar.jsx +++ b/frontend/bitmatch/src/components/navbar.jsx @@ -15,12 +15,18 @@ export default function Navbar({ links = [] }) { const { user } = useUser(); const defaultLinks = [ { href: "/about", label: "About" }, +<<<<<<< HEAD + { href: "/browse", label: "Browse" }, + { href: "/contact", label: "Contact" }, + { href: "/my-profile", label: "My Profile" }, +======= ...(user?.id ? [ { href: "/project-list", label: "Browse" }, { href: `/profile/${user.id}`, label: "My Profile" }, ] : []), +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 ]; const [showModal, setShowModal] = useState(false); diff --git a/frontend/bitmatch/src/components/onboarding/CreateProfile.jsx b/frontend/bitmatch/src/components/onboarding/CreateProfile.jsx index 1feb700..32e014e 100644 --- a/frontend/bitmatch/src/components/onboarding/CreateProfile.jsx +++ b/frontend/bitmatch/src/components/onboarding/CreateProfile.jsx @@ -1,3 +1,56 @@ +<<<<<<< HEAD +'use client' + +import { + forwardRef, + useEffect, + useState, + useImperativeHandle, +} from 'react' +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Badge } from '@/components/ui/badge' +import { X } from 'lucide-react' + +// ✅ Component with forwardRef +const CreateProfile = forwardRef(({ onDataChange, formData }, ref) => { + const [firstName, setFirstName] = useState(formData?.first_name || '') + const [lastName, setLastName] = useState(formData?.last_name || '') + const [colleges, setColleges] = useState(formData?.colleges || []) + const [newCollege, setNewCollege] = useState('') + const [errors, setErrors] = useState({}) + + // Send data to parent on change + useEffect(() => { + onDataChange({ first_name: firstName, last_name: lastName, colleges }) + }, [firstName, lastName, colleges]) + + // Validation logic exposed via ref + useImperativeHandle(ref, () => ({ + validate: () => { + const newErrors = {} + if (!firstName.trim()) newErrors.firstName = 'First name is required.' + if (!lastName.trim()) newErrors.lastName = 'Last name is required.' + if (colleges.length === 0) newErrors.colleges = 'At least one college is required.' + setErrors(newErrors) + return Object.keys(newErrors).length === 0 + }, + })) + + const handleAddCollege = () => { + const trimmed = newCollege.trim() + if (trimmed && !colleges.includes(trimmed)) { + const updated = [...colleges, trimmed].sort() + setColleges(updated) + setNewCollege('') + } + } + + const handleRemoveCollege = (college) => { + const updated = colleges.filter((c) => c !== college).sort() + setColleges(updated) + } +======= "use client"; import { forwardRef, useEffect, useState, useImperativeHandle } from "react"; @@ -47,6 +100,7 @@ const CreateProfile = forwardRef(({ onDataChange, formData }, ref) => { return Object.keys(newErrors).length === 0; }, })); +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 return (
@@ -61,9 +115,13 @@ const CreateProfile = forwardRef(({ onDataChange, formData }, ref) => { onChange={(e) => setFirstName(e.target.value)} placeholder="Enter your first name" /> +<<<<<<< HEAD + {errors.firstName &&

{errors.firstName}

} +======= {errors.firstName && (

{errors.firstName}

)} +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84
{/* Last Name */} @@ -77,6 +135,55 @@ const CreateProfile = forwardRef(({ onDataChange, formData }, ref) => { onChange={(e) => setLastName(e.target.value)} placeholder="Enter your last name" /> +<<<<<<< HEAD + {errors.lastName &&

{errors.lastName}

} + + + {/* Colleges */} +
+ +
+ setNewCollege(e.target.value)} + placeholder="Add college or university" + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault() + handleAddCollege() + } + }} + /> + +
+ +
+ {colleges.map((college) => ( + + {college} + + + ))} +
+ + {errors.colleges &&

{errors.colleges}

} +
+ + ) +}) + +// ✅ Export wrapped with forwardRef +export default CreateProfile +======= {errors.lastName && (

{errors.lastName}

)} @@ -158,3 +265,4 @@ const CreateProfile = forwardRef(({ onDataChange, formData }, ref) => { }); export default CreateProfile; +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 diff --git a/frontend/bitmatch/src/components/onboarding/Interest.jsx b/frontend/bitmatch/src/components/onboarding/Interest.jsx index c7e81ad..815b398 100644 --- a/frontend/bitmatch/src/components/onboarding/Interest.jsx +++ b/frontend/bitmatch/src/components/onboarding/Interest.jsx @@ -1,3 +1,49 @@ +<<<<<<< HEAD +'use client' + +import { + forwardRef, + useEffect, + useState, + useImperativeHandle, +} from 'react' +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { X } from 'lucide-react' + +const Interest = forwardRef(({ onDataChange, formData }, ref) => { + const [interests, setInterests] = useState(formData?.interests || []) + const [newInterest, setNewInterest] = useState('') + const [error, setError] = useState('') + + useEffect(() => { + onDataChange({ interests }) + }, [interests]) + + const validate = () => { + if (interests.length === 0) { + setError('Please add at least one interest.') + return false + } + setError('') + return true + } + + useImperativeHandle(ref, () => ({ validate })) + + const handleAdd = () => { + const trimmed = newInterest.trim() + if (trimmed && !interests.includes(trimmed)) { + setInterests([...interests, trimmed].sort()) + setNewInterest('') + setError('') + } + } + + const handleRemove = (interest) => { + setInterests(interests.filter((i) => i !== interest)) + } +======= "use client"; import { forwardRef, useEffect, useState, useImperativeHandle } from "react"; @@ -37,12 +83,17 @@ const Interest = forwardRef(({ onDataChange, formData }, ref) => { const handleRemove = (interest) => { setInterests(interests.filter((i) => i !== interest)); }; +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 return (
@@ -51,9 +102,15 @@ const Interest = forwardRef(({ onDataChange, formData }, ref) => { onChange={(e) => setNewInterest(e.target.value)} placeholder="Type a category" onKeyDown={(e) => { +<<<<<<< HEAD + if (e.key === 'Enter') { + e.preventDefault() + handleAdd() +======= if (e.key === "Enter") { e.preventDefault(); handleAdd(); +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 } }} /> @@ -78,7 +135,14 @@ const Interest = forwardRef(({ onDataChange, formData }, ref) => { ))}
+<<<<<<< HEAD + ) +}) + +export default Interest +======= ); }); export default Interest; +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 diff --git a/frontend/bitmatch/src/components/onboarding/Location.jsx b/frontend/bitmatch/src/components/onboarding/Location.jsx index 5e87e8e..d69dd8c 100644 --- a/frontend/bitmatch/src/components/onboarding/Location.jsx +++ b/frontend/bitmatch/src/components/onboarding/Location.jsx @@ -1,3 +1,22 @@ +<<<<<<< HEAD +'use client' + +import { + forwardRef, + useEffect, + useState, + useImperativeHandle, +} from 'react' +import { Checkbox } from '@/components/ui/checkbox' + +const Location = forwardRef(({ onDataChange, formData }, ref) => { + const [location, setLocation] = useState(formData?.location || '') + const [preferences, setPreferences] = useState( + formData?.location_preferences?.filter(p => p !== '') || ["Remote friendly projects"] + ) + const [other, setOther] = useState('') + const [errors, setErrors] = useState({}) +======= "use client"; import { forwardRef, useEffect, useState, useImperativeHandle } from "react"; @@ -12,11 +31,40 @@ const Location = forwardRef(({ onDataChange, formData }, ref) => { ); const [other, setOther] = useState(""); const [errors, setErrors] = useState({}); +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 const options = [ "Near my location", "Near my University or College location", "Remote friendly projects", +<<<<<<< HEAD + ] + + useEffect(() => { + const allPreferences = [...preferences, ...(other ? [other] : [])] + onDataChange({ location, location_preferences: allPreferences }) + }, [location, preferences, other]) + + const validate = () => { + const newErrors = {} + if (!location.trim()) newErrors.location = 'Location is required.' + if (preferences.length === 0 && !other.trim()) { + newErrors.preferences = 'Please select or enter at least one preference.' + } + setErrors(newErrors) + return Object.keys(newErrors).length === 0 + } + + useImperativeHandle(ref, () => ({ validate })) + + const togglePreference = (value) => { + setPreferences((prev) => + prev.includes(value) + ? prev.filter((p) => p !== value) + : [...prev, value] + ) + } +======= ]; useEffect(() => { @@ -41,6 +89,7 @@ const Location = forwardRef(({ onDataChange, formData }, ref) => { prev.includes(value) ? prev.filter((p) => p !== value) : [...prev, value] ); }; +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 return (
@@ -54,15 +103,23 @@ const Location = forwardRef(({ onDataChange, formData }, ref) => { onChange={(e) => setLocation(e.target.value)} placeholder="Enter your location" /> +<<<<<<< HEAD + {errors.location &&

{errors.location}

} +======= {errors.location && (

{errors.location}

)} +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84
{options.map((option) => ( @@ -72,6 +129,29 @@ const Location = forwardRef(({ onDataChange, formData }, ref) => { checked={preferences.includes(option)} onCheckedChange={() => togglePreference(option)} /> +<<<<<<< HEAD + +
+ ))} + +
+ + setOther(e.target.value)} + placeholder="Add custom preference" + /> +
+ + {errors.preferences &&

{errors.preferences}

} + + + ) +}) + +export default Location +======= @@ -87,3 +167,4 @@ const Location = forwardRef(({ onDataChange, formData }, ref) => { }); export default Location; +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 diff --git a/frontend/bitmatch/src/components/project/EditProfileDialog.jsx b/frontend/bitmatch/src/components/project/EditProfileDialog.jsx index 9ae73d8..6253b4f 100644 --- a/frontend/bitmatch/src/components/project/EditProfileDialog.jsx +++ b/frontend/bitmatch/src/components/project/EditProfileDialog.jsx @@ -1,5 +1,15 @@ "use client"; import { useState } from "react"; +<<<<<<< HEAD +import { X, Plus, Edit2, Trash2, Mail, Phone, Globe } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +======= import { X, Plus, Edit2, Trash2, Mail } from "lucide-react"; import { Button } from "@/components/ui/button"; import { @@ -8,12 +18,486 @@ import { DialogHeader, DialogTitle, DialogFooter, +>>>>>>> d273cc17c82f58fa65fb0d6a01dc2146af9a0b84 } from "@/components/ui/Dialog"; import { ScrollArea } from "@/components/ui/ScrollArea"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/Label"; import { Textarea } from "@/components/ui/Textarea"; import { Card } from "@/components/ui/Card"; +<<<<<<< HEAD + +// Default dummy user data +const DEFAULT_USER_DATA = { + name: "John Doe", + title: "Software Engineer", + bio: "Passionate about building great user experiences and scalable systems.", + email: "john.doe@example.com", + phone: "+1 (555) 123-4567", + website: "https://johndoe.dev", + skills: ["JavaScript", "React", "Node.js"], + experience: [ + { + company: "Tech Corp", + position: "Senior Developer", + duration: "2020 - Present" + }, + { + company: "Startup Inc", + position: "Frontend Developer", + duration: "2018 - 2020" + } + ], + education: [ + { + institution: "State University", + degree: "B.S. Computer Science", + year: "2018" + } + ] +}; + +export function EditProfileDialog({ open, onOpenChange, onSave }) { + const [userData, setUserData] = useState(DEFAULT_USER_DATA); + const [newSkill, setNewSkill] = useState(""); + const [editingSkillIndex, setEditingSkillIndex] = useState(-1); + const [newExperience, setNewExperience] = useState({ company: "", position: "", duration: "" }); + const [editingExperienceIndex, setEditingExperienceIndex] = useState(-1); + const [newEducation, setNewEducation] = useState({ institution: "", degree: "", year: "" }); + const [editingEducationIndex, setEditingEducationIndex] = useState(-1); + + const handleChange = (field, value) => { + setUserData(prev => ({ ...prev, [field]: value })); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + // In a real app, you would call onSave with the updated data + console.log("Profile data to save:", userData); + onOpenChange(false); + }; + + // Skills management + const addSkill = () => { + if (!newSkill.trim()) return; + + if (editingSkillIndex >= 0) { + const updatedSkills = [...userData.skills]; + updatedSkills[editingSkillIndex] = newSkill; + setUserData(prev => ({ ...prev, skills: updatedSkills })); + setEditingSkillIndex(-1); + } else { + setUserData(prev => ({ + ...prev, + skills: [...prev.skills, newSkill], + })); + } + setNewSkill(""); + }; + + const removeSkill = (index) => { + const updatedSkills = userData.skills.filter((_, i) => i !== index); + setUserData(prev => ({ ...prev, skills: updatedSkills })); + }; + + const editSkill = (index) => { + setNewSkill(userData.skills[index]); + setEditingSkillIndex(index); + }; + + // Experience management + const addExperience = () => { + if (!newExperience.company.trim() || !newExperience.position.trim()) return; + + if (editingExperienceIndex >= 0) { + const updatedExperiences = [...userData.experience]; + updatedExperiences[editingExperienceIndex] = { ...newExperience }; + setUserData(prev => ({ ...prev, experience: updatedExperiences })); + setEditingExperienceIndex(-1); + } else { + setUserData(prev => ({ + ...prev, + experience: [...prev.experience, { ...newExperience }], + })); + } + setNewExperience({ company: "", position: "", duration: "" }); + }; + + const removeExperience = (index) => { + const updatedExperiences = userData.experience.filter((_, i) => i !== index); + setUserData(prev => ({ ...prev, experience: updatedExperiences })); + }; + + const editExperience = (index) => { + setNewExperience({ ...userData.experience[index] }); + setEditingExperienceIndex(index); + }; + + // Education management + const addEducation = () => { + if (!newEducation.institution.trim() || !newEducation.degree.trim()) return; + + if (editingEducationIndex >= 0) { + const updatedEducation = [...userData.education]; + updatedEducation[editingEducationIndex] = { ...newEducation }; + setUserData(prev => ({ ...prev, education: updatedEducation })); + setEditingEducationIndex(-1); + } else { + setUserData(prev => ({ + ...prev, + education: [...prev.education, { ...newEducation }], + })); + } + setNewEducation({ institution: "", degree: "", year: "" }); + }; + + const removeEducation = (index) => { + const updatedEducation = userData.education.filter((_, i) => i !== index); + setUserData(prev => ({ ...prev, education: updatedEducation })); + }; + + const editEducation = (index) => { + setNewEducation({ ...userData.education[index] }); + setEditingEducationIndex(index); + }; + + return ( + + + +
+ + Edit Profile + + +
+

+ Update your profile information. +

+
+ +
+ {/* Basic Info Section */} +
+
+ + handleChange("name", e.target.value)} + className="w-full" + placeholder="Your full name" + /> +
+
+ + handleChange("title", e.target.value)} + className="w-full" + placeholder="Your professional title" + /> +
+
+ +
+ +