Skip to content

Commit

Permalink
feat: projects in cv
Browse files Browse the repository at this point in the history
  • Loading branch information
jedwards1230 committed Jan 1, 2024
1 parent 5c44499 commit 88ce051
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 121 deletions.
4 changes: 2 additions & 2 deletions src/app/(admin)/admin/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export default function Layout({ children }: { children: React.ReactNode }) {
<Header />

<div className="rounded-sm grid grid-cols-12 overflow-hidden border border-border h-full w-full">
<div className="flex w-full col-span-2 flex-col justify-between gap-2">
<div className="w-full transition-all hidden lg:flex flex-col border-r border-border">
<div className="hidden lg:flex w-full col-span-2 flex-col justify-between gap-2">
<div className="w-full transition-all flex flex-col border-r border-border">
<NavItem to={"/admin/about"}>About</NavItem>
<NavItem to={"/admin/experience"}>
Experience
Expand Down
4 changes: 3 additions & 1 deletion src/app/(index)/DownloadResume.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import { ExternalLinkIcon } from "lucide-react";
import { usePlausible } from "next-plausible";
import Link from "next/link";
Expand All @@ -12,7 +14,7 @@ export default function DownloadResume() {
target="_blank"
className="group inline-flex select-none gap-4 hover:underline"
>
View Resume
Download Resume
<span className="pt-0.5 transition-all duration-150 group-hover:sm:translate-x-1">
<ExternalLinkIcon />
</span>
Expand Down
26 changes: 1 addition & 25 deletions src/app/(index)/Projects.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use client";

import { useMemo } from "react";
import { usePlausible } from "next-plausible";

import TagList from "@/components/TagList";
Expand All @@ -9,32 +8,9 @@ import ProjectDialog from "@/components/dialogs/ProjectDialog";
export default function Projects({ projects }: { projects: Project[] }) {
const plausible = usePlausible();

const sortedProjects = useMemo(
() =>
projects.sort((a, b) => {
// sort by year, most recent first
if (a.date.getFullYear() > b.date.getFullYear()) return -1;
if (a.date.getFullYear() < b.date.getFullYear()) return 1;
// sort by month, most recent first
if (a.date.getMonth() > b.date.getMonth()) return -1;
if (a.date.getMonth() < b.date.getMonth()) return 1;
// sort by favorite
if (a.favorite && !b.favorite) return -1;
if (!a.favorite && b.favorite) return 1;
// sort by company
if (a.company > b.company) return 1;
if (a.company < b.company) return -1;
// sort by title
if (a.title > b.title) return 1;
if (a.title < b.title) return -1;
return 0;
}),
[projects]
);

return (
<div className="grid grid-cols-12 gap-4 md:gap-6">
{sortedProjects.map((p, i) => (
{projects.map((p, i) => (
<ProjectDialog
project={p}
className="col-span-6 md:col-span-4 lg:col-span-3"
Expand Down
77 changes: 77 additions & 0 deletions src/app/(index)/cv/Experiences.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { getAllExperiences } from "@/models/experience.server";

export default async function Experiences() {
const experiences = await getAllExperiences("endDate");
return (
<div className="space-y-2">
<div className="text-xl font-semibold">Experience</div>
<div className="space-y-4">
{experiences.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>
<div className="text-sm px-2">
{experience.description.map(d => (
<div key={d}>{d}</div>
))}
</div>
</div>
);
})}
</div>
</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`;
}
37 changes: 37 additions & 0 deletions src/app/(index)/cv/Projects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import TagList from "@/components/TagList";
import { getAllProjects } from "@/models/project.server";

export default async function Projects() {
const projects = await getAllProjects();

return (
<div className="space-y-2">
<div className="text-xl font-semibold">Projects</div>
<div className="space-y-4">
{projects.map(project => (
<div className="space-y-1" key={project.id}>
<div className="flex items-center justify-between">
<div className="flex gap-2 items-center">
<div className="font-medium">
{project.title}
</div>
{"-"}
<div className="text-sm">{project.company}</div>
</div>
<p className="text-sm text-secondary-foreground">
{project.date.getMonth() + 1}/
{project.date.getFullYear()}
</p>
</div>
<div className="text-sm px-2">
{project.description}
</div>
<div>
<TagList tags={project.tags} />
</div>
</div>
))}
</div>
</div>
);
}
95 changes: 6 additions & 89 deletions src/app/(index)/cv/page.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { Button } from "@/components/ui/button";
import { getAbout } from "@/models/about.server";
import { getAllExperiences } from "@/models/experience.server";
import { getAllProjects } from "@/models/project.server";
import Link from "next/link";
import Experiences from "./Experiences";
import Projects from "./Projects";

export default async function Page() {
const [about, projects, experience] = await Promise.all([
await getAbout(),
await getAllProjects(),
await getAllExperiences("endDate"),
]);
const about = await getAbout();

const linkedInUsername = about.linkedin.replace(/\/$/, "").split("/").pop();
const githubUsername = about.github.replace(/\/$/, "").split("/").pop();

return (
<div className="max-w-4xl space-y-6 mx-auto py-16">
<div className="max-w-4xl px-4 space-y-6 mx-auto py-16">
<Button className="!px-0" variant="link" asChild>
<Link href="/">Home</Link>
</Button>
Expand Down Expand Up @@ -52,87 +48,8 @@ export default async function Page() {
</a>
</div>
</div>
<div className="space-y-1">
<div className="text-xl font-semibold">Experience</div>
<div className="space-y-2">
{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>
<div className="text-sm px-2">
{experience.description.map(d => (
<div key={d}>{d}</div>
))}
</div>
</div>
);
})}
</div>
</div>
{/* <div>
<div className="text-lg font-semibold">Projects</div>
<div>
{projects.map(project => (
<div key={project.id}>
<div>{project.title}</div>
<div>{project.description}</div>
</div>
))}
</div>
</div> */}
<Experiences />
<Projects />
</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`;
}
27 changes: 23 additions & 4 deletions src/models/project.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,29 @@ export async function getAllProjects(): Promise<Project[]> {
projects.push(project);
}
}
return projects.map(p => ({
...p,
date: new Date(p.date),
}));
return projects
.map(p => ({
...p,
date: new Date(p.date),
}))
.sort((a, b) => {
// sort by year, most recent first
if (a.date.getFullYear() > b.date.getFullYear()) return -1;
if (a.date.getFullYear() < b.date.getFullYear()) return 1;
// sort by month, most recent first
if (a.date.getMonth() > b.date.getMonth()) return -1;
if (a.date.getMonth() < b.date.getMonth()) return 1;
// sort by favorite
if (a.favorite && !b.favorite) return -1;
if (!a.favorite && b.favorite) return 1;
// sort by company
if (a.company > b.company) return 1;
if (a.company < b.company) return -1;
// sort by title
if (a.title > b.title) return 1;
if (a.title < b.title) return -1;
return 0;
});
}

export async function updateProject(p: Project): Promise<Project> {
Expand Down

0 comments on commit 88ce051

Please sign in to comment.