Skip to content

Commit

Permalink
feat: create new landing page (#36)
Browse files Browse the repository at this point in the history
* style: add tailwind utils

* feat: build landing page

* feat: add popover for articulatable def

* style: adjust breakpoints

* fix: header link redirects to "/"

* style: add button and gradients

* style: adjust styles for mobile

* refactor: extract articulation def

* style: unsticky header

* feat: add example cards

* style: adjust styling breakpoints

* chore: update open-graph

* chore: update GhA name

* chore: update open-graph img
  • Loading branch information
KevinWu098 authored Dec 30, 2023
1 parent 2928a20 commit 7f8dd04
Show file tree
Hide file tree
Showing 14 changed files with 831 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs

name: Node.js CI
name: Test Build

on:
push:
Expand Down
154 changes: 84 additions & 70 deletions app/globals.css
Original file line number Diff line number Diff line change
@@ -1,76 +1,90 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;

--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;

--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;

--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;

--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;

--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;

--radius: 0.5rem;
}

.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;

--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;

--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;

--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;

--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;

--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;

--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;

--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;

--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

@layer utilities {
.wrapper {
@apply mx-auto w-full max-w-[1728px] px-2 md:px-20;
}

.flex-center {
@apply flex items-center justify-center;
}

.flex-between {
@apply flex items-center justify-between;
}
}
1 change: 0 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export const metadata: Metadata = {
description:
"Find online, async, and articulatable courses from California Community Colleges.",
url: "https://ge-z.vercel.app",
siteName: "GE-Z",
images: [
{
url: "/open-graph.png",
Expand Down
198 changes: 195 additions & 3 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,201 @@
import Hero from "@/components/hero/Hero";
import { Button, buttonVariants } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { HelpCircle, Search } from "lucide-react";
import Link from "next/link";

const EXAMPLES = [
{
uni: "UC Irvine",
ge: "GE IV - Arts and Humanities",
courses: 150,
link: "/search?uni=University%20of%20California%2C%20Irvine&ge=GE%20IV",
},
{
uni: "UC Santa Barbara",
ge: "GE E - Culture and Thought",
courses: 100,
link: "/search?uni=University%20of%20California%2C%20Santa%20Barbara&ge=GE%20E",
},
{
uni: "UC Irvine",
ge: "GE VIII - Multicultural Studies",
courses: 100,
link: "/search?uni=University%20of%20California%2C%20Irvine&ge=GE%20VII",
},
];

const ArticulatableDefinition = () => {
return (
<Popover>
<PopoverTrigger>
<HelpCircle className="inline-block h-4 w-4" />
</PopoverTrigger>
<PopoverContent>
<p className="text-sm">
&quot;An articulated course is a course... that can be used
to satisfy... general education requirements at another
college or university.&quot; - <br />
<Link
href={
"https://www.sdmesa.edu/about-mesa/administration/articulation/homepage-docs/Articulated%20vs%20Transferable.pdf"
}
referrerPolicy="no-referrer"
target="_blank"
>
<i>
<u>San Diego Mesa College</u>
</i>
</Link>
</p>
</PopoverContent>
</Popover>
);
};

const Graphics = () => {
return (
<div>
<div className="relative isolate">
<div
aria-hidden="true"
className="pointer-events-none absolute inset-x-0 -top-40 -z-10 transform-gpu blur-[52px] sm:-top-48"
>
<div
style={{
clipPath:
"polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)",
}}
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[26.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-blue-500 to-purple-500 opacity-30 sm:left-[calc(50%-30rem)] sm:w-[42.1875rem]"
/>
</div>
</div>
<div className="relative isolate hidden md:flex">
<div
aria-hidden="true"
className="pointer-events-none absolute inset-x-0 -top-40 -z-10 transform-gpu blur-[52px] sm:-top-72"
>
<div
style={{
clipPath:
"polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)",
}}
className="relative aspect-[1155/678] w-[16.125rem] rotate-[30deg] bg-gradient-to-tr from-blue-500 to-purple-500 opacity-30 sm:w-[22.1875rem] md:-right-[0vw] lg:-right-[12vw] xl:-right-[20vw]"
/>
</div>
</div>
</div>
);
};

export default function Home() {
return (
<main className="flex min-h-[calc(100vh-96px)] place-content-center">
<Hero />
<main className="flex min-h-[calc(100vh-96px)] flex-col items-center">
<div className="wrapper mt-20 flex flex-col items-center gap-y-5 text-center md:mt-24">
<div className="flex flex-col items-center gap-y-5 text-center">
<h1 className="flex-center xs:text-5xl max-w-2xl flex-col text-4xl font-bold sm:text-6xl">
<span className="hidden md:flex">
Online, Async, and{" "}
</span>
<span className="flex text-center md:hidden">
Online, Async,
</span>
<span className="xs:text-6xl bg-gradient-to-r from-blue-500 to-purple-500 bg-clip-text text-5xl text-transparent sm:text-7xl md:text-8xl">
Articulatable
</span>
</h1>
<p className="text-gray-600 max-w-prose text-slate-600 sm:text-lg">
GE-Z sources data directly from{" "}
<Link
href="https://assist.org/"
target="_blank"
referrerPolicy="no-referrer"
className="underline"
>
Assist.org
</Link>{" "}
and{" "}
<Link
href="https://cvc.edu/"
target="_blank"
referrerPolicy="no-referrer"
className="underline"
>
CVC.edu
</Link>{" "}
to find you high-quality, articulatable
<ArticulatableDefinition /> California Community College
courses that save you time and money.
</p>
</div>
<Link href={"/search"}>
<Button
className={cn(
buttonVariants({
size: "lg",
}),
"flex-center w-fit gap-2 text-lg text-white",
)}
>
Discover Courses <Search className="h-5 w-5" />
</Button>
</Link>
</div>

<Graphics />

<div className="mx-auto my-24 flex max-w-5xl flex-col gap-4 md:my-32">
<div className="px-6 lg:px-8">
<div className="mx-auto flex max-w-2xl flex-col gap-4 sm:text-center">
<h2 className="text-4xl font-bold text-slate-900 sm:text-5xl">
Check out some searches
</h2>
<p className="text-lg text-slate-600">
GE-Z makes course discovery simple. No complicated
articulation agreements necessary.
</p>
</div>
</div>

<div className="flex flex-wrap gap-4 px-6 sm:justify-center lg:px-8">
{EXAMPLES.map((example) => (
<Card
className="w-[275px] hover:shadow-md sm:w-[300px]"
key={example.uni + example.ge}
>
<CardHeader>
<CardTitle>{example.uni}</CardTitle>
<CardDescription>{example.ge}</CardDescription>
</CardHeader>
<CardFooter className="flex justify-between">
<span className="flex text-neutral-600 sm:hidden">
<b>{example.courses}+</b>&nbsp;Courses
</span>
<span className="hidden text-neutral-600 sm:flex">
<b>{example.courses}+</b>&nbsp;Courses Found
</span>
<Link href={example.link}>
<Button className="text-white">
Go To
</Button>
</Link>
</CardFooter>
</Card>
))}
</div>
</div>
</main>
);
}
Loading

0 comments on commit 7f8dd04

Please sign in to comment.