iris_backend / src /components /ProfileTab.jsx
Saandraahh's picture
Update ProfileTab.jsx
411b8bd unverified
import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
// --- Helper Component for Tag Inputs ---
const TagInput = ({ name, value, onChange, placeholder, isEditing }) => {
const [inputValue, setInputValue] = useState("");
// Convert string "A, B, C" to array ["A", "B", "C"]
const tags = value ? value.split(',').map(s => s.trim()).filter(Boolean) : [];
const handleAddParam = (val) => {
const trimmed = val.trim();
if (trimmed && !tags.includes(trimmed)) {
const newTags = [...tags, trimmed];
onChange({ target: { name, value: newTags.join(', ') } });
}
setInputValue("");
};
const handleKeyDown = (e) => {
if (e.key === 'Enter' || e.key === ',') {
e.preventDefault();
handleAddParam(inputValue);
} else if (e.key === 'Backspace' && !inputValue && tags.length > 0) {
handleRemoveTag(tags.length - 1);
}
};
const handleRemoveTag = (index) => {
const newTags = tags.filter((_, i) => i !== index);
onChange({ target: { name, value: newTags.join(', ') } });
};
return (
<div style={{
display: 'flex', flexWrap: 'wrap', gap: '0.5rem',
padding: '0.5rem', borderRadius: '0.5rem',
border: isEditing ? '1px solid rgba(251, 191, 36, 0.3)' : 'none',
backgroundColor: isEditing ? 'rgba(255,255,255,0.05)' : 'transparent',
minHeight: '2.5rem'
}}>
{tags.map((tag, index) => (
<span key={index} style={{
backgroundColor: 'rgba(251, 191, 36, 0.15)',
color: '#FCD34D',
padding: '0.25rem 0.75rem',
borderRadius: '9999px',
fontSize: '0.875rem',
display: 'flex', alignItems: 'center', gap: '0.5rem'
}}>
{tag}
{isEditing && (
<button
onClick={() => handleRemoveTag(index)}
style={{ background: 'none', border: 'none', color: '#FCD34D', cursor: 'pointer', fontSize: '1rem', padding: 0 }}
>
×
</button>
)}
</span>
))}
{isEditing && (
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyDown={handleKeyDown}
onBlur={() => handleAddParam(inputValue)} // Add on blur too
placeholder={tags.length === 0 ? placeholder : ""}
style={{
background: 'transparent', border: 'none', color: 'white',
outline: 'none', flex: 1, minWidth: '100px'
}}
/>
)}
{!isEditing && tags.length === 0 && <span style={{ color: '#6B7280' }}>Not set</span>}
</div>
);
};
const ProfileTab = ({
profileData,
isEditing,
handleProfileChange,
handleExperienceChange,
handleAddExperience,
handleAddEducation,
handleEducationChange,
showFullProfile,
}) => {
if (!profileData) return null;
const inputStyles = {
width: '100%', padding: '0.75rem', borderRadius: '0.5rem',
border: '1px solid rgba(251, 191, 36, 0.3)',
backgroundColor: 'rgba(255,255,255,0.1)', color: 'white'
};
const labelStyles = { display: 'block', marginBottom: '0.5rem', color: '#d1d5db' };
const checkboxLabelStyles = { display: 'flex', alignItems: 'center', gap: '0.5rem', color: '#d1d5db' };
const checkboxStyles = { width: '1.15em', height: '1.15em', accentColor: '#FBBF24' };
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem', marginTop: '1.5rem' }}>
{/* Basic Info */}
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1.5rem' }}>
<div>
<label style={labelStyles}>Full Name</label>
{isEditing ? (<input type="text" name="full_name" value={profileData?.full_name || ''} onChange={handleProfileChange} style={inputStyles} placeholder="e.g., John Doe" />) : (<p>{profileData?.full_name || 'Not set'}</p>)}
</div>
<div>
<label style={labelStyles}>Headline</label>
{isEditing ? (<input type="text" name="headline" value={profileData?.headline || ''} onChange={handleProfileChange} style={inputStyles} placeholder="e.g., Senior Software Engineer" />) : (<p>{profileData?.headline || 'Not set'}</p>)}
</div>
</div>
{/* Summary */}
<div>
<label style={labelStyles}>Summary</label>
{isEditing ? (<textarea name="summary" value={profileData?.summary || ''} onChange={handleProfileChange} rows="4" style={inputStyles} placeholder="Tell us about yourself..." />) : (<p>{profileData?.summary || 'Not set'}</p>)}
</div>
{/* Extended Profile Fields */}
<AnimatePresence>
{showFullProfile && (
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1.5rem', marginTop: '1.5rem' }}>
<div>
<label style={labelStyles}>Email</label>
{isEditing ? (<input type="email" name="email" value={profileData?.email || ''} onChange={handleProfileChange} style={inputStyles} />) : (<p>{profileData?.email || 'Not set'}</p>)}
</div>
<div>
<label style={labelStyles}>Phone</label>
{isEditing ? (<input type="tel" name="phone" value={profileData?.phone || ''} onChange={handleProfileChange} style={inputStyles} />) : (<p>{profileData?.phone || 'Not set'}</p>)}
</div>
<div>
<label style={labelStyles}>Address</label>
{isEditing ? (<input type="text" name="address" value={profileData?.address || ''} onChange={handleProfileChange} style={inputStyles} />) : (<p>{profileData?.address || 'Not set'}</p>)}
</div>
<div>
<label style={labelStyles}>Current Position</label>
{isEditing ? (<input type="text" name="current_position" value={profileData?.current_position || ''} onChange={handleProfileChange} style={inputStyles} />) : (<p>{profileData?.current_position || 'Not set'}</p>)}
</div>
<div>
<label style={labelStyles}>Years of Experience</label>
{isEditing ? (<input type="text" name="experience_years" value={profileData?.experience_years || ''} onChange={handleProfileChange} style={inputStyles} />) : (<p>{profileData?.experience_years || 'Not set'}</p>)}
</div>
<div>
<label style={labelStyles}>Desired Salary</label>
{isEditing ? (<input type="text" name="desired_salary" value={profileData?.desired_salary || ''} onChange={handleProfileChange} style={inputStyles} />) : (<p>{profileData?.desired_salary || 'Not set'}</p>)}
</div>
<div>
<label style={labelStyles}>LinkedIn</label>
{isEditing ? (<input type="url" name="linkedin" value={profileData?.linkedin || ''} onChange={handleProfileChange} style={inputStyles} />) : (<a href={profileData?.linkedin || '#'} target="_blank" rel="noreferrer" style={{ color: '#93C5FD' }}>{profileData?.linkedin || 'Not set'}</a>)}
</div>
<div>
<label style={labelStyles}>GitHub</label>
{isEditing ? (<input type="url" name="github" value={profileData?.github || ''} onChange={handleProfileChange} style={inputStyles} />) : (<a href={profileData?.github || '#'} target="_blank" rel="noreferrer" style={{ color: '#93C5FD' }}>{profileData?.github || 'Not set'}</a>)}
</div>
<div>
<label style={labelStyles}>Portfolio</label>
{isEditing ? (<input type="url" name="portfolio" value={profileData?.portfolio || ''} onChange={handleProfileChange} style={inputStyles} />) : (<a href={profileData?.portfolio || '#'} target="_blank" rel="noreferrer" style={{ color: '#93C5FD' }}>{profileData?.portfolio || 'Not set'}</a>)}
</div>
{/* TAG INPUTS */}
<div style={{ gridColumn: 'span 2' }}>
<label style={labelStyles}>Technical Skills</label>
<TagInput
name="technical_skills"
value={profileData?.technical_skills}
onChange={handleProfileChange}
isEditing={isEditing}
placeholder="Add skill (press Enter)..."
/>
</div>
<div style={{ gridColumn: 'span 2' }}>
<label style={labelStyles}>Certifications</label>
<TagInput
name="certifications"
value={profileData?.certifications}
onChange={handleProfileChange}
isEditing={isEditing}
placeholder="Add certification (press Enter)..."
/>
</div>
<div style={{ gridColumn: 'span 2' }}>
<label style={labelStyles}>Languages</label>
<TagInput
name="languages"
value={profileData?.languages}
onChange={handleProfileChange}
isEditing={isEditing}
placeholder="Add language (press Enter)..."
/>
</div>
<div style={{ alignSelf: 'center' }}>
{isEditing ? (
<label style={checkboxLabelStyles}><input type="checkbox" name="willing_to_relocate" checked={!!profileData?.willing_to_relocate} onChange={handleProfileChange} style={checkboxStyles} /> Willing to Relocate</label>
) : (<p>{profileData?.willing_to_relocate ? 'Willing to relocate' : 'Not willing to relocate'}</p>)}
</div>
<div style={{ alignSelf: 'center' }}>
{isEditing ? (
<label style={checkboxLabelStyles}><input type="checkbox" name="available_remote" checked={!!profileData?.available_remote} onChange={handleProfileChange} style={checkboxStyles} /> Available for Remote Work</label>
) : (<p>{profileData?.available_remote ? 'Available for remote' : 'Not available for remote'}</p>)}
</div>
</div>
</motion.div>
)}
</AnimatePresence>
{/* Work Experience Section */}
<div>
<h3 style={{ fontSize: '1.25rem', fontWeight: 'bold', marginBottom: '1.5rem', marginTop: '1.5rem' }}>Work Experience</h3>
{isEditing ? (
<>
{(profileData?.work_experience || []).map((exp, index) => (
<div key={exp.id || index} style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: '1rem', marginBottom: '1rem' }}>
<input type="text" name="company" value={exp.company || ''} onChange={(e) => handleExperienceChange(index, e)} placeholder="Company" style={inputStyles} />
<input type="text" name="role" value={exp.role || ''} onChange={(e) => handleExperienceChange(index, e)} placeholder="Role" style={inputStyles} />
<input type="text" name="years" value={exp.years || ''} onChange={(e) => handleExperienceChange(index, e)} placeholder="Years" style={inputStyles} />
</div>
))}
<button
onClick={handleAddExperience}
style={{
backgroundColor: 'rgba(251, 191, 36, 0.2)',
color: '#FCD34D',
padding: '0.5rem 1rem',
borderRadius: '0.5rem',
border: 'none',
cursor: 'pointer'
}}
>
+ Add More Experience
</button>
</>
) : (
<div>
{profileData?.work_experience && profileData.work_experience.length > 0 ? (
profileData.work_experience.map((exp, index) => (
<div key={exp.id || index} style={{ marginBottom: '1rem' }}>
<p style={{ fontWeight: 'bold', margin: 0 }}>{exp.role}</p>
<p style={{ color: '#d1d5db', margin: 0 }}>{exp.company} • {exp.years} years</p>
</div>
))
) : (
<p>No work experience added.</p>
)}
</div>
)}
</div>
{/* Education Section */}
<div>
<h3 style={{ fontSize: '1.25rem', fontWeight: 'bold', marginBottom: '1.5rem', marginTop: '1.5rem' }}>Education</h3>
{isEditing ? (
<>
{(profileData?.education || []).map((edu, index) => (
<div key={edu.id || index} style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: '1rem', marginBottom: '1rem' }}>
<input type="text" name="course" value={edu.course || ''} onChange={(e) => handleEducationChange(index, e)} placeholder="Course/Degree" style={inputStyles} />
<input type="text" name="institution" value={edu.institution || ''} onChange={(e) => handleEducationChange(index, e)} placeholder="Institution" style={inputStyles} />
<input type="text" name="year" value={edu.year || ''} onChange={(e) => handleEducationChange(index, e)} placeholder="Year" style={inputStyles} />
</div>
))}
<button
onClick={handleAddEducation}
style={{
backgroundColor: 'rgba(251, 191, 36, 0.2)',
color: '#FCD34D',
padding: '0.5rem 1rem',
borderRadius: '0.5rem',
border: 'none',
cursor: 'pointer'
}}
>
+ Add More Education
</button>
</>
) : (
<div>
{profileData?.education && profileData.education.length > 0 ? (
profileData.education.map((edu, index) => (
<div key={edu.id || index} style={{ marginBottom: '1rem' }}>
<p style={{ fontWeight: 'bold', margin: 0 }}>{edu.course}</p>
<p style={{ color: '#d1d5db', margin: 0 }}>{edu.institution} • {edu.year}</p>
</div>
))
) : (
<p>No education added.</p>
)}
</div>
)}
</div>
{/* Projects Section */}
<div>
<h3 style={{ fontSize: '1.25rem', fontWeight: 'bold', marginBottom: '1.5rem', marginTop: '1.5rem' }}>Projects</h3>
{isEditing ? (
<>
{(profileData?.projects || []).map((proj, index) => (
<div key={index} style={{ marginBottom: '1.5rem', padding: '1rem', backgroundColor: 'rgba(255,255,255,0.05)', borderRadius: '0.5rem' }}>
<div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: '0.5rem', marginBottom: '0.5rem' }}>
<input type="text" name="title" value={proj.title || ''} onChange={(e) => {
const newProjects = [...(profileData.projects || [])];
newProjects[index] = { ...newProjects[index], title: e.target.value };
handleProfileChange({ target: { name: 'projects', value: newProjects } });
}} placeholder="Project Title" style={{ ...inputStyles, marginBottom: '0.5rem' }} />
<textarea name="description" value={proj.description || ''} onChange={(e) => {
const newProjects = [...(profileData.projects || [])];
newProjects[index] = { ...newProjects[index], description: e.target.value };
handleProfileChange({ target: { name: 'projects', value: newProjects } });
}} placeholder="Description" rows="2" style={{ ...inputStyles, marginBottom: '0.5rem' }} />
<TagInput
name={`projects[${index}].technologies_used`}
value={Array.isArray(proj.technologies_used) ? proj.technologies_used.join(', ') : (proj.technologies_used || '')}
onChange={(e) => {
const newProjects = [...(profileData.projects || [])];
const val = e.target.value;
newProjects[index] = { ...newProjects[index], technologies_used: val.split(',').map(s => s.trim()).filter(Boolean) };
handleProfileChange({ target: { name: 'projects', value: newProjects } });
}}
isEditing={true}
placeholder="Technologies (comma separated)..."
/>
</div>
<button onClick={() => {
const newProjects = profileData.projects.filter((_, i) => i !== index);
handleProfileChange({ target: { name: 'projects', value: newProjects } });
}} style={{ color: '#EF4444', background: 'none', border: 'none', cursor: 'pointer', fontSize: '0.875rem' }}>Remove Project</button>
</div>
))}
<button
onClick={() => {
const newProjects = [...(profileData.projects || []), { title: '', technologies_used: [], description: '' }];
handleProfileChange({ target: { name: 'projects', value: newProjects } });
}}
style={{
backgroundColor: 'rgba(251, 191, 36, 0.2)',
color: '#FCD34D',
padding: '0.5rem 1rem',
borderRadius: '0.5rem',
border: 'none',
cursor: 'pointer'
}}
>
+ Add Project
</button>
</>
) : (
<div>
{profileData?.projects && profileData.projects.length > 0 ? (
profileData.projects.map((proj, index) => (
<div key={index} style={{ marginBottom: '1.5rem' }}>
<p style={{ fontWeight: 'bold', margin: 0, color: '#FCD34D' }}>{proj.title}</p>
<p style={{ fontSize: '0.875rem', color: '#9CA3AF', margin: '0.25rem 0' }}>
{Array.isArray(proj.technologies_used) ? proj.technologies_used.join(', ') : proj.technologies_used}
</p>
<p style={{ color: '#d1d5db', margin: 0 }}>{proj.description}</p>
</div>
))
) : (
<p>No projects added.</p>
)}
</div>
)}
</div>
</div>
);
};
export default ProfileTab;