Skip to content

Commit

Permalink
words page
Browse files Browse the repository at this point in the history
  • Loading branch information
yisding committed Mar 26, 2023
1 parent 6c60440 commit 344bbaf
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 2 deletions.
21 changes: 21 additions & 0 deletions components/BigRedLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import cx from "classnames";
import Link from "next/link";
import { ReactNode } from "react";

export default function BigRedButton(props: {
children?: ReactNode;
href: string;
className?: string;
}) {
return (
<Link
className={cx(
"text-white bg-panda text-2xl rounded-full p-4",
props.className
)}
href={props.href}
>
{props.children}
</Link>
);
}
32 changes: 32 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"next": "13.2.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-loading-skeleton": "^3.2.0",
"swr": "^2.1.1",
"typescript": "5.0.2"
},
"devDependencies": {
Expand Down
13 changes: 13 additions & 0 deletions pages/api/wordgrade.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next";

type Data = {
grade: string;
};

export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
res.status(200).json({ grade: "K" });
}
21 changes: 21 additions & 0 deletions pages/api/words.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next";

type Data = string[];

export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
res
.status(200)
.json([
"hello",
"world",
"goodbye",
"tomorrow",
"today",
"after",
"before",
]);
}
68 changes: 68 additions & 0 deletions pages/grade.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useRouter } from "next/router";
import useSWR from "swr";

import Skeleton from "react-loading-skeleton";
import "react-loading-skeleton/dist/skeleton.css";

import BigRedLink from "@/components/BigRedLink";

const fetcher = (input: RequestInfo | URL, init?: RequestInit) =>
fetch(input, init).then((res) => res.json());

function WordLevel(props: { word: string; wordGrade: string }) {
return (
<div>
The word {props.word} is at a reading level of grade {props.wordGrade}.
</div>
);
}

function GradePicker(props: { word?: string }) {
let urlPrefix;
if (props.word) {
urlPrefix = `/word?word=${encodeURIComponent(props.word)}&grade=`;
} else {
urlPrefix = "/wordpicker?grade=";
}

return (
<div>
<h1>What grade are you in?</h1>
<div className="grid grid-cols-3 grid-rows-2 gap-4">
<BigRedLink href={`${urlPrefix}K`}>Kindergarten</BigRedLink>
<BigRedLink href={`${urlPrefix}1`}>1st</BigRedLink>
<BigRedLink href={`${urlPrefix}2`}>2nd</BigRedLink>
<BigRedLink href={`${urlPrefix}3`}>3rd</BigRedLink>
<BigRedLink href={`${urlPrefix}4`}>4th</BigRedLink>
<BigRedLink href={`${urlPrefix}5`}>5th</BigRedLink>
</div>
</div>
);
}

export default function Grade() {
const router = useRouter();
const { word, grade } = router.query;

const { data: wordGrade, error: wordGradeError } = useSWR(
typeof word === "string"
? `/api/wordgrade?word=${encodeURIComponent(word)}`
: null,
fetcher
);

if (typeof word !== "string" || wordGradeError) {
return <GradePicker />;
}

if (!wordGrade) {
return <Skeleton />;
}

return (
<div>
<WordLevel word={word} wordGrade={wordGrade} />
<GradePicker />
</div>
);
}
7 changes: 5 additions & 2 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Image from "next/image";

import WordHero from "@/components/WordHero";
import BigRedButton from "@/components/BigRedButton";
import BigRedLink from "@/components/BigRedLink";

export default function Home() {
return (
Expand All @@ -29,7 +30,9 @@ export default function Home() {
alt="red panda sitting"
/>
<div className="flex flex-col justify-between m-4">
<BigRedButton>I want to learn new words</BigRedButton>
<BigRedLink href="/grade">
<span className="font-bold">I want to learn new words</span>
</BigRedLink>
<BigRedButton>
<Image
src="/search.png"
Expand All @@ -38,7 +41,7 @@ export default function Home() {
alt="search"
className="inline"
/>
Search a word to practice
<span className="font-bold">Search for a word</span>
</BigRedButton>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions pages/word.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import WordHero from "@/components/WordHero";
import { useRouter } from "next/router";

export default function Word() {
const router = useRouter();
const { word, grade } = router.query;

return (
<WordHero
word="ocean"
Expand Down
75 changes: 75 additions & 0 deletions pages/wordpicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { useRouter } from "next/router";

import useSWR from "swr";

import Skeleton from "react-loading-skeleton";
import "react-loading-skeleton/dist/skeleton.css";

import BigRedLink from "@/components/BigRedLink";

const fetcher = (input: RequestInfo | URL, init?: RequestInit) =>
fetch(input, init).then((res) => res.json());

export default function WordPicker() {
const router = useRouter();
const { phoneme, characters, grade } = router.query;

const phonemeSpecific =
typeof phoneme === "string" && typeof characters === "string";

const validGrade = typeof grade === "string";

let url;
if (!validGrade) {
url = null;
} else if (phonemeSpecific) {
url = `/api/words?grade=${encodeURIComponent(
grade
)}&phoneme=${encodeURIComponent(phoneme)}&characters=${encodeURIComponent(
characters
)}`;
} else {
url = `/api/words?grade=${encodeURIComponent(grade)}`;
}

const { data: words, error: wordsError } = useSWR(url, fetcher);

if (!validGrade) {
return <div>Error: Need a grade.</div>;
}

if (wordsError) {
return <div>There was an error calling the API.</div>;
}

if (!words) {
return <Skeleton />;
}

if (!Array.isArray(words)) {
return <div>There was an error calling the API.</div>;
}

let heading;

if (phonemeSpecific) {
heading = `Words with ${characters} (${phoneme})`;
} else {
heading = `Grade ${grade} words`;
}

return (
<div>
<h1 className="text-3xl text-panda text-center font-bold">{heading}</h1>
<div className="grid grid-cols-3 grid-rows-2 gap-4">
{words.map((word) => (
<BigRedLink key={word} href={`/word?grade=${grade}&word=${word}`}>
{word}
</BigRedLink>
))}
</div>
</div>
);

return <div></div>;
}
File renamed without changes
1 change: 1 addition & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = {
extend: {
colors: {
panda: "#E49393",
salmon: "#FFC6A6",
},
},
},
Expand Down

0 comments on commit 344bbaf

Please sign in to comment.