204 lines
5.9 KiB
TypeScript
204 lines
5.9 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import SafeImage from "./SafeImage";
|
|
interface Experience {
|
|
name: string;
|
|
company: string;
|
|
position: string;
|
|
description: string;
|
|
startDate: string;
|
|
endDate: string;
|
|
logo?: string;
|
|
}
|
|
|
|
interface ExperienceProps {
|
|
experiences: Experience[];
|
|
}
|
|
|
|
function formatDate(d: string) {
|
|
if (d === "current") return "Present";
|
|
const [, m, y] = d.split("-");
|
|
const months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
|
return `${months[parseInt(m) - 1]} ${y}`;
|
|
}
|
|
|
|
function ExperienceItem({ exp, index }: { exp: Experience; index: number }) {
|
|
const isCurrent = exp.endDate === "current";
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
display: "grid",
|
|
gridTemplateColumns: "120px 1px 1fr",
|
|
gap: "0 2rem",
|
|
paddingBottom: "3rem",
|
|
}}
|
|
>
|
|
{/* Date */}
|
|
<div style={{ textAlign: "right", paddingTop: "2px" }}>
|
|
<div
|
|
className="font-mono"
|
|
style={{
|
|
fontFamily: "var(--font-jetbrains), monospace",
|
|
fontSize: "0.62rem",
|
|
letterSpacing: "0.08em",
|
|
color: isCurrent ? "#c8a96e" : "#4a5060",
|
|
lineHeight: 1.6,
|
|
}}
|
|
>
|
|
{isCurrent && (
|
|
<div style={{ color: "#c8a96e", marginBottom: "0.25rem", letterSpacing: "0.14em" }}>
|
|
● NOW
|
|
</div>
|
|
)}
|
|
{formatDate(exp.startDate)}
|
|
<br />—<br />
|
|
{formatDate(exp.endDate)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Line with dot */}
|
|
<div style={{ position: "relative", display: "flex", justifyContent: "center" }}>
|
|
<div style={{ width: "1px", background: "#1c1f26", height: "100%" }} />
|
|
<div
|
|
style={{
|
|
position: "absolute",
|
|
top: "4px",
|
|
width: "8px",
|
|
height: "8px",
|
|
borderRadius: "50%",
|
|
background: isCurrent ? "#c8a96e" : "#1c1f26",
|
|
border: isCurrent ? "none" : "1px solid #4a5060",
|
|
left: "50%",
|
|
transform: "translateX(-50%)",
|
|
}}
|
|
/>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div>
|
|
<div style={{ display: "flex", alignItems: "center", gap: "0.75rem", marginBottom: "0.5rem" }}>
|
|
{exp.logo && (
|
|
<SafeImage
|
|
src={exp.logo}
|
|
alt={exp.company}
|
|
width={28}
|
|
height={28}
|
|
fallbackLabel={exp.company.slice(0, 2).toUpperCase()}
|
|
style={{ width: "24px", height: "24px", objectFit: "contain", filter: "brightness(0.7) grayscale(0.4)" }}
|
|
/>
|
|
)}
|
|
<span
|
|
className="section-label"
|
|
style={{ fontSize: "0.58rem" }}
|
|
>
|
|
{exp.company}
|
|
</span>
|
|
</div>
|
|
|
|
<h3
|
|
className="font-display"
|
|
style={{
|
|
fontFamily: "var(--font-bebas), sans-serif",
|
|
fontSize: "1.5rem",
|
|
letterSpacing: "0.04em",
|
|
color: "#e2e4e9",
|
|
marginBottom: "0.5rem",
|
|
}}
|
|
>
|
|
{exp.position}
|
|
</h3>
|
|
<p
|
|
style={{
|
|
fontFamily: "var(--font-lora), serif",
|
|
fontSize: "0.9rem",
|
|
lineHeight: 1.7,
|
|
color: "#6b7280",
|
|
}}
|
|
>
|
|
{exp.description}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function Experience({ experiences }: ExperienceProps) {
|
|
const [showAll, setShowAll] = useState(false);
|
|
|
|
return (
|
|
<section
|
|
id="experience"
|
|
style={{ padding: "8rem 2rem", background: "#0a0b0e" }}
|
|
>
|
|
<div style={{ maxWidth: "1200px", margin: "0 auto" }}>
|
|
<div style={{ marginBottom: "4rem" }}>
|
|
<div className="section-label" style={{ marginBottom: "0.75rem" }}>Career Path</div>
|
|
<h2
|
|
className="font-display"
|
|
style={{
|
|
fontFamily: "var(--font-bebas), sans-serif",
|
|
fontSize: "clamp(2.5rem, 6vw, 5rem)",
|
|
letterSpacing: "0.04em",
|
|
color: "#e2e4e9",
|
|
lineHeight: 1,
|
|
}}
|
|
>
|
|
Experience
|
|
</h2>
|
|
<div style={{ width: "48px", height: "1px", background: "#c8a96e", marginTop: "1rem" }} />
|
|
</div>
|
|
|
|
<div>
|
|
{(showAll ? experiences : experiences.slice(0, 2)).map((exp, i) => (
|
|
<div
|
|
key={exp.name}
|
|
style={{
|
|
opacity: 1,
|
|
animation: "fadeUp 0.6s ease both",
|
|
animationDelay: `${i * 100}ms`
|
|
}}
|
|
>
|
|
<ExperienceItem exp={exp} index={i} />
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{experiences.length > 2 && (
|
|
<div style={{ display: "flex", justifyContent: "center", marginTop: "1rem" }}>
|
|
<button
|
|
onClick={() => setShowAll(!showAll)}
|
|
style={{
|
|
fontFamily: "var(--font-jetbrains), monospace",
|
|
fontSize: "0.75rem",
|
|
letterSpacing: "0.15em",
|
|
textTransform: "uppercase",
|
|
padding: "14px 28px",
|
|
background: "transparent",
|
|
border: "1px solid #1c1f26",
|
|
color: "#c8a96e",
|
|
cursor: "pointer",
|
|
transition: "all 0.3s ease",
|
|
display: "inline-flex",
|
|
alignItems: "center",
|
|
gap: "0.5rem"
|
|
}}
|
|
onMouseEnter={(e) => {
|
|
e.currentTarget.style.background = "rgba(200, 169, 110, 0.03)";
|
|
e.currentTarget.style.borderColor = "#c8a96e";
|
|
}}
|
|
onMouseLeave={(e) => {
|
|
e.currentTarget.style.background = "transparent";
|
|
e.currentTarget.style.borderColor = "#1c1f26";
|
|
}}
|
|
>
|
|
{showAll ? "— Show Less" : "+ Show More"}
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|