feat(resume): replace with Gemini's resume builder

- Two-column resume layout (sidebar + main)
- Edit mode with forms for all sections
- Preview mode with live resume preview
- Version saving system
- Print/Download functionality
- Personal info, Experience, Education, Skills, Languages
This commit is contained in:
2026-03-24 00:22:40 +01:00
parent 9c017b5967
commit 29312444d0
9 changed files with 5708 additions and 391 deletions
+451 -391
View File
@@ -1,520 +1,580 @@
"use client";
import BackToMC from "@/components/mission-control/BackToMC";
import { useState, useEffect } from "react";
interface PersonalInfo {
name: string;
title: string;
email: string;
phone: string;
location: string;
linkedin: string;
website: string;
}
import BackToMC from "@/components/mission-control/BackToMC";
interface Experience {
id: string;
title: string;
company: string;
location: string;
startDate: string;
endDate: string;
bullets: string[];
period: string;
description: string;
}
interface Education {
id: string;
degree: string;
school: string;
location: string;
graduationDate: string;
gpa: string;
honors: string;
year: string;
}
export default function ResumePage() {
interface Skill {
id: string;
name: string;
}
export default function ResumeBuilderPage() {
const [activeTab, setActiveTab] = useState<"edit" | "preview">("edit");
const [personal, setPersonal] = useState<PersonalInfo>({
const [resumeName, setResumeName] = useState("My Resume");
// Personal Info
const [personalInfo, setPersonalInfo] = useState({
name: "Your Name",
title: "Your Professional Title",
email: "your.email@email.com",
phone: "+1 (555) 000-0000",
location: "City, State",
title: "Professional Title",
email: "email@example.com",
phone: "+34 XXX XXX XXX",
location: "City, Country",
website: "www.yoursite.com",
linkedin: "linkedin.com/in/yourprofile",
website: "yourwebsite.com"
summary: "A brief professional summary..."
});
// Experience
const [experiences, setExperiences] = useState<Experience[]>([
{
id: "1",
title: "Job Title",
company: "Company Name",
location: "City, State",
startDate: "Jan 2020",
endDate: "Present",
bullets: [
"Key achievement or responsibility with measurable impact",
"Another accomplishment that demonstrates your skills",
"Additional relevant contribution"
]
period: "2020 - Present",
description: "Key responsibilities and achievements in this role."
}
]);
// Education
const [education, setEducation] = useState<Education[]>([
{
id: "1",
degree: "Bachelor of Science in Computer Science",
degree: "Degree Name",
school: "University Name",
location: "City, State",
graduationDate: "May 2016",
gpa: "3.8/4.0",
honors: "Magna Cum Laude"
year: "2016 - 2020"
}
]);
const [skills, setSkills] = useState<string[]>([
"JavaScript/TypeScript", "React/Next.js", "Node.js", "Python",
"AWS/Cloud Services", "Database Management", "Agile/Scrum", "Git"
// Skills
const [skills, setSkills] = useState<Skill[]>([
{ id: "1", name: "Skill 1" },
{ id: "2", name: "Skill 2" },
{ id: "3", name: "Skill 3" }
]);
const [languages, setLanguages] = useState<{name: string, level: string}[]>([
{ name: "English", level: "Native" },
{ name: "Spanish", level: "Professional" },
{ name: "Arabic", level: "Native" }
const [languages, setLanguages] = useState([
{ id: "1", name: "Language 1", level: "Fluent" },
{ id: "2", name: "Language 2", level: "Native" }
]);
const [certifications, setCertifications] = useState<string[]>([
"AWS Solutions Architect",
"Google Cloud Professional"
]);
useEffect(() => {
const saved = localStorage.getItem("haitham_resume_v2");
if (saved) {
try {
const data = JSON.parse(saved);
if (data.personal) setPersonal(data.personal);
if (data.experiences) setExperiences(data.experiences);
if (data.education) setEducation(data.education);
if (data.skills) setSkills(data.skills);
if (data.languages) setLanguages(data.languages);
if (data.certifications) setCertifications(data.certifications);
} catch (e) {}
}
}, []);
useEffect(() => {
localStorage.setItem("haitham_resume_v2", JSON.stringify({
personal, experiences, education, skills, languages, certifications
}));
}, [personal, experiences, education, skills, languages, certifications]);
// Versions
const [versions, setVersions] = useState<string[]>(["Default"]);
const [currentVersion, setCurrentVersion] = useState("Default");
// CRUD operations
const addExperience = () => {
setExperiences([...experiences, {
id: Date.now().toString(),
title: "", company: "", location: "", startDate: "", endDate: "", bullets: [""]
title: "New Position",
company: "Company",
period: "2023 - Present",
description: "Description..."
}]);
};
const updateExperience = (id: string, field: keyof Experience, value: any) => {
const removeExperience = (id: string) => {
setExperiences(experiences.filter(e => e.id !== id));
};
const updateExperience = (id: string, field: keyof Experience, value: string) => {
setExperiences(experiences.map(e => e.id === id ? { ...e, [field]: value } : e));
};
const addBullet = (id: string) => {
setExperiences(experiences.map(e =>
e.id === id ? { ...e, bullets: [...e.bullets, ""] } : e
));
};
const updateBullet = (expId: string, index: number, value: string) => {
setExperiences(experiences.map(e =>
e.id === expId ? { ...e, bullets: e.bullets.map((b, i) => i === index ? value : b) } : e
));
};
const removeBullet = (expId: string, index: number) => {
setExperiences(experiences.map(e =>
e.id === expId ? { ...e, bullets: e.bullets.filter((_, i) => i !== index) } : e
));
};
const addEducation = () => {
setEducation([...education, {
id: Date.now().toString(), degree: "", school: "", location: "",
graduationDate: "", gpa: "", honors: ""
id: Date.now().toString(),
degree: "New Degree",
school: "School Name",
year: "2020 - 2024"
}]);
};
const removeEducation = (id: string) => {
setEducation(education.filter(e => e.id !== id));
};
const updateEducation = (id: string, field: keyof Education, value: string) => {
setEducation(education.map(e => e.id === id ? { ...e, [field]: value } : e));
};
const handlePrint = () => {
setActiveTab("preview");
setTimeout(() => window.print(), 100);
const addSkill = () => {
setSkills([...skills, { id: Date.now().toString(), name: "New Skill" }]);
};
const inputClass = "w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500";
const labelClass = "block text-slate-400 text-xs mb-1 font-medium";
const removeSkill = (id: string) => {
setSkills(skills.filter(s => s.id !== id));
};
const updateSkill = (id: string, name: string) => {
setSkills(skills.map(s => s.id === id ? { ...s, name } : s));
};
const saveVersion = () => {
const name = prompt("Enter version name:", `Resume - ${currentVersion}`);
if (name && !versions.includes(name)) {
setVersions([...versions, name]);
setCurrentVersion(name);
alert(`Version "${name}" saved!`);
}
};
const loadVersion = (version: string) => {
setCurrentVersion(version);
};
const deleteVersion = (version: string) => {
if (versions.length > 1) {
setVersions(versions.filter(v => v !== version));
if (currentVersion === version) {
setCurrentVersion(versions[0]);
}
}
};
const handlePrint = () => {
window.print();
};
return (
<div className="min-h-screen bg-slate-950 text-white flex flex-col">
{/* Header */}
<div className="bg-slate-900 border-b border-slate-800 px-6 py-4 flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold text-white">📝 Professional Resume</h1>
<p className="text-slate-400 text-sm">Edit Preview Download PDF</p>
<div className="min-h-screen bg-slate-950 text-white">
<BackToMC />
{/* Toolbar */}
<div className="sticky top-0 z-50 bg-slate-800 border-b border-slate-700 px-6 py-3 flex items-center justify-between">
<div className="flex items-center gap-4">
<h1 className="text-xl font-bold">📄 Resume Builder</h1>
<div className="flex gap-2">
<button
onClick={() => setActiveTab("edit")}
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
activeTab === "edit" ? "bg-blue-600 text-white" : "bg-slate-700 text-slate-300"
}`}
>
Edit
</button>
<button
onClick={() => setActiveTab("preview")}
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
activeTab === "preview" ? "bg-blue-600 text-white" : "bg-slate-700 text-slate-300"
}`}
>
Preview
</button>
</div>
</div>
<div className="flex gap-2">
<button
onClick={() => setActiveTab(activeTab === "edit" ? "preview" : "edit")}
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
activeTab === "edit" ? "bg-slate-700 text-white" : "bg-blue-600 text-white"
}`}
<div className="flex items-center gap-3">
<select
value={currentVersion}
onChange={(e) => loadVersion(e.target.value)}
className="bg-slate-700 text-white px-3 py-2 rounded-lg text-sm"
>
{activeTab === "edit" ? "👁️ Preview" : "✏️ Edit"}
{versions.map(v => (
<option key={v} value={v}>{v}</option>
))}
</select>
<button
onClick={saveVersion}
className="bg-green-600 hover:bg-green-500 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors"
>
💾 Save Version
</button>
<button
onClick={handlePrint}
className="bg-emerald-600 hover:bg-emerald-500 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors"
className="bg-slate-600 hover:bg-slate-500 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors"
>
📄 Download PDF
🖨 Print/Download
</button>
</div>
</div>
{activeTab === "edit" ? (
<div className="flex-1 overflow-auto p-6">
<div className="max-w-4xl mx-auto space-y-6">
{/* Personal Info */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<h2 className="text-white font-bold mb-4">👤 Personal Information</h2>
<div className="grid grid-cols-2 gap-4">
<div>
<label className={labelClass}>Full Name</label>
<input type="text" value={personal.name} onChange={e => setPersonal({...personal, name: e.target.value})} className={inputClass} />
</div>
<div>
<label className={labelClass}>Professional Title</label>
<input type="text" value={personal.title} onChange={e => setPersonal({...personal, title: e.target.value})} className={inputClass} />
</div>
<div>
<label className={labelClass}>Email</label>
<input type="email" value={personal.email} onChange={e => setPersonal({...personal, email: e.target.value})} className={inputClass} />
</div>
<div>
<label className={labelClass}>Phone</label>
<input type="tel" value={personal.phone} onChange={e => setPersonal({...personal, phone: e.target.value})} className={inputClass} />
</div>
<div>
<label className={labelClass}>Location</label>
<input type="text" value={personal.location} onChange={e => setPersonal({...personal, location: e.target.value})} className={inputClass} />
</div>
<div>
<label className={labelClass}>LinkedIn</label>
<input type="text" value={personal.linkedin} onChange={e => setPersonal({...personal, linkedin: e.target.value})} className={inputClass} />
</div>
<div className="p-6 max-w-4xl mx-auto space-y-6">
{/* Personal Info */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<h2 className="text-lg font-bold mb-4 text-blue-400">👤 Personal Information</h2>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm text-slate-400 mb-1">Full Name</label>
<input
type="text"
value={personalInfo.name}
onChange={(e) => setPersonalInfo({...personalInfo, name: e.target.value})}
className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white"
/>
</div>
<div>
<label className="block text-sm text-slate-400 mb-1">Professional Title</label>
<input
type="text"
value={personalInfo.title}
onChange={(e) => setPersonalInfo({...personalInfo, title: e.target.value})}
className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white"
/>
</div>
<div>
<label className="block text-sm text-slate-400 mb-1">Email</label>
<input
type="email"
value={personalInfo.email}
onChange={(e) => setPersonalInfo({...personalInfo, email: e.target.value})}
className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white"
/>
</div>
<div>
<label className="block text-sm text-slate-400 mb-1">Phone</label>
<input
type="tel"
value={personalInfo.phone}
onChange={(e) => setPersonalInfo({...personalInfo, phone: e.target.value})}
className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white"
/>
</div>
<div>
<label className="block text-sm text-slate-400 mb-1">Location</label>
<input
type="text"
value={personalInfo.location}
onChange={(e) => setPersonalInfo({...personalInfo, location: e.target.value})}
className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white"
/>
</div>
<div>
<label className="block text-sm text-slate-400 mb-1">Website</label>
<input
type="text"
value={personalInfo.website}
onChange={(e) => setPersonalInfo({...personalInfo, website: e.target.value})}
className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white"
/>
</div>
</div>
<div className="mt-4">
<label className="block text-sm text-slate-400 mb-1">Professional Summary</label>
<textarea
value={personalInfo.summary}
onChange={(e) => setPersonalInfo({...personalInfo, summary: e.target.value})}
rows={3}
className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white"
/>
</div>
</div>
{/* Experience */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<div className="flex items-center justify-between mb-4">
<h2 className="text-white font-bold">💼 Work Experience</h2>
<button onClick={addExperience} className="bg-blue-600 hover:bg-blue-500 text-white px-3 py-1 rounded text-sm">+ Add Position</button>
</div>
{/* Experience */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-bold text-blue-400">💼 Experience</h2>
<button
onClick={addExperience}
className="bg-blue-600 hover:bg-blue-500 text-white px-3 py-1 rounded-lg text-sm"
>
+ Add
</button>
</div>
<div className="space-y-4">
{experiences.map((exp) => (
<div key={exp.id} className="bg-slate-900 rounded-lg p-4 mb-4 border border-slate-700">
<div className="grid grid-cols-2 gap-4 mb-3">
<div>
<label className={labelClass}>Job Title</label>
<input type="text" value={exp.title} onChange={e => updateExperience(exp.id, "title", e.target.value)} className={inputClass} />
</div>
<div>
<label className={labelClass}>Company</label>
<input type="text" value={exp.company} onChange={e => updateExperience(exp.id, "company", e.target.value)} className={inputClass} />
</div>
<div>
<label className={labelClass}>Location</label>
<input type="text" value={exp.location} onChange={e => updateExperience(exp.id, "location", e.target.value)} className={inputClass} />
</div>
<div className="flex gap-2">
<div className="flex-1">
<label className={labelClass}>Start</label>
<input type="text" value={exp.startDate} onChange={e => updateExperience(exp.id, "startDate", e.target.value)} className={inputClass} placeholder="Jan 2020" />
</div>
<div className="flex-1">
<label className={labelClass}>End</label>
<input type="text" value={exp.endDate} onChange={e => updateExperience(exp.id, "endDate", e.target.value)} className={inputClass} placeholder="Present" />
</div>
</div>
</div>
<div className="mb-2">
<label className={labelClass}>Key Achievements</label>
{exp.bullets.map((bullet, i) => (
<div key={i} className="flex gap-2 mb-2">
<input type="text" value={bullet} onChange={e => updateBullet(exp.id, i, e.target.value)} className={inputClass} placeholder={`Achievement ${i + 1}`} />
{exp.bullets.length > 1 && (
<button onClick={() => removeBullet(exp.id, i)} className="text-red-400 hover:text-red-300 text-sm px-2"></button>
)}
</div>
))}
<button onClick={() => addBullet(exp.id)} className="text-blue-400 hover:text-blue-300 text-xs">+ Add achievement</button>
</div>
</div>
))}
</div>
{/* Education */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<div className="flex items-center justify-between mb-4">
<h2 className="text-white font-bold">🎓 Education</h2>
<button onClick={addEducation} className="bg-blue-600 hover:bg-blue-500 text-white px-3 py-1 rounded text-sm">+ Add</button>
</div>
{education.map((edu) => (
<div key={edu.id} className="bg-slate-900 rounded-lg p-4 mb-4 border border-slate-700">
<div key={exp.id} className="bg-slate-700/50 rounded-lg p-4 border border-slate-600">
<div className="grid grid-cols-2 gap-4">
<div>
<label className={labelClass}>Degree</label>
<input type="text" value={edu.degree} onChange={e => updateEducation(edu.id, "degree", e.target.value)} className={inputClass} />
<label className="block text-sm text-slate-400 mb-1">Job Title</label>
<input
type="text"
value={exp.title}
onChange={(e) => updateExperience(exp.id, "title", e.target.value)}
className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm"
/>
</div>
<div>
<label className={labelClass}>School</label>
<input type="text" value={edu.school} onChange={e => updateEducation(edu.id, "school", e.target.value)} className={inputClass} />
<label className="block text-sm text-slate-400 mb-1">Company</label>
<input
type="text"
value={exp.company}
onChange={(e) => updateExperience(exp.id, "company", e.target.value)}
className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm"
/>
</div>
<div>
<label className={labelClass}>Location</label>
<input type="text" value={edu.location} onChange={e => updateEducation(edu.id, "location", e.target.value)} className={inputClass} />
<div className="col-span-2">
<label className="block text-sm text-slate-400 mb-1">Period</label>
<input
type="text"
value={exp.period}
onChange={(e) => updateExperience(exp.id, "period", e.target.value)}
className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm"
/>
</div>
<div>
<label className={labelClass}>Graduation Date</label>
<input type="text" value={edu.graduationDate} onChange={e => updateEducation(edu.id, "graduationDate", e.target.value)} className={inputClass} />
</div>
<div>
<label className={labelClass}>GPA (optional)</label>
<input type="text" value={edu.gpa} onChange={e => updateEducation(edu.id, "gpa", e.target.value)} className={inputClass} />
</div>
<div>
<label className={labelClass}>Honors (optional)</label>
<input type="text" value={edu.honors} onChange={e => updateEducation(edu.id, "honors", e.target.value)} className={inputClass} placeholder="Magna Cum Laude" />
<div className="col-span-2">
<label className="block text-sm text-slate-400 mb-1">Description</label>
<textarea
value={exp.description}
onChange={(e) => updateExperience(exp.id, "description", e.target.value)}
rows={3}
className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm"
/>
</div>
</div>
<button
onClick={() => removeExperience(exp.id)}
className="mt-2 text-red-400 text-sm hover:text-red-300"
>
Remove
</button>
</div>
))}
</div>
</div>
{/* Skills */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<h2 className="text-white font-bold mb-4">🛠 Technical Skills</h2>
<div className="flex flex-wrap gap-2">
{skills.map((skill, i) => (
<div key={i} className="flex items-center gap-2 bg-slate-900 rounded-lg px-3 py-1">
<input
type="text"
value={skill}
onChange={e => {
const newSkills = [...skills];
newSkills[i] = e.target.value;
setSkills(newSkills);
}}
className="bg-transparent text-white text-sm w-24 focus:outline-none"
/>
<button onClick={() => setSkills(skills.filter((_, j) => j !== i))} className="text-slate-500 hover:text-red-400 text-xs"></button>
</div>
))}
<button onClick={() => setSkills([...skills, ""])} className="bg-slate-700 hover:bg-slate-600 text-white text-sm px-3 py-1 rounded-lg">+ Add</button>
</div>
{/* Education */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-bold text-blue-400">🎓 Education</h2>
<button
onClick={addEducation}
className="bg-blue-600 hover:bg-blue-500 text-white px-3 py-1 rounded-lg text-sm"
>
+ Add
</button>
</div>
{/* Languages */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<h2 className="text-white font-bold mb-4">🌍 Languages</h2>
<div className="flex flex-wrap gap-3">
{languages.map((lang, i) => (
<div key={i} className="flex items-center gap-2 bg-slate-900 rounded-lg px-3 py-2">
<input
type="text"
value={lang.name}
onChange={e => {
const newLangs = [...languages];
newLangs[i].name = e.target.value;
setLanguages(newLangs);
}}
className="bg-transparent text-white text-sm w-24 focus:outline-none"
/>
<span className="text-slate-500 text-xs"></span>
<input
type="text"
value={lang.level}
onChange={e => {
const newLangs = [...languages];
newLangs[i].level = e.target.value;
setLanguages(newLangs);
}}
className="bg-transparent text-slate-400 text-sm w-20 focus:outline-none"
/>
<div className="space-y-4">
{education.map((edu) => (
<div key={edu.id} className="bg-slate-700/50 rounded-lg p-4 border border-slate-600">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm text-slate-400 mb-1">Degree</label>
<input
type="text"
value={edu.degree}
onChange={(e) => updateEducation(edu.id, "degree", e.target.value)}
className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm"
/>
</div>
<div>
<label className="block text-sm text-slate-400 mb-1">School</label>
<input
type="text"
value={edu.school}
onChange={(e) => updateEducation(edu.id, "school", e.target.value)}
className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm"
/>
</div>
<div>
<label className="block text-sm text-slate-400 mb-1">Year</label>
<input
type="text"
value={edu.year}
onChange={(e) => updateEducation(edu.id, "year", e.target.value)}
className="w-full bg-slate-600 border border-slate-500 rounded-lg px-3 py-2 text-white text-sm"
/>
</div>
</div>
))}
<button onClick={() => setLanguages([...languages, {name: "", level: ""}])} className="bg-slate-700 hover:bg-slate-600 text-white text-sm px-3 py-2 rounded-lg">+ Add</button>
</div>
<button
onClick={() => removeEducation(edu.id)}
className="mt-2 text-red-400 text-sm hover:text-red-300"
>
Remove
</button>
</div>
))}
</div>
</div>
{/* Certifications */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<h2 className="text-white font-bold mb-4">📜 Certifications</h2>
<div className="flex flex-wrap gap-2">
{certifications.map((cert, i) => (
<div key={i} className="flex items-center gap-2 bg-slate-900 rounded-lg px-3 py-1">
<input
type="text"
value={cert}
onChange={e => {
const newCerts = [...certifications];
newCerts[i] = e.target.value;
setCertifications(newCerts);
}}
className="bg-transparent text-white text-sm w-40 focus:outline-none"
/>
<button onClick={() => setCertifications(certifications.filter((_, j) => j !== i))} className="text-slate-500 hover:text-red-400 text-xs"></button>
</div>
))}
<button onClick={() => setCertifications([...certifications, ""])} className="bg-slate-700 hover:bg-slate-600 text-white text-sm px-3 py-1 rounded-lg">+ Add</button>
</div>
{/* Skills */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-bold text-blue-400">🛠 Skills</h2>
<button
onClick={addSkill}
className="bg-blue-600 hover:bg-blue-500 text-white px-3 py-1 rounded-lg text-sm"
>
+ Add
</button>
</div>
<div className="flex flex-wrap gap-2">
{skills.map((skill) => (
<div key={skill.id} className="flex items-center gap-2 bg-slate-700 px-3 py-1 rounded-lg">
<input
type="text"
value={skill.name}
onChange={(e) => updateSkill(skill.id, e.target.value)}
className="bg-transparent border-none text-white text-sm w-24"
/>
<button
onClick={() => removeSkill(skill.id)}
className="text-slate-400 hover:text-red-400 text-lg"
>
×
</button>
</div>
))}
</div>
</div>
{/* Languages */}
<div className="bg-slate-800 rounded-xl p-6 border border-slate-700">
<h2 className="text-lg font-bold text-blue-400 mb-4">🌍 Languages</h2>
<div className="flex flex-wrap gap-2">
{languages.map((lang) => (
<div key={lang.id} className="bg-slate-700 px-3 py-2 rounded-lg text-sm">
{lang.name} - {lang.level}
</div>
))}
</div>
</div>
</div>
) : (
/* PREVIEW - Professional Resume Template */
<div className="flex-1 overflow-auto bg-slate-100 p-8">
<div className="max-w-850px mx-auto bg-white shadow-xl rounded-lg overflow-hidden" style={{maxWidth: "850px"}}>
{/* Header - Dark Blue Professional */}
<div className="bg-gradient-to-r from-slate-800 to-slate-700 text-white px-8 py-10">
<div className="text-center mb-4">
<h1 className="text-3xl font-bold tracking-wide mb-2">{personal.name || "Your Name"}</h1>
<div className="text-slate-300 text-lg font-light">{personal.title || "Professional Title"}</div>
/* Resume Preview */
<div className="p-8">
<style>{`
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap');
.resume-preview {
width: 850px;
min-height: 1100px;
background: white;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
margin: 0 auto;
display: flex;
font-family: 'Roboto', sans-serif;
}
.resume-sidebar {
width: 280px;
background-color: #f3f3f3;
padding: 2.5rem 1.5rem;
}
.resume-main {
flex: 1;
padding: 3.5rem 3rem;
background: white;
}
.resume-photo {
width: 176px;
height: 176px;
border-radius: 9999px;
border: 10px solid #e2e2e2;
background: #d1d1d1;
margin: 0 auto 2rem;
}
.resume-section-header {
font-size: 1.1rem;
font-weight: 700;
color: #1a1a1a;
border-bottom: 1px solid #ccc;
padding-bottom: 4px;
margin-bottom: 12px;
text-transform: capitalize;
}
.resume-main-header {
font-size: 1.6rem;
font-weight: 800;
letter-spacing: 0.15em;
color: #1a1a1a;
border-bottom: 2px solid #1a1a1a;
padding-bottom: 8px;
margin-bottom: 24px;
text-transform: uppercase;
}
@media print {
body { background: white; }
.resume-preview { box-shadow: none; margin: 0; }
}
`}</style>
<div className="resume-preview">
{/* Sidebar */}
<div className="resume-sidebar">
<div className="resume-photo" />
{/* Contact Section */}
<div className="mb-6">
<h3 className="resume-section-header">Contact</h3>
<div className="space-y-2 text-sm text-gray-700">
<p>📧 {personalInfo.email}</p>
<p>📱 {personalInfo.phone}</p>
<p>📍 {personalInfo.location}</p>
<p>🌐 {personalInfo.website}</p>
<p>💼 {personalInfo.linkedin}</p>
</div>
</div>
<div className="flex justify-center flex-wrap gap-4 text-sm text-slate-300">
{personal.email && <span> {personal.email}</span>}
{personal.phone && <span>📱 {personal.phone}</span>}
{personal.location && <span>📍 {personal.location}</span>}
{personal.linkedin && <span>💼 {personal.linkedin}</span>}
{/* Skills Section */}
<div className="mb-6">
<h3 className="resume-section-header">Skills</h3>
<div className="space-y-1">
{skills.map((skill) => (
<div key={skill.id} className="text-sm text-gray-700">
{skill.name}
</div>
))}
</div>
</div>
{/* Languages Section */}
<div className="mb-6">
<h3 className="resume-section-header">Languages</h3>
<div className="space-y-1">
{languages.map((lang) => (
<div key={lang.id} className="text-sm text-gray-700">
{lang.name} ({lang.level})
</div>
))}
</div>
</div>
</div>
{/* Body */}
<div className="px-8 py-6 space-y-6">
{/* Main Content */}
<div className="resume-main">
<h1 className="resume-main-header">{personalInfo.name}</h1>
<p className="text-lg text-gray-600 mb-6 uppercase tracking-wide">{personalInfo.title}</p>
{/* Summary */}
<div>
<div className="border-b-2 border-slate-800 pb-1 mb-3">
<span className="text-sm font-bold text-slate-800 uppercase tracking-wider">Professional Summary</span>
</div>
<p className="text-slate-600 text-sm leading-relaxed">
Results-driven professional with proven expertise in delivering high-impact solutions. Skilled in modern technologies and best practices. Demonstrated ability to lead projects, optimize processes, and achieve organizational goals.
</p>
<div className="mb-6">
<h3 className="resume-section-header">Profile</h3>
<p className="text-sm text-gray-700 leading-relaxed">{personalInfo.summary}</p>
</div>
{/* Experience */}
<div>
<div className="border-b-2 border-slate-800 pb-1 mb-3">
<span className="text-sm font-bold text-slate-800 uppercase tracking-wider">Work Experience</span>
</div>
{experiences.filter(e => e.title || e.company).map((exp) => (
<div className="mb-6">
<h3 className="resume-section-header">Experience</h3>
{experiences.map((exp) => (
<div key={exp.id} className="mb-4">
<div className="flex justify-between items-baseline mb-1">
<div className="flex justify-between items-start">
<div>
<span className="font-bold text-slate-800">{exp.title || "Job Title"}</span>
<span className="text-slate-600"> | {exp.company || "Company"}</span>
<h4 className="font-bold text-gray-800">{exp.title}</h4>
<p className="text-gray-600">{exp.company}</p>
</div>
<span className="text-slate-500 text-sm">{exp.startDate} - {exp.endDate}</span>
<span className="text-sm text-gray-500">{exp.period}</span>
</div>
{exp.location && <div className="text-slate-500 text-sm mb-2">{exp.location}</div>}
<ul className="space-y-1">
{exp.bullets.filter(b => b).map((bullet, i) => (
<li key={i} className="text-slate-600 text-sm flex items-start gap-2">
<span className="text-slate-400"></span>
<span>{bullet}</span>
</li>
))}
</ul>
<p className="text-sm text-gray-700 mt-2 leading-relaxed">{exp.description}</p>
</div>
))}
</div>
{/* Education */}
<div>
<div className="border-b-2 border-slate-800 pb-1 mb-3">
<span className="text-sm font-bold text-slate-800 uppercase tracking-wider">Education</span>
</div>
{education.filter(e => e.degree || e.school).map((edu) => (
<h3 className="resume-section-header">Education</h3>
{education.map((edu) => (
<div key={edu.id} className="mb-3">
<div className="flex justify-between items-baseline">
<div>
<span className="font-bold text-slate-800">{edu.degree || "Degree"}</span>
{edu.honors && <span className="text-slate-500"> ({edu.honors})</span>}
</div>
<span className="text-slate-500 text-sm">{edu.graduationDate}</span>
</div>
<div className="text-slate-600 text-sm">{edu.school}{edu.location && `, ${edu.location}`}</div>
{edu.gpa && <div className="text-slate-500 text-sm">GPA: {edu.gpa}</div>}
<h4 className="font-bold text-gray-800">{edu.degree}</h4>
<p className="text-gray-600">{edu.school} {edu.year}</p>
</div>
))}
</div>
{/* Skills */}
<div>
<div className="border-b-2 border-slate-800 pb-1 mb-3">
<span className="text-sm font-bold text-slate-800 uppercase tracking-wider">Technical Skills</span>
</div>
<div className="flex flex-wrap gap-2">
{skills.filter(s => s).map((skill, i) => (
<span key={i} className="bg-slate-100 text-slate-700 px-3 py-1 rounded text-sm">{skill}</span>
))}
</div>
</div>
{/* Languages & Certs */}
<div className="grid grid-cols-2 gap-6">
<div>
<div className="border-b-2 border-slate-800 pb-1 mb-3">
<span className="text-sm font-bold text-slate-800 uppercase tracking-wider">Languages</span>
</div>
<div className="space-y-1">
{languages.filter(l => l.name).map((lang, i) => (
<div key={i} className="text-sm">
<span className="text-slate-800 font-medium">{lang.name}</span>
<span className="text-slate-500"> - {lang.level}</span>
</div>
))}
</div>
</div>
<div>
<div className="border-b-2 border-slate-800 pb-1 mb-3">
<span className="text-sm font-bold text-slate-800 uppercase tracking-wider">Certifications</span>
</div>
<div className="space-y-1">
{certifications.filter(c => c).map((cert, i) => (
<div key={i} className="text-slate-700 text-sm">{cert}</div>
))}
</div>
</div>
</div>
</div>
</div>
</div>
)}
<style jsx global>{`
@media print {
body { background: white !important; }
.bg-slate-100 { background: white !important; }
}
`}</style>
</div>
);
}