--- import BaseLayout from "@/layouts/BaseLayout.astro"; import resume from "@/data/resume.json"; const { basics, work, volunteer, education, skills, projects } = resume as any; function fmtDate(iso: string) { const d = new Date(iso); return d.toLocaleDateString("en-US", { month: "short", year: "numeric" }); } type ExtLink = { label: string; url: string }; type Role = { title: string; startDate: string; endDate?: string; summary?: string; highlights?: string[]; links?: ExtLink[]; }; type TimelineEntry = { type: "work" | "education" | "volunteer"; title: string; subtitle: string; url?: string; location?: string; startDate: string; endDate?: string; summary?: string; highlights?: string[]; links?: ExtLink[]; roles?: Role[]; }; type FlatEntry = { key: string; type: TimelineEntry["type"]; title: string; subtitle: string; url?: string; location?: string; startDate: string; endDate?: string; summary?: string; highlights?: string[]; links?: ExtLink[]; }; /** * Groups flat entries by their `key` (organization/company name). * Single-entry orgs stay flat; multi-entry orgs become grouped cards * with nested roles sorted reverse-chronologically. */ function groupToTimeline(entries: FlatEntry[]): TimelineEntry[] { const byKey = new Map(); for (const e of entries) { if (!byKey.has(e.key)) byKey.set(e.key, []); byKey.get(e.key)!.push(e); } const result: TimelineEntry[] = []; for (const [, items] of byKey) { const sorted = [...items].sort( (a, b) => new Date(b.startDate).getTime() - new Date(a.startDate).getTime(), ); const latest = sorted[0]; if (sorted.length === 1) { result.push({ type: latest.type, title: latest.title, subtitle: latest.subtitle, url: latest.url, location: latest.location, startDate: latest.startDate, endDate: latest.endDate, summary: latest.summary, highlights: latest.highlights, links: latest.links, }); } else { result.push({ type: latest.type, title: latest.subtitle, subtitle: latest.subtitle, url: latest.url, location: latest.location, startDate: latest.startDate, endDate: latest.endDate, roles: sorted.map((e) => ({ title: e.title, startDate: e.startDate, endDate: e.endDate, summary: e.summary, highlights: e.highlights, links: e.links, })), }); } } return result; } const workFlat: FlatEntry[] = work.map((w: any) => ({ key: w.name, type: "work" as const, title: w.position, subtitle: w.name, url: w.url || undefined, location: w.location, startDate: w.startDate, endDate: w.endDate, summary: w.summary, highlights: w.highlights, links: w.links, })); const volunteerFlat: FlatEntry[] = volunteer.map((v: any) => ({ key: v.organization, type: "volunteer" as const, title: v.position, subtitle: v.organization, url: v.url || undefined, location: undefined, startDate: v.startDate, endDate: v.endDate, summary: v.summary, highlights: undefined as string[] | undefined, })); const timeline: TimelineEntry[] = [ ...groupToTimeline(workFlat), ...groupToTimeline(volunteerFlat), ...education.map((e: any) => ({ type: "education" as const, title: e.area ? `${e.studyType} in ${e.area}` : e.studyType, subtitle: e.institution, url: e.url || undefined, location: e.location, startDate: e.startDate, endDate: e.endDate, summary: e.score ? `CGPA: ${e.score}` : undefined, highlights: undefined as string[] | undefined, })), ].sort((a, b) => new Date(b.startDate).getTime() - new Date(a.startDate).getTime()); const typeLabels: Record = { work: "Work", education: "Education", volunteer: "Community", }; ---

{basics.name}

{basics.label}

{basics.summary}

{basics.image ? ( {basics.name} ) : (
)}

Experience & Education

{timeline.map((entry) => { const isActive = !entry.endDate; return (
{typeLabels[entry.type]}
{entry.roles ? ( /* Grouped card: multiple roles at the same org */
{fmtDate(entry.roles[entry.roles.length - 1].startDate)} — {entry.endDate ? fmtDate(entry.endDate) : "Present"}

{entry.url ? {entry.subtitle} : entry.subtitle}

{entry.location &&

{entry.location}

}
{entry.roles.map((role, i) => (

{role.title}

{fmtDate(role.startDate)} — {role.endDate ? fmtDate(role.endDate) : "Present"}
{role.summary &&

{role.summary}

} {role.highlights && role.highlights.length > 0 && (
    {role.highlights.map((h) =>
  • {h}
  • )}
)} {role.links && role.links.length > 0 && ( )}
))}
) : ( /* Single card */
{fmtDate(entry.startDate)} — {entry.endDate ? fmtDate(entry.endDate) : "Present"}

{entry.title}

{entry.url ? {entry.subtitle} : entry.subtitle} {entry.location && · {entry.location}}

{entry.summary &&

{entry.summary}

} {entry.highlights && entry.highlights.length > 0 && (
    {entry.highlights.map((h) =>
  • {h}
  • )}
)} {entry.links && entry.links.length > 0 && ( )}
)}
)})}

Skills

{skills.map((group) => (

{group.name}

{group.keywords.map((kw) => ( {kw} ))}
))}

Projects

{projects.map((p) => (

{p.url ? {p.name} : p.name}

{p.description}

{p.highlights && p.highlights.length > 0 && (
    {p.highlights.map((h) =>
  • {h}
  • )}
)}
))}