Added resume

This commit is contained in:
2025-05-18 00:55:19 -06:00
parent d86ae2f16b
commit 6ceb4918f7
4 changed files with 715 additions and 11 deletions

232
src/pages/resume.astro Normal file
View File

@ -0,0 +1,232 @@
---
import { Icon } from 'astro-icon/components';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import Layout from '../layouts/Layout.astro';
import '../styles/global.css';
interface ResumeData {
basics: {
name: string;
email: string;
url?: { href: string };
};
sections: {
summary: { name: string; content: string };
profiles: { name: string; items: { network: string; username: string; url: { href: string } }[] };
skills: { name: string; items: { id: string; name: string; level: number }[] };
experience: { name: string; items: { id: string; company: string; position: string; date: string; location: string; summary: string; url?: { href: string } }[] };
education: { name: string; items: { id: string; institution: string; studyType: string; area: string; date: string; summary: string }[] };
volunteer: { name: string; items: { id: string; organization: string; position: string; date: string }[] };
};
}
let resumeData: ResumeData | undefined = undefined;
let fetchError: string | null = null;
try {
let resumeJson: string;
try {
resumeJson = await readFile(join(process.cwd(), 'public', 'files', 'resume.json'), 'utf-8');
} catch (err) {
resumeJson = await readFile('/Users/atridad/Downloads/resume.json', 'utf-8');
}
resumeData = JSON.parse(resumeJson);
if (resumeData && resumeData.sections && resumeData.sections.skills) {
const skillsSection = resumeData.sections.skills;
if (skillsSection.items) {
const tsSkill = skillsSection.items.find(s => s.name === "Typescrpt");
if (tsSkill) {
tsSkill.name = "Typescript";
}
}
}
} catch (error) {
console.error("Error processing resume data:", error);
fetchError = "An error occurred while processing resume data. Please make sure the resume.json file is in the correct location.";
resumeData = undefined;
}
const data = resumeData;
---
{(!data || fetchError) && (
<Layout>
<div class="container mx-auto p-4 max-w-4xl text-center">
<h1 class="text-2xl font-bold text-red-600">Error loading resume data.</h1>
<p>{fetchError || "Please try refreshing the page."}</p>
</div>
</Layout>
)}
{data && !fetchError && (
<Layout>
<div class="container mx-auto p-4 max-w-4xl">
<h1 class="text-4xl font-bold mb-6 text-center">{data.basics.name}</h1>
<div class="flex justify-center items-center flex-wrap gap-x-4 gap-y-2 mb-6">
{data.basics.email && (
<a href={`mailto:${data.basics.email}`} class="link link-hover inline-flex items-center gap-1">
<Icon name="mdi:email" /> {data.basics.email}
</a>
)}
{data.sections.profiles.items.find(p => p.network === "GitHub") && (
<a href={data.sections.profiles.items.find(p => p.network === "GitHub")!.url.href} target="_blank" rel="noopener noreferrer" class="link link-hover inline-flex items-center gap-1">
<Icon name="simple-icons:github" /> GitHub
</a>
)}
{data.sections.profiles.items.find(p => p.network === "linkedin") && (
<a href={data.sections.profiles.items.find(p => p.network === "linkedin")!.url.href} target="_blank" rel="noopener noreferrer" class="link link-hover inline-flex items-center gap-1">
<Icon name="simple-icons:linkedin" /> LinkedIn
</a>
)}
</div>
<div class="text-center mb-8">
<a
href="/files/Atridad_Lahiji_Resume.pdf"
download="Atridad_Lahiji_Resume.pdf"
class="btn btn-primary inline-flex items-center gap-2"
>
<Icon name="mdi:download" /> Download Resume (PDF)
</a>
</div>
{data.sections.summary && (
<div class="card bg-base-200 shadow-xl mb-6">
<div class="card-body">
<h2 class="card-title text-2xl">{data.sections.summary.name || "Summary"}</h2>
<div set:html={data.sections.summary.content}></div>
</div>
</div>
)}
{data.sections.profiles && data.sections.profiles.items && data.sections.profiles.items.length > 0 && (
<div class="card bg-base-200 shadow-xl mb-6">
<div class="card-body">
<h2 class="card-title text-2xl">{data.sections.profiles.name || "Profiles"}</h2>
<div class="flex flex-wrap gap-4">
{data.sections.profiles.items.map((profile) => {
let iconName = "mdi:web";
const networkLower = profile.network.toLowerCase();
if (networkLower === "github") iconName = "simple-icons:github";
else if (networkLower === "linkedin") iconName = "simple-icons:linkedin";
else if (networkLower === "gitea") iconName = "simple-icons:gitea";
return (
<a
href={profile.url.href}
target="_blank"
rel="noopener noreferrer"
class="link link-hover inline-flex items-center gap-1"
>
<Icon name={iconName} /> {profile.network} ({profile.username})
</a>
);
})}
</div>
</div>
</div>
)}
{data.sections.skills && data.sections.skills.items && data.sections.skills.items.length > 0 && (
<div class="card bg-base-200 shadow-xl mb-6">
<div class="card-body">
<h2 class="card-title text-2xl">{data.sections.skills.name || "Skills"}</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
{data.sections.skills.items.map((skill) => (
<div>
<label class="label">
<span class="label-text">{skill.name}</span>
</label>
<progress
class="progress progress-primary w-full"
value={skill.level * 20}
max="100"
>
</progress>
</div>
))}
</div>
</div>
</div>
)}
{data.sections.experience && data.sections.experience.items && data.sections.experience.items.length > 0 && (
<div class="card bg-base-200 shadow-xl mb-6">
<div class="card-body">
<h2 class="card-title text-2xl">{data.sections.experience.name || "Experience"}</h2>
<div class="space-y-4">
{data.sections.experience.items.map((exp, index) => (
<details class="collapse collapse-arrow bg-base-100" open={index === 0 ? true : undefined}>
<summary class="collapse-title text-xl font-medium">
{exp.position} at {exp.company} ({exp.date})
{exp.location && (
<span class="text-sm font-normal float-right pt-1">{exp.location}</span>
)}
</summary>
<div class="collapse-content">
{exp.url && exp.url.href && (
<a href={exp.url.href} target="_blank" rel="noopener noreferrer" class="link link-primary block mb-2">{exp.url.href}</a>
)}
<div class="mt-2">
<ul class="list">
{exp.summary.replace(/<\/?ul>|<\/?p>/g, '')
.split('<li>')
.filter(item => item.trim() !== '')
.map(item => (
<li class="list-row">
{item.replace('</li>', '')}
</li>
))
}
</ul>
</div>
</div>
</details>
))}
</div>
</div>
</div>
)}
{data.sections.education && data.sections.education.items && data.sections.education.items.length > 0 && (
<div class="card bg-base-200 shadow-xl mb-6">
<div class="card-body">
<h2 class="card-title text-2xl">{data.sections.education.name || "Education"}</h2>
<div class="space-y-4">
{data.sections.education.items.map((edu, index) => (
<div>
<h3 class="text-lg font-semibold">{edu.institution}</h3>
<p>{edu.studyType} - {edu.area} ({edu.date})</p>
{edu.summary && (
<div class="ml-4 text-sm mt-1" set:html={edu.summary}></div>
)}
</div>
))}
</div>
</div>
</div>
)}
{data.sections.volunteer && data.sections.volunteer.items && data.sections.volunteer.items.length > 0 && (
<div class="card bg-base-200 shadow-xl mb-6">
<div class="card-body">
<h2 class="card-title text-2xl">{data.sections.volunteer.name || "Volunteering"}</h2>
<div class="space-y-4">
{data.sections.volunteer.items.map((vol, index) => (
<div>
<h3 class="text-lg font-semibold">{vol.organization}</h3>
<p>{vol.position} ({vol.date})</p>
</div>
))}
</div>
</div>
</div>
)}
</div>
</Layout>
)}