11"use client" ;
22import axios from "axios" ;
3- import { useState } from "react" ;
3+ import { useState , useEffect } from "react" ;
44import { X , Plus , Edit2 , Trash2 } from "lucide-react" ;
55import { Button } from "@/components/ui/button" ;
66import {
@@ -26,6 +26,12 @@ export function EditProjectDialog({ open, onOpenChange, projectData, onSave }) {
2626 const [ newPosition , setNewPosition ] = useState ( { title : "" } ) ;
2727 const [ editingIndex , setEditingIndex ] = useState ( - 1 ) ;
2828 const [ sliderImages , setSliderImages ] = useState ( projectData . images || [ ] ) ;
29+ const [ interests , setInterests ] = useState ( projectData . interest_tags || [ ] ) ;
30+ const [ skills , setSkills ] = useState ( projectData . skill_tags || [ ] ) ;
31+ const [ newInterest , setNewInterest ] = useState ( "" ) ;
32+ const [ newSkill , setNewSkill ] = useState ( "" ) ;
33+ const [ interestError , setInterestError ] = useState ( "" ) ;
34+ const [ skillError , setSkillError ] = useState ( "" ) ;
2935
3036 const handleImageUrlChange = ( index , e ) => {
3137 const newSliderImages = [ ...sliderImages ] ;
@@ -37,6 +43,59 @@ export function EditProjectDialog({ open, onOpenChange, projectData, onSave }) {
3743 handleChange ( "images" , filteredImages ) ;
3844 } ;
3945
46+ // For Interests
47+ const handleInterestChange = ( e ) => {
48+ setNewInterest ( e . target . value ) ;
49+ setInterestError ( "" ) ; // Reset error message
50+ } ;
51+
52+ const handleAddInterest = ( ) => {
53+ if ( newInterest . trim ( ) ) {
54+ setInterests ( ( prev ) => {
55+ const updatedInterests = [ ...prev , newInterest . trim ( ) ] ;
56+ handleChange ( "interest_tags" , updatedInterests ) ; // Call handleChange with updated interests
57+ return updatedInterests ;
58+ } ) ;
59+ setNewInterest ( "" ) ; // Clear input after adding
60+ } else {
61+ setInterestError ( "Interest can't be empty." ) ;
62+ }
63+ } ;
64+
65+ const handleSkillChange = ( e ) => {
66+ setNewSkill ( e . target . value ) ;
67+ setSkillError ( "" ) ;
68+ } ;
69+
70+ const handleAddSkill = ( ) => {
71+ if ( newSkill . trim ( ) ) {
72+ setSkills ( ( prev ) => {
73+ const updatedSkills = [ ...prev , newSkill . trim ( ) ] ;
74+ handleChange ( "skill_tags" , updatedSkills ) ;
75+ return updatedSkills ;
76+ } ) ;
77+ setNewSkill ( "" ) ;
78+ } else {
79+ setSkillError ( "Skill can't be empty." ) ;
80+ }
81+ } ;
82+
83+ const handleRemoveInterest = ( index ) => {
84+ setInterests ( ( prev ) => {
85+ const updatedInterests = prev . filter ( ( _ , i ) => i !== index ) ;
86+ handleChange ( "interest_tags" , updatedInterests ) ;
87+ return updatedInterests ;
88+ } ) ;
89+ } ;
90+
91+ const handleRemoveSkill = ( index ) => {
92+ setSkills ( ( prev ) => {
93+ const updatedSkills = prev . filter ( ( _ , i ) => i !== index ) ;
94+ handleChange ( "skill_tags" , updatedSkills ) ;
95+ return updatedSkills ;
96+ } ) ;
97+ } ;
98+
4099 const handleChange = ( field , value ) => {
41100 setFormData ( ( prev ) => ( { ...prev , [ field ] : value } ) ) ;
42101 } ;
@@ -95,6 +154,17 @@ export function EditProjectDialog({ open, onOpenChange, projectData, onSave }) {
95154 setEditingIndex ( index ) ;
96155 } ;
97156
157+ useEffect ( ( ) => {
158+ if ( open ) {
159+ document . body . style . overflow = "hidden" ;
160+ } else {
161+ document . body . style . overflow = "" ;
162+ }
163+ return ( ) => {
164+ document . body . style . overflow = "" ;
165+ } ;
166+ } , [ open ] ) ;
167+
98168 return (
99169 < Dialog
100170 className = "flex-1 custom-scrollbar"
@@ -383,6 +453,102 @@ export function EditProjectDialog({ open, onOpenChange, projectData, onSave }) {
383453 </ div >
384454 </ div >
385455
456+ < div className = "mt-6" >
457+ < label className = "block font-medium mb-2" >
458+ Categories/Interests
459+ </ label >
460+ < div className = "flex items-center space-x-2 mb-2" >
461+ < input
462+ type = "text"
463+ value = { newInterest }
464+ onChange = { handleInterestChange }
465+ className = "flex-grow border rounded-md p-2 focus:ring-blue-500 focus:border-blue-500"
466+ placeholder = "e.g., Backend, Frontend, DevOps, AI"
467+ />
468+ < button
469+ type = "button"
470+ onClick = { handleAddInterest }
471+ className = "bg-black text-white px-4 py-2 rounded-md hover:bg-gray-800 transition-colors text-sm"
472+ >
473+ Add Interest
474+ </ button >
475+ </ div >
476+ { interestError && (
477+ < p className = "text-red-500 text-sm mt-1" > { interestError } </ p >
478+ ) }
479+ < div className = "mt-3 border rounded-md overflow-hidden" >
480+ { interests . length === 0 ? (
481+ < p className = "text-sm text-gray-500 px-4 py-3" >
482+ No interests added yet.
483+ </ p >
484+ ) : (
485+ interests . map ( ( interest , index ) => (
486+ < div
487+ key = { index }
488+ className = "flex items-center justify-between px-4 py-2 border-b last:border-b-0 bg-gray-50"
489+ >
490+ < span className = "text-sm" > { interest } </ span >
491+ < button
492+ type = "button"
493+ onClick = { ( ) => handleRemoveInterest ( index ) }
494+ className = "text-red-500 hover:text-red-700 transition-colors font-bold"
495+ aria-label = { `Remove interest: ${ interest } ` }
496+ >
497+ ✕
498+ </ button >
499+ </ div >
500+ ) )
501+ ) }
502+ </ div >
503+ </ div >
504+
505+ < div className = "mt-6" >
506+ < label className = "block font-medium mb-2" > Desired Skills</ label >
507+ < div className = "flex items-center space-x-2 mb-2" >
508+ < input
509+ type = "text"
510+ value = { newSkill }
511+ onChange = { handleSkillChange }
512+ className = "flex-grow border rounded-md p-2 focus:ring-blue-500 focus:border-blue-500"
513+ placeholder = "e.g., JavaScript, Figma, Django"
514+ />
515+ < button
516+ type = "button"
517+ onClick = { handleAddSkill }
518+ className = "bg-black text-white px-4 py-2 rounded-md hover:bg-gray-800 transition-colors text-sm"
519+ >
520+ Add Skill
521+ </ button >
522+ </ div >
523+ { skillError && (
524+ < p className = "text-red-500 text-sm mt-1" > { skillError } </ p >
525+ ) }
526+ < div className = "mt-3 border rounded-md overflow-hidden" >
527+ { skills . length === 0 ? (
528+ < p className = "text-sm text-gray-500 px-4 py-3" >
529+ No skills added yet.
530+ </ p >
531+ ) : (
532+ skills . map ( ( skill , index ) => (
533+ < div
534+ key = { index }
535+ className = "flex items-center justify-between px-4 py-2 border-b last:border-b-0 bg-gray-50"
536+ >
537+ < span className = "text-sm" > { skill } </ span >
538+ < button
539+ type = "button"
540+ onClick = { ( ) => handleRemoveSkill ( index ) }
541+ className = "text-red-500 hover:text-red-700 transition-colors font-bold"
542+ aria-label = { `Remove skill: ${ skill } ` }
543+ >
544+ ✕
545+ </ button >
546+ </ div >
547+ ) )
548+ ) }
549+ </ div >
550+ </ div >
551+
386552 < DialogFooter className = "pt-2" >
387553 < Button
388554 variant = "outline"
0 commit comments