Skip to content

Commit

Permalink
add onboarding screens
Browse files Browse the repository at this point in the history
  • Loading branch information
wwsalmon committed Feb 12, 2023
1 parent 74503c6 commit 7d35f06
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 38 deletions.
2 changes: 1 addition & 1 deletion components/H1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ export default function H1(props: ComponentProps<"h1">) {
delete domProps.className;

return (
<h1 className={classNames("font-bold text-2xl", props.className)} {...domProps}/>
<h1 className={classNames("font-semibold text-5xl font-garamond", props.className)} {...domProps}/>
)
}
14 changes: 14 additions & 0 deletions components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { HydratedDocument } from "mongoose";
import { signOut } from "next-auth/react";

import { IUser } from "../models/models";

export default function Navbar({thisUser}: {thisUser: HydratedDocument<IUser>}) {
return (
<div className="w-full fixed top-0 left-0 h-16 flex items-center px-4">
<img src={thisUser.image} className="w-8 h-8 rounded-full" alt={`Profile picture of ${thisUser.name}`} />
<span className="ml-4">{thisUser.name}</span>
<button className="ml-auto" onClick={() => signOut()}>Sign out</button>
</div>
)
}
5 changes: 1 addition & 4 deletions pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ export default function Document() {
return (
<Html>
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Eczar:wght@400;500;600;700;800&family=Inter:wght@300;400;500;600;700&display=swap"
rel="stylesheet"
/>
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400;1,500;1,700;1,800&family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet"/>
</Head>
<body>
<Main />
Expand Down
63 changes: 30 additions & 33 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import temp from "../data/temp.json";
import temp2 from "../data/temp2.json";
import vaxModels from "../data/vaxModels.json";
import primary from "../data/primary.json";
import Navbar from "../components/Navbar";

const chartPadding = {
top: 8,
Expand Down Expand Up @@ -165,41 +166,37 @@ export default function Index({ thisUser }: {
}

return (
<div className="max-w-2xl mx-auto px-4 py-8">
<div className="p-4 bg-gray-100 rounded-md shadow-md border my-8">
<H2>Account information</H2>
<p>{thisUser.name} / {thisUser.email}</p>
<img src={thisUser.image} alt="Profile picture" />
<button onClick={() => signOut()}>Sign out</button>
</div>
<hr className="my-8"/>
<H1>Immunity graph</H1>
<div className="relative overflow-y-hidden" style={{height: 400, width: "100%"}}>
<svg ref={axisRef} className="absolute top-0 left-0 w-full" style={{height: 400}}/>
<div className="absolute top-0 left-0 w-full overflow-x-auto overflow-y-hidden" style={{height: 400}}>
<svg ref={svgRef}/>
<>
<Navbar thisUser={thisUser}/>
<div className="max-w-2xl mx-auto px-4 py-8">
<H1>Immunity graph</H1>
<div className="relative overflow-y-hidden" style={{height: 400, width: "100%"}}>
<svg ref={axisRef} className="absolute top-0 left-0 w-full" style={{height: 400}}/>
<div className="absolute top-0 left-0 w-full overflow-x-auto overflow-y-hidden" style={{height: 400}}>
<svg ref={svgRef}/>
</div>
</div>
</div>
<hr className="my-8"/>
<H1>Vaccinations</H1>
<H2>Add vaccination</H2>
<div className="flex items-center">
<input type="date" min="2019-01-01" max={format(addDays(new Date(), 1), "yyyy-MM-dd")} className="p-2 border mr-4" value={date} onChange={e => setDate(e.target.value)}/>
<select className="p-2 border mr-4" value={vaxId} onChange={e => setVaxId(e.target.value)}>
{vaxModels.map(d => (
<option value={d} key={d}>{d}</option>
))}
</select>
<button onClick={onAdd} className="p-2 bg-black text-white disabled:opacity-50" disabled={!date}>Add</button>
</div>
<H2>Vaccination record</H2>
{vaxEvents.map(d => (
<div className="p-4 border rounded-md my-2 shadow-md" key={d._id.toString()}>
<p>{format(dateOnly(d.date), "MMMM d, yyyy")}, {d.vaxId}</p>
<button className="bg-black p-2 text-white" onClick={() => onDelete(d._id.toString())}>Delete</button>
<hr className="my-8"/>
<H1>Vaccinations</H1>
<H2>Add vaccination</H2>
<div className="flex items-center">
<input type="date" min="2019-01-01" max={format(addDays(new Date(), 1), "yyyy-MM-dd")} className="p-2 border mr-4" value={date} onChange={e => setDate(e.target.value)}/>
<select className="p-2 border mr-4" value={vaxId} onChange={e => setVaxId(e.target.value)}>
{vaxModels.map(d => (
<option value={d} key={d}>{d}</option>
))}
</select>
<button onClick={onAdd} className="p-2 bg-black text-white disabled:opacity-50" disabled={!date}>Add</button>
</div>
))}
</div>
<H2>Vaccination record</H2>
{vaxEvents.map(d => (
<div className="p-4 border rounded-md my-2 shadow-md" key={d._id.toString()}>
<p>{format(dateOnly(d.date), "MMMM d, yyyy")}, {d.vaxId}</p>
<button className="bg-black p-2 text-white" onClick={() => onDelete(d._id.toString())}>Delete</button>
</div>
))}
</div>
</>
);
}

Expand Down
112 changes: 112 additions & 0 deletions pages/onboarding.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { addDays, format } from "date-fns";
import { useState } from "react";
import { IUser, UserModel } from "../models/models";
import { createAccount } from "../utils/createAccount";
import { cleanForJSON } from "../utils/cleanForJson";
import mongoose, { HydratedDocument } from "mongoose";
import { GetServerSidePropsContext } from "next";
import { getSession, signOut } from "next-auth/react";
import classNames from "classnames";
import axios from "axios";
import { useRouter } from "next/router";
import Navbar from "../components/Navbar";

export default function Onboarding({thisUser}: {thisUser: HydratedDocument<IUser>}) {
const [brand, setBrand] = useState<string>("");
const [date, setDate] = useState<string>("");
const [stage, setStage] = useState<number>(0);
const [isLoading, setIsLoading] = useState<boolean>(false);
const router = useRouter();

const q1fill = {
0: "",
1: "were your primary doses (two for Pfizer and Moderna, one for J&J)?",
2: "was your first booster?",
3: "was your second booster?",
}[stage];

const q2fill = {
0: "",
1: "your last primary dose (second for Pfizer and Moderna, first for J&J)?",
2: "your first booster?",
3: "your second booster?",
}[stage];

function onNext() {
if (stage === 0) return setStage(1);

setIsLoading(true);

axios.post("/api/vaxEvent", {
vaxId: brand + " " + (stage === 1 ? brand === "J&J" ? "1st dose" : "1st and 2nd doses" : stage === 2 ? "first booster" : "second booster"),
date: date,
}).then(res => {
setStage(prev => prev + 1);
}).catch(e => {
console.log(e);
}).finally(() => {
setIsLoading(false);
setBrand("");
setDate("");
})
}

return (
<>
<Navbar thisUser={thisUser}/>
<div className="max-w-2xl mx-auto px-4 py-8">
{stage === 0 ? (
<div className="relative top-[50vh] transform -translate-y-1/2 -mt-8">
<img src="/logo.png" className="w-64 mx-auto block" alt="BoostOnTime logo" />
<h1 style={{fontFamily: "EB Garamond"}} className="font-semibold text-5xl text-center">Welcome to BoostOnTime</h1>
<p className="text-lg my-4 opacity-75 text-center">Share some info about your vaccination history and we'll help you estimate your COVID immunity.</p>
<button onClick={() => setStage(prev => prev + 1)} className="p-4 bg-black text-white my-8 block w-full shadow-lg">Get started</button>
</div>
) : (
<>
<div className="w-full h-2 bg-gray-300 relative mt-16">
<div className={classNames("h-full absolute left-0 top-0 bg-[#FC3142]", {1: "w-4", 2: "w-1/3", 3: "w-2/3"}[stage])}/>
<img src="/bullet.png" alt="silly goofy bullet point" className="h-12 rotate-90 absolute -top-5" style={{left: (stage - 1) / 3 * 100 + "%"}}/>
</div>
<p className="text-2xl mt-16 mb-8">What brand {q1fill}</p>
<select value={brand} onChange={e => setBrand(e.target.value)} className="p-4 border w-full block shadow-lg">
{["Pfizer", "Moderna", "J&J", ""].map(d => (
<option value={d} key={d}>{d}</option>
))}
</select>
<p className="text-2xl mt-16 mb-8">By when did you receive {q2fill}</p>
<input type="date" value={date} onChange={e => setDate(e.target.value)} min="2019-01-01"
max={format(addDays(new Date(), 1), "yyyy-MM-dd")} className="p-4 border w-full block shadow-lg" />
<button onClick={onNext} className="p-4 bg-black text-white mt-16 block w-full shadow-lg disabled:opacity-50 hover:shadow-xl hover:bg-neutral-900 transition" disabled={isLoading || !date || !brand}>{isLoading ? "loading..." : "Next"}</button>
{stage > 1 && (
<button className="p-4 border border-black mt-4 w-full shadow-lg block hover:bg-gray-100 hover:shadow-xl transition" onClick={() => router.push("/")}>No {{
2: "boosters",
3: "second booster",
}[stage]}</button>
)}
<button onClick={() => setStage(prev => prev + 1)}>DEV SKIP</button>
</>
)}
</div>
</>
)
}

export async function getServerSideProps(context: GetServerSidePropsContext) {
const session = await getSession(context);

if (!session) return { redirect: { permanent: false, destination: "/signin" } };

try {
await mongoose.connect(process.env.MONGODB_URL as string);

let thisUser = await UserModel.findOne({email: session.user.email});

if (!thisUser) thisUser = await createAccount(session.user);

return {props: {thisUser: cleanForJSON(thisUser)}};
} catch (e) {
console.log(e);
return { notFound: true };
}
}
Binary file added public/bullet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
body {
font-family: "Inter", sans-serif;
}

.font-garamond {
font-family: "EB Garamond", serif;
}

0 comments on commit 7d35f06

Please sign in to comment.