Initial website was built base on the context

This commit is contained in:
StormRunner06106
2026-09-11 10:13:41 -07:00
parent 1e532f4c42
commit f80bceaa3c
31 changed files with 4832 additions and 1 deletions
+167
View File
@@ -0,0 +1,167 @@
import { useEffect, useMemo, useState } from "react";
import { getExperience } from "../api";
import Icon from "../components/Icon";
import PageHeader from "../components/PageHeader";
import { ErrorState, LoadingState } from "../components/Status";
function asDate(value) {
const [year, month] = value.split("-").map(Number);
return new Date(year, month - 1, 1);
}
function monthLabel(value) {
return new Intl.DateTimeFormat("en-US", {
month: "short",
year: "numeric",
}).format(asDate(value));
}
function durationLabel(start, end) {
const startDate = asDate(start);
const endDate = end ? asDate(end) : new Date();
const months = Math.max(
1,
(endDate.getFullYear() - startDate.getFullYear()) * 12 +
endDate.getMonth() -
startDate.getMonth(),
);
const years = Math.floor(months / 12);
const remainingMonths = months % 12;
const parts = [];
if (years) parts.push(`${years} yr${years === 1 ? "" : "s"}`);
if (remainingMonths) parts.push(`${remainingMonths} mo`);
return parts.join(" ") || "1 mo";
}
function TimelineItem({ item, index, isExpanded, onToggle }) {
const isCurrent = !item.end;
const year = item.start.slice(0, 4);
return (
<article className={`timeline-item reveal ${isCurrent ? "is-current" : ""}`}>
<div className="timeline-year" aria-hidden="true">
<span>{year}</span>
</div>
<div className="timeline-marker">
<span />
</div>
<div className="timeline-card">
<button
className="timeline-card__header"
onClick={onToggle}
type="button"
aria-expanded={isExpanded}
aria-controls={`experience-${item.id}`}
>
<div>
<div className="timeline-meta">
<span>{monthLabel(item.start)} {item.end ? monthLabel(item.end) : "Present"}</span>
<span>{durationLabel(item.start, item.end)}</span>
{isCurrent && <span className="current-label">Current</span>}
</div>
<h2>{item.role}</h2>
<p className="company-line">{item.company} <span>·</span> {item.location}</p>
</div>
<span className={`expand-button ${isExpanded ? "is-open" : ""}`}>
<Icon name="chevron" />
</span>
</button>
<div
className={`timeline-details ${isExpanded ? "is-open" : ""}`}
id={`experience-${item.id}`}
>
<div className="timeline-details__inner">
<p className="timeline-summary">{item.summary}</p>
<ul className="highlight-list">
{item.highlights.map((highlight) => (
<li key={highlight}>
<span><Icon name="check" size={14} /></span>
{highlight}
</li>
))}
</ul>
{item.projects && (
<div className="project-links">
{item.projects.map((project) => (
<a href={project.href} key={project.name} target="_blank" rel="noreferrer">
<span>
<strong>{project.name}</strong>
<small>{project.period}</small>
</span>
<Icon name="arrowUpRight" size={17} />
</a>
))}
</div>
)}
<div className="tag-row">
{item.technologies.map((technology) => (
<span key={technology}>{technology}</span>
))}
</div>
</div>
</div>
</div>
</article>
);
}
export default function ExperiencePage() {
const [experience, setExperience] = useState([]);
const [expandedId, setExpandedId] = useState("independent");
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
useEffect(() => {
const controller = new AbortController();
getExperience(controller.signal)
.then(setExperience)
.catch((requestError) => {
if (requestError.name !== "AbortError") setError(requestError.message);
})
.finally(() => setLoading(false));
return () => controller.abort();
}, []);
const visibleYears = useMemo(() => {
if (!experience.length) return "2013 — now";
return `${experience.at(-1).start.slice(0, 4)} — now`;
}, [experience]);
return (
<section className="content-page container">
<PageHeader
eyebrow="Experience"
title="A career built close to the work."
description="Product engineering, critical operations, and technical leadership—connected by a habit of making complicated systems easier to use."
aside={
<div className="heading-stat">
<strong>{experience.length || "6"}</strong>
<span>career chapters<br />{visibleYears}</span>
</div>
}
/>
{loading && <LoadingState label="Mapping the timeline" />}
{error && <ErrorState message={error} />}
{!loading && !error && (
<div className="timeline">
{experience.map((item, index) => (
<TimelineItem
index={index}
isExpanded={expandedId === item.id}
item={item}
key={item.id}
onToggle={() => setExpandedId((active) => (active === item.id ? "" : item.id))}
/>
))}
</div>
)}
</section>
);
}