Major re-work!
Some checks failed
Docker Deploy / build-and-push (push) Has been cancelled

This commit is contained in:
2025-06-12 11:09:24 -06:00
parent 324449dd59
commit ab2eb7eeac
13 changed files with 545 additions and 348 deletions

View File

@ -3,31 +3,32 @@ import { Image } from "astro:assets";
import SocialLinks from "../components/SocialLinks.astro";
import TechLinks from "../components/TechLinks.astro";
import Layout from "../layouts/Layout.astro";
import { personalInfo, homepageSections } from "../config/data";
---
<Layout>
<Image
src="/logo_real.webp"
alt="A drawing of Atridad Lahiji by Shelze!"
height={150}
width={150}
src={personalInfo.profileImage.src}
alt={personalInfo.profileImage.alt}
height={personalInfo.profileImage.height}
width={personalInfo.profileImage.width}
/>
<h1
class="bg-gradient-to-r from-primary via-secondary to-accent bg-clip-text text-transparent text-4xl sm:text-6xl font-bold text-center"
>
Atridad Lahiji
{personalInfo.name}
</h1>
<h2 class="text-xl sm:text-3xl font-bold text-center">
Researcher, Full-Stack Developer, and IT Professional.
{personalInfo.tagline}
</h2>
<h3 class="text-lg sm:text-2xl font-bold">Places I Exist:</h3>
<h3 class="text-lg sm:text-2xl font-bold">{homepageSections.socialLinks.title}</h3>
<SocialLinks />
<h3 class="text-lg sm:text-2xl font-bold">Stuff I Use:</h3>
<h3 class="text-lg sm:text-2xl font-bold">{homepageSections.techStack.title}</h3>
<TechLinks />
</Layout>

View File

@ -2,6 +2,7 @@
import { Icon } from "astro-icon/components";
import Layout from "../layouts/Layout.astro";
import ResumeSkills from "../components/ResumeSkills";
import { siteConfig } from "../config/data";
import "../styles/global.css";
interface ResumeData {
@ -66,8 +67,8 @@ try {
// Get the base URL for the current request
const baseUrl = Astro.url.origin;
// Fetch the JSON file from the public directory
const response = await fetch(`${baseUrl}/files/resume.json`);
// Fetch the JSON file from the public directory using config
const response = await fetch(`${baseUrl}${siteConfig.resume.jsonFile}`);
if (!response.ok) {
throw new Error(
@ -96,11 +97,12 @@ try {
}
const data = resumeData;
const resumeConfig = siteConfig.resume;
---
{
(!data || fetchError) && (
<Layout>
<Layout title="Resume">
<div class="container mx-auto p-4 sm:p-6 lg:p-8 max-w-4xl text-center w-full">
<h1 class="text-2xl font-bold text-red-600">
Error loading resume data.
@ -113,7 +115,7 @@ const data = resumeData;
{
data && !fetchError && (
<Layout>
<Layout title="Resume">
<div class="container mx-auto p-4 sm:p-6 lg:p-8 max-w-4xl w-full">
<h1 class="text-3xl sm:text-4xl font-bold mb-4 sm:mb-6 text-center">
{data.basics.name}
@ -164,19 +166,19 @@ const data = resumeData;
<div class="text-center mb-6 sm:mb-8">
<a
href="/files/Atridad_Lahiji_Resume.pdf"
download="Atridad_Lahiji_Resume.pdf"
href={resumeConfig.pdfFile.path}
download={resumeConfig.pdfFile.filename}
class="btn btn-primary inline-flex items-center gap-2 text-sm sm:text-base"
>
<Icon name="mdi:download" /> Download Resume (PDF)
<Icon name="mdi:download" /> {resumeConfig.pdfFile.displayText}
</a>
</div>
{data.sections.summary && (
{data.sections.summary && resumeConfig.sections.summary?.enabled && (
<div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body p-4 sm:p-6">
<h2 class="card-title text-xl sm:text-2xl">
{data.sections.summary.name || "Summary"}
{resumeConfig.sections.summary.title || data.sections.summary.name || "Summary"}
</h2>
<div set:html={data.sections.summary.content} />
</div>
@ -185,11 +187,12 @@ const data = resumeData;
{data.sections.profiles &&
data.sections.profiles.items &&
data.sections.profiles.items.length > 0 && (
data.sections.profiles.items.length > 0 &&
resumeConfig.sections.profiles?.enabled && (
<div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body p-4 sm:p-6">
<h2 class="card-title text-xl sm:text-2xl">
{data.sections.profiles.name || "Profiles"}
{resumeConfig.sections.profiles.title || data.sections.profiles.name || "Profiles"}
</h2>
<div class="flex flex-wrap gap-3 sm:gap-4">
{data.sections.profiles.items.map(
@ -197,16 +200,23 @@ const data = resumeData;
let iconName = "mdi:web";
const networkLower =
profile.network.toLowerCase();
if (networkLower === "github")
iconName =
"simple-icons:github";
else if (
if (networkLower === "github") {
iconName = "simple-icons:github";
} else if (
networkLower === "linkedin"
)
) {
iconName =
"simple-icons:linkedin";
else if (networkLower === "gitea")
iconName = "simple-icons:gitea";
} else if (
networkLower === "twitter"
) {
iconName = "simple-icons:x";
} else if (
networkLower === "youtube"
) {
iconName =
"simple-icons:youtube";
}
return (
<a
@ -215,9 +225,8 @@ const data = resumeData;
rel="noopener noreferrer"
class="link link-hover inline-flex items-center gap-1 text-sm sm:text-base"
>
<Icon name={iconName} />{" "}
{profile.network} (
{profile.username})
<Icon name={iconName} />
{profile.network}
</a>
);
},
@ -229,93 +238,62 @@ const data = resumeData;
{data.sections.skills &&
data.sections.skills.items &&
data.sections.skills.items.length > 0 && (
<ResumeSkills
title={data.sections.skills.name}
skills={data.sections.skills.items}
client:visible
/>
data.sections.skills.items.length > 0 &&
resumeConfig.sections.skills?.enabled && (
<div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body p-4 sm:p-6">
<h2 class="card-title text-xl sm:text-2xl">
{resumeConfig.sections.skills.title || data.sections.skills.name || "Skills"}
</h2>
<ResumeSkills
skills={data.sections.skills.items}
client:load
/>
</div>
</div>
)}
{data.sections.experience &&
data.sections.experience.items &&
data.sections.experience.items.length > 0 && (
data.sections.experience.items.length > 0 &&
resumeConfig.sections.experience?.enabled && (
<div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body p-4 sm:p-6">
<h2 class="card-title text-xl sm:text-2xl">
{data.sections.experience.name ||
"Experience"}
{resumeConfig.sections.experience.title || data.sections.experience.name || "Experience"}
</h2>
<div class="space-y-3 sm:space-y-4">
<div class="space-y-4 sm:space-y-6">
{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-lg sm:text-xl font-medium p-3 sm:p-4">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-1 sm:gap-2">
<span class="font-semibold">
{exp.position} at{" "}
{exp.company}
</span>
<div class="flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-3 text-sm sm:text-base font-normal">
<span>
{exp.date}
</span>
{exp.location && (
<span class="text-base-content/70">
{
exp.location
}
</span>
)}
</div>
</div>
</summary>
<div class="collapse-content p-3 sm:p-4">
{exp.url &&
exp.url.href && (
<a
href={
exp.url.href
}
target="_blank"
rel="noopener noreferrer"
class="link link-primary block mb-2 text-sm sm:text-base break-all"
>
{exp.url.href}
</a>
)}
<div class="mt-2">
<ul class="list space-y-1">
{exp.summary
.replace(
/<\/?ul>|<\/?p>/g,
"",
)
.split("<li>")
.filter(
(item) =>
item.trim() !==
"",
)
.map((item) => (
<li class="list-row text-sm sm:text-base">
{item.replace(
"</li>",
"",
)}
</li>
))}
</ul>
</div>
(experience) => (
<div class="border-l-2 border-primary pl-4 sm:pl-6">
<h3 class="text-lg sm:text-xl font-semibold">
{experience.position}
</h3>
<div class="flex flex-col sm:flex-row sm:items-center sm:gap-4 text-sm sm:text-base text-base-content/70 mb-2">
<span class="font-medium">
{experience.company}
</span>
<span>{experience.date}</span>
<span>
{experience.location}
</span>
</div>
</details>
<div
class="prose prose-sm sm:prose-base max-w-none"
set:html={experience.summary}
/>
{experience.url && experience.url.href && (
<a
href={experience.url.href}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-1 text-primary hover:text-primary-focus text-sm mt-2"
>
<Icon name="mdi:link" />
Company Website
</a>
)}
</div>
),
)}
</div>
@ -325,28 +303,33 @@ const data = resumeData;
{data.sections.education &&
data.sections.education.items &&
data.sections.education.items.length > 0 && (
data.sections.education.items.length > 0 &&
resumeConfig.sections.education?.enabled && (
<div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body p-4 sm:p-6">
<h2 class="card-title text-xl sm:text-2xl">
{data.sections.education.name ||
"Education"}
{resumeConfig.sections.education.title || data.sections.education.name || "Education"}
</h2>
<div class="space-y-3 sm:space-y-4">
<div class="space-y-4">
{data.sections.education.items.map(
(edu, index) => (
<div>
<h3 class="text-base sm:text-lg font-semibold">
{edu.institution}
(education) => (
<div class="border-l-2 border-secondary pl-4 sm:pl-6">
<h3 class="text-lg sm:text-xl font-semibold">
{education.institution}
</h3>
<p class="text-sm sm:text-base">
{edu.studyType} - {edu.area}{" "}
({edu.date})
</p>
{edu.summary && (
<div class="text-sm sm:text-base text-base-content/70 mb-2">
<span class="font-medium">
{education.studyType} in{" "}
{education.area}
</span>
<span class="block sm:inline sm:ml-4">
{education.date}
</span>
</div>
{education.summary && (
<div
class="ml-2 sm:ml-4 text-xs sm:text-sm mt-1"
set:html={edu.summary}
class="prose prose-sm sm:prose-base max-w-none"
set:html={education.summary}
/>
)}
</div>
@ -359,23 +342,28 @@ const data = resumeData;
{data.sections.volunteer &&
data.sections.volunteer.items &&
data.sections.volunteer.items.length > 0 && (
data.sections.volunteer.items.length > 0 &&
resumeConfig.sections.volunteer?.enabled && (
<div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body p-4 sm:p-6">
<h2 class="card-title text-xl sm:text-2xl">
{data.sections.volunteer.name ||
"Volunteering"}
{resumeConfig.sections.volunteer.title || data.sections.volunteer.name || "Volunteer Work"}
</h2>
<div class="space-y-3 sm:space-y-4">
<div class="space-y-4">
{data.sections.volunteer.items.map(
(vol, index) => (
<div>
<h3 class="text-base sm:text-lg font-semibold">
{vol.organization}
(volunteer) => (
<div class="border-l-2 border-accent pl-4 sm:pl-6">
<h3 class="text-lg sm:text-xl font-semibold">
{volunteer.organization}
</h3>
<p class="text-sm sm:text-base">
{vol.position} ({vol.date})
</p>
<div class="text-sm sm:text-base text-base-content/70 mb-2">
<span class="font-medium">
{volunteer.position}
</span>
<span class="block sm:inline sm:ml-4">
{volunteer.date}
</span>
</div>
</div>
),
)}