Files
sitemente/app/mission-control/resume/page.tsx
T
horus 45af56d9cf feat(mission-control): restore MC tabs - temple, office, memory, claude, pdf-viewer, resume, resume-upload, temple-3d, demos
Also added:
- Memory API endpoints
- Briefs API endpoints
- AnveVoice stats API
- Claude spawn API
- TTS proxy
- Cleopatra voice widget
- api-auth middleware
2026-03-23 16:30:44 +01:00

520 lines
24 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useState, useEffect } from "react";
interface PersonalInfo {
name: string;
title: string;
email: string;
phone: string;
location: string;
linkedin: string;
website: string;
}
interface Experience {
id: string;
title: string;
company: string;
location: string;
startDate: string;
endDate: string;
bullets: string[];
}
interface Education {
id: string;
degree: string;
school: string;
location: string;
graduationDate: string;
gpa: string;
honors: string;
}
export default function ResumePage() {
const [activeTab, setActiveTab] = useState<"edit" | "preview">("edit");
const [personal, setPersonal] = useState<PersonalInfo>({
name: "Your Name",
title: "Your Professional Title",
email: "your.email@email.com",
phone: "+1 (555) 000-0000",
location: "City, State",
linkedin: "linkedin.com/in/yourprofile",
website: "yourwebsite.com"
});
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"
]
}
]);
const [education, setEducation] = useState<Education[]>([
{
id: "1",
degree: "Bachelor of Science in Computer Science",
school: "University Name",
location: "City, State",
graduationDate: "May 2016",
gpa: "3.8/4.0",
honors: "Magna Cum Laude"
}
]);
const [skills, setSkills] = useState<string[]>([
"JavaScript/TypeScript", "React/Next.js", "Node.js", "Python",
"AWS/Cloud Services", "Database Management", "Agile/Scrum", "Git"
]);
const [languages, setLanguages] = useState<{name: string, level: string}[]>([
{ name: "English", level: "Native" },
{ name: "Spanish", level: "Professional" },
{ name: "Arabic", 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]);
const addExperience = () => {
setExperiences([...experiences, {
id: Date.now().toString(),
title: "", company: "", location: "", startDate: "", endDate: "", bullets: [""]
}]);
};
const updateExperience = (id: string, field: keyof Experience, value: any) => {
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: ""
}]);
};
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 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";
return (
<div className="min-h-screen bg-slate-950 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>
<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"
}`}
>
{activeTab === "edit" ? "👁️ Preview" : "✏️ Edit"}
</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"
>
📄 Download PDF
</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>
</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>
{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 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} />
</div>
<div>
<label className={labelClass}>School</label>
<input type="text" value={edu.school} onChange={e => updateEducation(edu.id, "school", e.target.value)} className={inputClass} />
</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>
<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>
</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>
</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>
))}
<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>
</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>
</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>
</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>}
</div>
</div>
{/* Body */}
<div className="px-8 py-6 space-y-6">
{/* 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>
{/* 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 key={exp.id} className="mb-4">
<div className="flex justify-between items-baseline mb-1">
<div>
<span className="font-bold text-slate-800">{exp.title || "Job Title"}</span>
<span className="text-slate-600"> | {exp.company || "Company"}</span>
</div>
<span className="text-slate-500 text-sm">{exp.startDate} - {exp.endDate}</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>
</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) => (
<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>}
</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>
);
}