Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Website revamp #50

Merged
merged 19 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ This is my personal website's repository! Hopefully you're here because you like

I built my website using Next.js and Tailwind CSS.

## Getting Started
Run `npm i` to install packages. Then `npm run dev` to run the site locally in dev mode.

### Past Stuff

#### Netlify CMS
Expand Down
17 changes: 17 additions & 0 deletions app/about/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getMDXComponent } from 'mdx-bundler/client';

import { Components as MDXComponents } from '@components/mdx/components';

import { GetAboutMDX } from '@lib/mdxUtils';

export default async function Page() {
const { code } = await GetAboutMDX('about');
const Component = getMDXComponent(code);

return (
<div className="flex flex-col gap-y-2">
<span className="text-4xl font-medium">About me</span>
<Component components={MDXComponents} />
</div>
);
}
7 changes: 7 additions & 0 deletions app/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use client';

import NotFound from '@components/notFound';

export default function Error() {
return <NotFound />;
}
26 changes: 26 additions & 0 deletions app/layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Navbar from '@components/navbar';
import Footer from '@components/footer';

import NavbarButtons from '@config/navbarButtons.config';

import './styles/globals.css';

export const metadata = {
title: {
default: 'Samuel Ping',
template: '%s | Sam Ping',
},
description: 'Welcome to Next.js',
};

export default function RootLayout({ children }) {
return (
<html lang="en">
<body className="min-h-screen max-w-screen-lg flex flex-col gap-y-32 px-5 py-12 mx-auto bg-green-100">
<Navbar navbarButtons={NavbarButtons} />
<main className="flex flex-col flex-grow gap-y-14">{children}</main>
<Footer navbarButtons={NavbarButtons} />
</body>
</html>
);
}
5 changes: 5 additions & 0 deletions app/not-found.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import NotFound from '@components/notFound';

export default function Error() {
return <NotFound />;
}
56 changes: 56 additions & 0 deletions app/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Image from 'next/image';
import Link from 'next/link';

import Button from '@components/rightArrowButton';
import { ProjectCardCarousel } from '@components/projectCardCarousel';

import profilePic from '@public/assets/sam.jpg';

import { GetProjectDetails } from '@lib/mdxUtils';

export default async function Page() {
const projects = await GetProjectDetails(4);

return (
<>
{/* about me section */}
<div className="pb-16 flex flex-col-reverse items-center gap-y-4 md:flex-row md:justify-between md:pb-32">
<div className="max-w-md flex flex-col space-y-5">
<span className="text-4xl font-medium">
Hey! I&apos;m Sam Ping, a...
</span>
<span className="text-2xl font-light">
... software engineer at MongoDB, Rutgers University graduate, avid
tennis player, budding boulderer, occasional theater performer, and
neglectful plant dad. I&apos;m currently based out of NYC.
</span>
<Button text={'more about me'} url={'/about'} />
</div>

<Image
src={profilePic}
alt="Photo of Sam"
placeholder="blur"
priority
className="w-48 h-48 md:w-64 md:h-64 rounded-full object-cover"
/>
</div>

{/* projects section */}
<div className="flex flex-col gap-y-8">
<div className="flex flex-col gap-y-2">
<span className="text-4xl font-medium">Projects</span>
<span className="text-base font-light">
Here are some of my recent projects that I&apos;ve been working on!
Or,{' '}
<Link href="/projects" className="underline">
see all my projects
</Link>
.
</span>
</div>
<ProjectCardCarousel projects={projects} />
</div>
</>
);
}
65 changes: 65 additions & 0 deletions app/projects/[slug]/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { getMDXComponent } from 'mdx-bundler/client';

import { CodeBracketsIcon, ExternalLinkIcon } from '@components/icons';
import Chip from '@components/chip';
import BackButton from '@components/leftArrowButton';
import { Components as MDXComponents } from '@components/mdx/components';
import IconButton from '@components/iconButton';

import { GetProject, GetProjectDetails } from '@lib/mdxUtils';

export async function generateStaticParams() {
const projects = await GetProjectDetails();

return projects.props.projects.map((project) => ({
slug: project.title,
}));
}

export default async function Page({ params }) {
const { code, details } = await GetProject(`projects/${params.slug}`);
const Component = getMDXComponent(code);

const tags = details.tags;

return (
<div className="flex flex-col gap-y-10">
<div className="flex flex-col gap-y-2">
<BackButton text="all projects" url="/projects" />
<span className="text-4xl font-medium">{details.title}</span>
<span className="text-xl font-light italic">{details.dates}</span>
<div className="flex flex-row gap-1">
{details.repo ? (
<IconButton
text="view code"
icon={<CodeBracketsIcon className={''} />}
url={details.repo}
/>
) : (
<></>
)}

{details.website ? (
<IconButton
text="view site"
icon={<ExternalLinkIcon className={''} />}
url={details.website}
/>
) : (
<></>
)}
</div>
</div>
<Component components={MDXComponents} />
{/* tags */}
<div className="w-full flex flex-row flex-wrap gap-1">
<span>tags:</span>
{tags === undefined || tags.length == 0 ? (
<></>
) : (
tags.map((tag) => <Chip text={tag} key={tag} />)
)}
</div>
</div>
);
}
26 changes: 26 additions & 0 deletions app/projects/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import ProjectCard from '@components/projectCard';

import { GetProjectDetails } from '@lib/mdxUtils';

export default async function Page() {
const projects = await GetProjectDetails();

return (
<div className="flex flex-col gap-y-4">
<span className="text-4xl font-medium">Projects</span>
<div className="grid grid-cols-1 gap-3 justify-items-center md:justify-items-start sm:grid-cols-2 md:-mx-6 md:grid-cols-3 lg:grid-cols-4">
{projects.props.projects.map((project) => {
return (
<ProjectCard
key={project.details.title}
title={project.details.title}
dates={project.details.dates}
gist={project.details.gist}
tags={project.details.tags}
/>
);
})}
</div>
</div>
);
}
File renamed without changes.
13 changes: 13 additions & 0 deletions components/Chip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use client';

const Chip = ({ text }) => {
return (
<div className="flex justify-center items-center py-1 px-2 rounded-full text-green-100 group-hover:text-green-500 bg-green-500 group-hover:bg-green-100">
<div className="text-sm font-normal leading-none max-w-full flex-initial">
{text}
</div>
</div>
);
};

export default Chip;
53 changes: 53 additions & 0 deletions components/Footer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use client';

import Link from 'next/link';

import NavbarButton from '@components/navbarButton';
import { EnvelopeIcon, GitHubIcon, LinkedInIcon } from '@components/icons';

const Footer = ({ navbarButtons }) => (
<footer className="flex flex-col space-y-5">
<div className="flex flex-row justify-center md:justify-end space-x-4">
{navbarButtons.map((navButton) => (
<NavbarButton
title={navButton.title}
route={navButton.route}
key={navButton.route}
/>
))}
</div>
<div className="w-full flex flex-row justify-center md:justify-end items-center">
<div className="flex flex-row space-x-5 items-center">
<Link
href="https://github.com/samuel-ping"
target="_blank"
rel="noopener noreferrer"
>
<button className="flex items-center">
<GitHubIcon className="h-10 w-10 text-black hover:text-green-500 transition-colors" />
</button>
</Link>
<Link
href="https://linkedin.com/in/samuelping"
target="_blank"
rel="noopener noreferrer"
>
<button className="flex items-center">
<LinkedInIcon className="h-10 w-10 text-black hover:text-green-500 transition-colors" />
</button>
</Link>
<Link
href="mailto:[email protected]"
target="_blank"
rel="noopener noreferrer"
>
<button className="flex items-center">
<EnvelopeIcon className="h-10 w-10 text-black hover:text-green-500 transition-colors" />
</button>
</Link>
</div>
</div>
</footer>
);

export default Footer;
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client';

import { motion } from 'framer-motion';

export default function HamburgerButton({ isOpen }) {
Expand All @@ -9,7 +11,7 @@ export default function HamburgerButton({ isOpen }) {
fill="none"
strokeWidth="2"
stroke="#000000"
// strokeLinecap="round"
strokeLinecap="round"
animate={isOpen ? 'open' : 'closed'}
className="text-center"
>
Expand Down
6 changes: 4 additions & 2 deletions src/components/Logo.js → components/Logo.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
'use client';

import Link from 'next/link';

import SP from '@components/SP';
import SP from '@components/sp';

const Logo = ({ isAnimated, size, visible }) => (
<>
<Link href="/">
<div className="cursor-pointer p-3">
<div className="cursor-pointer">
<SP
isAnimated={isAnimated}
color="#000000"
Expand Down
67 changes: 67 additions & 0 deletions components/Navbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client';

import { usePathname } from 'next/navigation';

import { Popover, Transition } from '@headlessui/react';

import HamburgerButton from '@components/hamburgerButton';
import Logo from '@components/logo';
import NavbarButton from '@components/navbarButton';

export default function Navbar({ navbarButtons }) {
const pathname = usePathname();

return (
<Popover>
{({ open, close }) => (
<>
<nav className="flex items-center justify-between">
<Logo size={48} visible={true} />

{/* Desktop nav */}
<div className="hidden md:flex flex-row gap-x-4">
{navbarButtons.map((button) => (
<NavbarButton
key={button.route}
// active even when multiple levels deep
active={`/${pathname.split('/')[1]}` === button.route}
title={button.title}
route={button.route}
/>
))}
</div>

<div className="md:hidden">
<Popover.Button>
<HamburgerButton isOpen={open} />
</Popover.Button>
</div>
</nav>
<Transition
enter="transition duration-100 ease-out"
enterFrom="transform scale-95 opacity-0"
enterTo="transform scale-100 opacity-100"
leave="transition duration-75 ease-out"
leaveFrom="transform scale-100 opacity-100"
leaveTo="transform scale-95 opacity-0"
>
<div className="md:hidden flex justify-center">
<Popover.Panel className="absolute w-screen flex flex-col bg-green-100 shadow-lg divide-y divide-green-200">
{navbarButtons.map((button) => (
<NavbarButton
key={button.title}
active={`/${pathname.split('/')[1]}` === button.route}
title={button.title}
route={button.route}
mobile
close={close}
/>
))}
</Popover.Panel>
</div>
</Transition>
</>
)}
</Popover>
);
}
Loading
Loading