Skip to content

Commit

Permalink
feat: sorted experiences
Browse files Browse the repository at this point in the history
  • Loading branch information
jedwards1230 committed Jan 1, 2024
1 parent 8dd0a2d commit 9568788
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 38 deletions.
8 changes: 6 additions & 2 deletions script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { readFileSync } from "fs";
import { join } from "path";

async function loadDataFromFile() {
const filePath = join(__dirname, "./data-dev.json");
const filePath = join(__dirname, "./data.json");
const data = JSON.parse(readFileSync(filePath, "utf8"));

// Upload projects
Expand All @@ -16,7 +16,11 @@ async function loadDataFromFile() {

// Upload experiences
for (const experience of data.experience) {
await createExperience(experience);
await createExperience({
...experience,
startDate: new Date(),
endDate: experience.endDate ? new Date() : null,
});
}

// Upload contacts
Expand Down
4 changes: 3 additions & 1 deletion src/app/(admin)/admin/resume/pdf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ export function PdfDocument({ data }: { data: PDFData }) {
<Text>{experience.title}</Text>
</View>
<Text style={tw("uppercase text-[8px]")}>
{experience.period}
{experience.startDate.getDate()} -{" "}
{experience.endDate?.getDate() ??
"Present"}
</Text>
<View style={tw("pl-2")}>
{experience.description.map(item => (
Expand Down
82 changes: 63 additions & 19 deletions src/app/(index)/cv/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default async function Page() {
const [about, projects, experience] = await Promise.all([
await getAbout(),
await getAllProjects(),
await getAllExperiences(),
await getAllExperiences("endDate"),
]);

const linkedInUsername = about.linkedin.replace(/\/$/, "").split("/").pop();
Expand All @@ -28,7 +28,7 @@ export default async function Page() {
<div>{about.location}</div>
</div>

<div className="flex flex-col gap-1 pt-1">
<div className="flex flex-col text-sm gap-1 pt-1">
<a
className="hover:underline"
target="_blank"
Expand All @@ -55,27 +55,52 @@ export default async function Page() {
<div className="space-y-1">
<div className="text-xl font-semibold">Experience</div>
<div className="space-y-2">
{experience.map(experience => (
<div key={experience.id}>
<div className="flex pb-2 justify-between">
<div className="flex gap-2 items-end">
<div className="text-lg font-medium">
{experience.company}
{experience.map(experience => {
const startDate = new Date(experience.startDate);
const endDate = experience.endDate
? new Date(experience.endDate)
: null;

return (
<div key={experience.id}>
<div className="flex pb-2 justify-between">
<div className="flex gap-2 items-end">
<div className="font-medium">
{experience.company}
</div>
{"-"}
<div>{experience.title}</div>
</div>
<div
title={calculateTimeSpent(
startDate,
endDate
)}
className="flex gap-2 text-secondary-foreground"
>
<p>
{startDate.getMonth() + 1}/
{startDate.getFullYear()}
</p>
-
<p>
{endDate
? endDate.getMonth() +
1 +
"/" +
endDate.getFullYear()
: "Present"}
</p>
</div>
{"-"}
<div>{experience.title}</div>
</div>
<div className="text-secondary-foreground">
{experience.period}
<div className="text-sm px-2">
{experience.description.map(d => (
<div key={d}>{d}</div>
))}
</div>
</div>
<div className="text-sm px-2">
{experience.description.map(d => (
<div key={d}>{d}</div>
))}
</div>
</div>
))}
);
})}
</div>
</div>
{/* <div>
Expand All @@ -92,3 +117,22 @@ export default async function Page() {
</div>
);
}

function calculateTimeSpent(startDate: Date, endDate?: Date | null): string {
if (!endDate) {
endDate = new Date();
}

let years = endDate.getFullYear() - startDate.getFullYear();
let months = endDate.getMonth() - startDate.getMonth() + 1;

if (months <= 0) {
years--;
months += 12;
} else if (months > 12) {
years++;
months = 0;
}

return `${years} years, ${months} months`;
}
4 changes: 2 additions & 2 deletions src/app/(index)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import Link from "next/link";
export default async function Page() {
return (
<>
{/* <div className="fixed bottom-0 py-8 right-2 md:right-6 lg:right-10 z-10 flex flex-col h-full items-center justify-between gap-4">
<div className="fixed bottom-0 py-8 right-2 md:right-6 lg:right-10 z-10 flex flex-col h-full items-center justify-between gap-4">
<Button asChild variant="link">
<Link href="/cv">cv</Link>
</Button>
<AdminButton />
</div> */}
</div>
<div className="max-w-screen select-none flex w-full flex-col justify-between gap-4 px-4 pt-8 sm:px-8 md:h-full md:px-16 md:pt-0 lg:px-24 xl:px-32">
<Intro />
<Suspense fallback={null}>
Expand Down
58 changes: 55 additions & 3 deletions src/components/Forms/ExperienceForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,24 @@ export default function ExperienceForm({ data }: { data: Experience }) {
const id = Number(formData.get("id"));
if (!id) return { error: "Invalid id." };

const startYear = Number(formData.get("startYear"));
const startMonth = Number(formData.get("startMonth")) - 1;
const startDate = new Date(startYear, startMonth);

let endDate = null;
const endYear = formData.get("endYear");
const endMonth = formData.get("endMonth");
if (endYear && endMonth) {
endDate = new Date(Number(endYear), Number(endMonth) - 1);
}

try {
await updateExperience({
id,
title: String(formData.get("title")),
company: String(formData.get("company")),
period: String(formData.get("period")),
startDate,
endDate,
summary: String(formData.get("summary")),
description: String(formData.get("description")).split("\n"),
tags: String(formData.get("tags"))
Expand Down Expand Up @@ -64,8 +76,48 @@ export default function ExperienceForm({ data }: { data: Experience }) {
</div>
</div>
<div className="col-span-3">
<Label>Period</Label>
<Input required name="period" defaultValue={data.period} />
<Label>Start Date</Label>
<div className="flex gap-2">
<Input
required
name="startMonth"
type="month"
defaultValue={
new Date(data.startDate).getMonth() + 1
}
/>
<Input
required
name="startYear"
type="year"
defaultValue={new Date(
data.startDate
).getFullYear()}
/>
</div>
</div>
<div className="col-span-3">
<Label>End Date</Label>
<div className="flex gap-2">
<Input
name="endMonth"
type="month"
defaultValue={
data.endDate
? new Date(data.endDate).getMonth() + 1
: undefined
}
/>
<Input
name="endYear"
type="year"
defaultValue={
data.endDate
? new Date(data.endDate).getFullYear()
: undefined
}
/>
</div>
</div>
<div className="col-span-3">
<Label>Summary</Label>
Expand Down
18 changes: 17 additions & 1 deletion src/components/Views/ExperienceView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,30 @@ import Markdown from "@/components/Markdown";
import { Label } from "@/components/ui/label";

export default function ExperienceView({ data }: { data: Experience }) {
const startDate = new Date(data.startDate);
const endDate = data.endDate ? new Date(data.endDate) : null;

return (
<div className="flex transition-all flex-col gap-2">
<div className="w-1/2 pb-4">
<p className="text-2xl font-bold">{data.company}</p>
<p className="text-lg text-secondary-foreground">
{data.title}
</p>
<p>{data.period}</p>
<div className="flex gap-2">
<p>
{startDate.getMonth() + 1}/{startDate.getFullYear()}
</p>
-
<p>
{endDate
? endDate.getMonth() +
1 +
"/" +
endDate.getFullYear()
: "Present"}
</p>
</div>
</div>

<div className="flex flex-col gap-2">
Expand Down
3 changes: 2 additions & 1 deletion src/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ type Experience = {
id: number;
title: string;
company: string;
period: string;
startDate: Date;
endDate: Date | null;
summary: string;
description: string[];
tags: string[];
Expand Down
1 change: 0 additions & 1 deletion src/models/contact.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export async function createContact(contact: Contact): Promise<number> {
const key = `contact-${contact.id}`;
await kv.set(key, JSON.stringify(contact));
const id = await addIdToList("contact-ids", contact.id);
invariant(id, "Failed to add contact ID to list");
return id;
}

Expand Down
46 changes: 41 additions & 5 deletions src/models/experience.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ import { invariant } from "@/lib/utils";
import { kv } from "@vercel/kv";
import { addIdToList, getAllIds } from "./helpers";

function stringify(e: Experience): string {
return JSON.stringify({
...e,
startDate: e.startDate.toDateString(),
endDate: e.endDate ? e.endDate.toDateString() : null,
});
}

export async function createExperience(data: Experience): Promise<number> {
const key = `experience-${data.id}`;
await kv.set(key, JSON.stringify(data));
await kv.set(key, stringify(data));
const id = await addIdToList("experience-ids", data.id);
invariant(id, "Failed to add experience ID to list");
return id;
}

Expand All @@ -19,7 +26,9 @@ export async function getExperienceById(id: number): Promise<Experience> {
return value;
}

export async function getAllExperiences(): Promise<Experience[]> {
export async function getAllExperiences(
sortBy?: keyof Experience
): Promise<Experience[]> {
const ids = await getAllIds("experience-ids");
const experiences = [];
for (const id of ids) {
Expand All @@ -28,10 +37,37 @@ export async function getAllExperiences(): Promise<Experience[]> {
experiences.push(experience);
}
}
return experiences;

const cleanedExperiences = experiences.map(e => ({
...e,
startDate: new Date(e.startDate),
endDate: e.endDate ? new Date(e.endDate) : null,
}));

if (sortBy) {
cleanedExperiences.sort((a, b) => {
switch (sortBy) {
case "endDate":
if (a.endDate === null && b.endDate === null) {
return b.startDate.getTime() - a.startDate.getTime();
}
if (a.endDate === null) return -1;
if (b.endDate === null) return 1;
return b.endDate.getTime() - a.endDate.getTime();
case "startDate":
return a.startDate.getTime() - b.startDate.getTime();
case "company":
return a.company.localeCompare(b.company);
default:
return 0;
}
});
}

return cleanedExperiences;
}

export async function updateExperience(e: Experience) {
const key = `experience-${e.id}`;
await kv.set(key, JSON.stringify(e));
await kv.set(key, stringify(e));
}
3 changes: 1 addition & 2 deletions src/models/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ export async function addIdToList(key: string, id: number) {
ids.push(id);
const res = await kv.set(key, JSON.stringify(ids));
invariant(res, `Failed to add ID to list: ${key}`);
return id;
}
return null;
return id;
}

export async function removeIdFromList(key: string, id: number) {
Expand Down
1 change: 0 additions & 1 deletion src/models/project.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export async function createProject(data: Project): Promise<number> {
const key = `project-${data.id}`;
await kv.set(key, JSON.stringify(data));
const id = await addIdToList("project-ids", data.id);
invariant(id, "Failed to add project ID to list");
return id;
}

Expand Down

0 comments on commit 9568788

Please sign in to comment.