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

Load different word lists based on URL #16

Merged
merged 2 commits into from
Apr 19, 2024
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
47 changes: 36 additions & 11 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,55 @@
import React from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import ContentLayout from "./layouts/ContentLayout";
import Card from "./components/Card";
import WordList from "./components/WordList";
import wordList from "./data/teamLindyWordList.json";
import Card from "./components/DynamicCard";
import WordList from "./components/DynamicWordList";
import QRCode from "./components/QRCode";
import flattenWordList from "./lib/flattenWordList";
import {
defaultWordListLoader,
wordListLoader,
} from "./loaders/wordListLoaders";

const App: React.FC = () => {
const flattenedWordList = flattenWordList(wordList);
const rootPath = "/bingo-frontend";

const router = createBrowserRouter([
{
path: "/bingo-frontend",
element: <Card wordList={flattenedWordList} />,
path: rootPath,
loader: defaultWordListLoader,
element: <Card />,
},
{
path: "/",
path: rootPath,
element: <ContentLayout />,
children: [
{
path: "/bingo-frontend/word_list",
element: <WordList wordList={wordList} />,
path: "word_list",
element: <WordList />,
loader: defaultWordListLoader,
},
{
path: "/bingo-frontend/qr_code",
path: "qr_code",
element: <QRCode />,
},
],
},
{
path: `${rootPath}/:wordListName`,
loader: wordListLoader,
element: <Card />,
},
{
path: `${rootPath}/:wordListName`,
loader: wordListLoader,
element: <ContentLayout />,
children: [
{
path: "word_list",
element: <WordList />,
loader: wordListLoader,
},
{
path: "qr_code",
element: <QRCode />,
},
],
Expand Down
2 changes: 1 addition & 1 deletion src/components/CardActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const CardActions: React.FC<{
onClick={shareClick}
activeDuration={1500}
/>
<Link className="QRCodeButton" to="/bingo-frontend/qr_code">
<Link className="QRCodeButton" to="qr_code">
<img src={qrCodeIcon} alt="QR code Icon" />
</Link>
</div>
Expand Down
18 changes: 18 additions & 0 deletions src/components/DynamicCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from "react";
import { useLoaderData } from "react-router-dom";
import Card from "./Card";
import flattenWordList from "../lib/flattenWordList";
import type { WordListData } from "../data/wordList";

const DynamicCard: React.FC = () => {
const wordList = useLoaderData() as WordListData;

if (wordList.length > 0) {
// Card saves the word list to the session, so don't render a card if the
// word list hasn't loaded yet
const words = flattenWordList(wordList);
return <Card wordList={words} />;
}
};

export default DynamicCard;
14 changes: 14 additions & 0 deletions src/components/DynamicWordList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";
import { useLoaderData } from "react-router-dom";
import WordList from "./WordList";
import type { WordListData } from "../data/wordList";

const DynamicWordList: React.FC = () => {
const wordList = useLoaderData() as WordListData;

if (wordList.length > 0) {
return <WordList wordList={wordList} />;
}
};

export default DynamicWordList;
2 changes: 1 addition & 1 deletion src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const Footer: React.FC<{ className?: string }> = ({ className }) => {
<footer className={classNames("Footer", className)}>
<ul>
<li>
<Link to="/bingo-frontend/word_list">Full word list</Link>
<Link to="word_list">Full word list</Link>
</li>
<li>
<a
Expand Down
14 changes: 14 additions & 0 deletions src/data/loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import defaultWordList from "./teamLindyWordList.json";
import type { WordListData } from "./wordList";

export default async (listName: string): Promise<WordListData> => {
let data = defaultWordList;

try {
data = (await import(`./${listName}.json`)).default;
} catch (error) {
console.error("Failed to load the word list", error);
}

return data;
};
97 changes: 97 additions & 0 deletions src/data/numbers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
[
{
"title": "Numbers",
"words": [
{ "word": "1", "description": "Kelly's eye" },
{ "word": "2", "description": "One little duck" },
{ "word": "3", "description": "Cup of tea" },
{ "word": "4", "description": "Knock at the door" },
{ "word": "5", "description": "Man alive" },
{ "word": "6", "description": "Half a dozen" },
{ "word": "7", "description": "Lucky" },
{ "word": "8", "description": "Garden gate" },
{ "word": "9", "description": "Brighton line" },
{ "word": "10", "description": "(Current Prime Minister of the United Kingdom) Rishi's den" },
{ "word": "11", "description": "Legs eleven" },
{ "word": "12", "description": "One dozen" },
{ "word": "13", "description": "Unlucky for some" },
{ "word": "14", "description": "Valentine's Day" },
{ "word": "15", "description": "Young and keen" },
{ "word": "16", "description": "Never been kissed" },
{ "word": "17", "description": "Dancing Queen" },
{ "word": "18", "description": "Coming of age" },
{ "word": "19", "description": "Goodbye, teens" },
{ "word": "20", "description": "score" },
{ "word": "21", "description": "Key of the door" },
{ "word": "22", "description": "Two little ducks" },
{ "word": "23", "description": "The Lord is My Shepherd" },
{ "word": "24", "description": "Two dozen" },
{ "word": "25", "description": "Duck and dive" },
{ "word": "26", "description": "Half a crown" },
{ "word": "27", "description": "Duck and a crutch" },
{ "word": "28", "description": "In a state" },
{ "word": "29", "description": "Rise and shine" },
{ "word": "30", "description": "Dirty Gertie" },
{ "word": "31", "description": "Get up and run" },
{ "word": "32", "description": "Buckle my shoe" },
{ "word": "33", "description": "Dirty knee" },
{ "word": "34", "description": "Ask for more" },
{ "word": "35", "description": "Jump and jive" },
{ "word": "36", "description": "Three dozen" },
{ "word": "37", "description": "More than 11" },
{ "word": "38", "description": "Christmas cake" },
{ "word": "39", "description": "Steps" },
{ "word": "40", "description": "Life begins" },
{ "word": "41", "description": "Time for fun" },
{ "word": "42", "description": "Winnie the Pooh" },
{ "word": "43", "description": "Down on your knees" },
{ "word": "44", "description": "Droopy drawers" },
{ "word": "45", "description": "Halfway there" },
{ "word": "46", "description": "Up to tricks" },
{ "word": "47", "description": "Four and seven" },
{ "word": "48", "description": "Four dozen" },
{ "word": "49", "description": "PC" },
{ "word": "50", "description": "It's a bullseye!" },
{ "word": "51", "description": "Tweak of the thumb" },
{ "word": "52", "description": "Deck of cards" },
{ "word": "53", "description": "Here comes Herbie!" },
{ "word": "54", "description": "Man at the door" },
{ "word": "55", "description": "All the fives" },
{ "word": "56", "description": "Shotts bus" },
{ "word": "57", "description": "Heinz varieties" },
{ "word": "58", "description": "Make them wait" },
{ "word": "59", "description": "Brighton line" },
{ "word": "60", "description": "Grandma's getting frisky" },
{ "word": "61", "description": "Baker's bun" },
{ "word": "62", "description": "Tickety-boo" },
{ "word": "63", "description": "Tickle me" },
{ "word": "64", "description": "Almost retired" },
{ "word": "65", "description": "Retirement age: stop work" },
{ "word": "66", "description": "Clickety click" },
{ "word": "67", "description": "Stairway to Heaven" },
{ "word": "68", "description": "Pick a mate" },
{ "word": "69", "description": "Anyway up" },
{ "word": "70", "description": "Three score and 10" },
{ "word": "71", "description": "Bang on the drum" },
{ "word": "72", "description": "Danny La Rue" },
{ "word": "73", "description": "Queen bee" },
{ "word": "74", "description": "Hit the floor" },
{ "word": "75", "description": "Strive and strive" },
{ "word": "76", "description": "Trombones" },
{ "word": "77", "description": "Two little crutches" },
{ "word": "78", "description": "39 more steps" },
{ "word": "79", "description": "One more time" },
{ "word": "80", "description": "Gandhi's breakfast" },
{ "word": "81", "description": "Fat lady with a walking stick" },
{ "word": "82", "description": "Straight on through" },
{ "word": "83", "description": "Time for tea" },
{ "word": "84", "description": "Give me more" },
{ "word": "85", "description": "Staying alive" },
{ "word": "86", "description": "Between the sticks" },
{ "word": "87", "description": "Torquay in Devon" },
{ "word": "88", "description": "Two fat ladies" },
{ "word": "89", "description": "Nearly there" },
{ "word": "90", "description": "Top of the shop" }
]
}
]
2 changes: 1 addition & 1 deletion src/layouts/ContentLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const ContentLayout: React.FC = () => {
const headerContent = (
<>
<div className="Content-actions">
<Link to="/bingo-frontend">Back</Link>
<Link to=".">Back</Link>
</div>
</>
);
Expand Down
23 changes: 23 additions & 0 deletions src/loaders/wordListLoaders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import defaultWordList from "../data/teamLindyWordList.json";
import loader from "../data/loader";
import type { Params } from "react-router-dom";
import type { WordListData } from "../data/wordList";

export const defaultWordListLoader = (): WordListData => {
return defaultWordList;
};

export const wordListLoader = async ({
params,
}: {
params: Params<string>;
}): Promise<WordListData> => {
if (params.wordListName) {
return await loader(params.wordListName);
} else {
console.error(
"expected a param of 'wordListName' but didn't find one or it had a falsey value",
);
return [];
}
};
Loading