rework of experience
All checks were successful
Build and Deploy Gabriel Kaszewski Portfolio / build-and-deploy-local (push) Successful in 1m8s
All checks were successful
Build and Deploy Gabriel Kaszewski Portfolio / build-and-deploy-local (push) Successful in 1m8s
This commit is contained in:
83
components/experience-timeline.tsx
Normal file
83
components/experience-timeline.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import { Job } from "@/lib/types";
|
||||
import Chip from "./chip";
|
||||
import formatDate from "@/utils/format-date";
|
||||
|
||||
interface ExperienceTimelineProps {
|
||||
jobs: Job[];
|
||||
newestFirst?: boolean;
|
||||
}
|
||||
|
||||
const ExperienceTimeline = ({ jobs, newestFirst = true }: ExperienceTimelineProps) => {
|
||||
const sorted = [...jobs].sort((a, b) => {
|
||||
const diff = new Date(b.start_date).getTime() - new Date(a.start_date).getTime();
|
||||
return newestFirst ? diff : -diff;
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="relative w-full max-w-3xl mx-auto flex flex-col gap-0">
|
||||
<div className="absolute left-[9px] top-3 bottom-3 w-px bg-gradient-to-b from-white/30 to-white/0" />
|
||||
{sorted.map((job) => (
|
||||
<div key={job.id} className="flex gap-6 pb-10 last:pb-0">
|
||||
<div className="flex flex-col items-center shrink-0 w-5 pt-1.5 z-10">
|
||||
<div className="w-3 h-3 rounded-full bg-white/40 border border-white/20 shadow-[0_0_8px_rgba(255,255,255,0.2)]" />
|
||||
</div>
|
||||
<div className="flex-1 transition-all duration-300 bg-white/5 backdrop-blur-md border border-white/10 rounded-3xl hover:bg-white/10 hover:border-white/20 shadow-xl group p-5">
|
||||
<div className="flex justify-between items-start flex-wrap gap-1 mb-1">
|
||||
<h4 className="text-lg font-semibold text-white">{job.position}</h4>
|
||||
<span className="text-xs text-white/40">
|
||||
{formatDate(job.start_date)} –{" "}
|
||||
{job.still_working ? "Present" : job.end_date ? formatDate(job.end_date) : "—"}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-white/60 mb-4">{job.company}</p>
|
||||
|
||||
{job.summary && (
|
||||
<p className="text-sm text-white/50 italic mb-4">{job.summary}</p>
|
||||
)}
|
||||
|
||||
{job.sub_phases && job.sub_phases.length > 0 && (
|
||||
<div className="flex flex-col gap-3 mb-4">
|
||||
{job.sub_phases.map((phase) => (
|
||||
<div
|
||||
key={phase.label}
|
||||
className="bg-white/[0.03] border border-white/[0.07] rounded-xl px-4 py-3"
|
||||
>
|
||||
<div className="flex justify-between items-center flex-wrap gap-1 mb-2">
|
||||
<span className="text-[11px] font-semibold uppercase tracking-widest text-white/50">
|
||||
{phase.label}
|
||||
</span>
|
||||
<span className="text-[10px] text-white/30">
|
||||
{formatDate(phase.start_date)} –{" "}
|
||||
{phase.end_date ? formatDate(phase.end_date) : "Present"}
|
||||
</span>
|
||||
</div>
|
||||
<ul className="list-disc list-inside space-y-1">
|
||||
{phase.bullets.map((b, i) => (
|
||||
<li key={i} className="text-xs text-white/50 leading-relaxed">
|
||||
{b}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="border-t border-white/10 pt-4 mt-2">
|
||||
<p className="text-[10px] uppercase tracking-widest text-white/30 mb-2">
|
||||
Technologies
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{job.technologies.map((tech) => (
|
||||
<Chip key={tech} text={tech} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExperienceTimeline;
|
||||
Reference in New Issue
Block a user