diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 3b0c119..1fc4992 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -160,7 +160,7 @@ export default function AdminPage() { "projects.json": { name: "", description: "", link: "", open_source: false }, "mini_projects.json": { title: "", description: "", why: "" }, "experience.json": { name: "", type: "experience", description: "" }, - "real_work.json": { company: "", summary: "" } + "real_work.json": { company: "", role: "", from: "", until: "", summary: "" } }; setData([templates[selectedFile], ...data]); }; @@ -333,6 +333,18 @@ export default function AdminPage() { updateEntry(idx, "company", e.target.value)} className="w-full bg-black/40 border border-white/10 rounded-lg p-2 text-sm" /> +
+ + updateEntry(idx, "role", e.target.value)} className="w-full bg-black/40 border border-white/10 rounded-lg p-2 text-sm" /> +
+
+ + updateEntry(idx, "from", e.target.value)} className="w-full bg-black/40 border border-white/10 rounded-lg p-2 text-sm" placeholder="YYYY-MM" /> +
+
+ + updateEntry(idx, "until", e.target.value)} className="w-full bg-black/40 border border-white/10 rounded-lg p-2 text-sm" placeholder="YYYY-MM or Present" /> +
updateEntry(idx, "url", e.target.value)} className="w-full bg-black/40 border border-white/10 rounded-lg p-2 text-sm" /> diff --git a/src/sections/WorkExperience.tsx b/src/sections/WorkExperience.tsx index 6150f56..117c42f 100644 --- a/src/sections/WorkExperience.tsx +++ b/src/sections/WorkExperience.tsx @@ -6,7 +6,50 @@ interface WorkExperienceProps { realWork: RealWork[]; } +function getWorkDateTimestamp(dateValue?: string) { + if (!dateValue) return Number.NEGATIVE_INFINITY; + const timestamp = Date.parse(dateValue); + return Number.isNaN(timestamp) ? Number.NEGATIVE_INFINITY : timestamp; +} + +function getSortTimestamp(entry: RealWork) { + if (!entry.until || entry.until.trim().toLowerCase() === "present") { + return Number.POSITIVE_INFINITY; + } + const untilTimestamp = getWorkDateTimestamp(entry.until); + if (untilTimestamp !== Number.NEGATIVE_INFINITY) return untilTimestamp; + return getWorkDateTimestamp(entry.from); +} + +function formatWorkDate(dateValue: string) { + const yearMonthMatch = /^(\d{4})-(\d{2})$/.exec(dateValue.trim()); + if (yearMonthMatch) { + const year = Number.parseInt(yearMonthMatch[1], 10); + const monthIndex = Number.parseInt(yearMonthMatch[2], 10) - 1; + if (monthIndex >= 0 && monthIndex <= 11) { + return new Date(Date.UTC(year, monthIndex, 1)).toLocaleDateString("en-US", { + year: "numeric", + month: "short", + timeZone: "UTC", + }); + } + } + + const timestamp = Date.parse(dateValue); + if (Number.isNaN(timestamp)) return dateValue; + return new Date(timestamp).toLocaleDateString("en-US", { + year: "numeric", + month: "short", + }); +} + export function WorkExperience({ realWork }: WorkExperienceProps) { + const sortedRealWork = [...realWork].sort( + (a, b) => + getSortTimestamp(b) - getSortTimestamp(a) || + getWorkDateTimestamp(b.from) - getWorkDateTimestamp(a.from), + ); + return (
@@ -24,13 +67,28 @@ export function WorkExperience({ realWork }: WorkExperienceProps) {
) : (
- {realWork.map((entry, index) => ( + {sortedRealWork.map((entry, index) => (
-

{entry.company}

+
+

{entry.company}

+ {entry.role ? ( +

{entry.role}

+ ) : null} + {entry.from || entry.until ? ( +

+ {entry.from ? formatWorkDate(entry.from) : "Unknown"} -{" "} + {entry.until + ? entry.until.trim().toLowerCase() === "present" + ? "Present" + : formatWorkDate(entry.until) + : "Present"} +

+ ) : null} +
{entry.url ? (