diff --git a/src/App.tsx b/src/App.tsx
index 73ab333..c4d5e0f 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -28,7 +28,7 @@ const App: React.FC = () => {
{
path: "qr_code",
element: ,
- loader: configLoader,
+ loader: defaultConfigLoader,
},
],
},
diff --git a/src/components/Card.test.tsx b/src/components/Card.test.tsx
index 12d4606..b2f8f9c 100644
--- a/src/components/Card.test.tsx
+++ b/src/components/Card.test.tsx
@@ -13,7 +13,7 @@ describe("'New card' button", () => {
test("changes the words on the card", () => {
render(
-
+
,
);
const initialCells = screen.queryAllByRole("gridcell");
@@ -30,7 +30,7 @@ describe("'New card' button", () => {
test("clears any stamped cells", () => {
render(
-
+
,
);
const cells = screen.queryAllByRole("gridcell");
@@ -49,7 +49,7 @@ describe("'Clear' button", () => {
test("clears any stamped cells", () => {
render(
-
+
,
);
const cells = screen.queryAllByRole("gridcell");
@@ -74,7 +74,7 @@ describe("'Share' button", () => {
const user = userEvent.setup();
render(
-
+
,
);
diff --git a/src/components/Card.tsx b/src/components/Card.tsx
index f53c43d..7f23847 100644
--- a/src/components/Card.tsx
+++ b/src/components/Card.tsx
@@ -8,13 +8,16 @@ import share from "../lib/share";
import type { CellProps } from "./Cell";
import type { ButtonClickHandler } from "../clickHandler";
-const Card: React.FC<{ name: string; url: string; wordList: string[] }> = ({
- name,
- url,
- wordList,
-}) => {
- const [cellDataList, toggleStamped, setNewWords, clearAllCells] =
- useCard(wordList);
+const Card: React.FC<{
+ id: string;
+ name: string;
+ url: string;
+ wordList: string[];
+}> = ({ id, name, url, wordList }) => {
+ const [cellDataList, toggleStamped, setNewWords, clearAllCells] = useCard(
+ id,
+ wordList,
+ );
const cellPropsList: CellProps[] = cellDataList.map((cellData, index) => ({
...cellData,
diff --git a/src/components/DynamicCard.tsx b/src/components/DynamicCard.tsx
index 0179201..b01d1d5 100644
--- a/src/components/DynamicCard.tsx
+++ b/src/components/DynamicCard.tsx
@@ -2,16 +2,16 @@ import React from "react";
import { useLoaderData } from "react-router-dom";
import Card from "./Card";
import flattenWordList from "../lib/flattenWordList";
-import type { Config } from "../data/config";
+import type { KeyedConfig } from "../loaders/configLoaders";
const DynamicCard: React.FC = () => {
- const { name = "", url, wordList } = useLoaderData() as Config;
+ const { id, name = "", url, wordList } = useLoaderData() as KeyedConfig;
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 ;
+ return ;
}
};
diff --git a/src/hooks/useCard.ts b/src/hooks/useCard.ts
index 1981900..70d1fc5 100644
--- a/src/hooks/useCard.ts
+++ b/src/hooks/useCard.ts
@@ -10,7 +10,7 @@ type GetterSetters = [
ButtonClickHandler,
];
-const useCard = (wordList: string[]): GetterSetters => {
+const useCard = (id: string, wordList: string[]): GetterSetters => {
const newWords = (): string[] => shuffle(wordList).slice(0, 25);
const newCellDataList = function (): CellData[] {
@@ -19,8 +19,10 @@ const useCard = (wordList: string[]): GetterSetters => {
});
};
- const [cellDataList, setCellDataList] =
- useSession(newCellDataList);
+ const [cellDataList, setCellDataList] = useSession({
+ keyName: `bingoSession-${id}`,
+ initFunction: newCellDataList,
+ });
const setStamped = (index: number, stamped: boolean): void => {
setCellDataList(
diff --git a/src/hooks/useSession.ts b/src/hooks/useSession.ts
index 6cea5fb..1f458f4 100644
--- a/src/hooks/useSession.ts
+++ b/src/hooks/useSession.ts
@@ -3,10 +3,16 @@ import GuaranteedJsonSession from "../lib/GuaranteedJsonSession";
type GetterSetter = [T, (data: T) => void];
-const useSession = function (initialData: () => T): GetterSetter {
+const useSession = function ({
+ keyName,
+ initFunction,
+}: {
+ keyName: string;
+ initFunction: () => T;
+}): GetterSetter {
const session = useMemo(
- () => new GuaranteedJsonSession(initialData),
- [initialData],
+ () => new GuaranteedJsonSession({ keyName, initFunction }),
+ [initFunction],
);
const [data, setData] = useState(session.sessionData);
diff --git a/src/lib/GuaranteedJsonSession.test.ts b/src/lib/GuaranteedJsonSession.test.ts
index 9df2206..00a056a 100644
--- a/src/lib/GuaranteedJsonSession.test.ts
+++ b/src/lib/GuaranteedJsonSession.test.ts
@@ -7,7 +7,10 @@ beforeEach(() => {
test("can store an array of cell data in the session", () => {
const initFunction = () => [];
- const session = new GuaranteedJsonSession(initFunction);
+ const session = new GuaranteedJsonSession({
+ keyName: "key",
+ initFunction,
+ });
session.sessionData = [
{ word: "Aardvark", stamped: false },
@@ -22,7 +25,10 @@ test("can store an array of cell data in the session", () => {
test("returns a new array if nothing is stored", () => {
const initFunction = () => [{ word: "Camel", stamped: false }];
- const session = new GuaranteedJsonSession(initFunction);
+ const session = new GuaranteedJsonSession({
+ keyName: "key",
+ initFunction,
+ });
expect(session.sessionData).toEqual([{ word: "Camel", stamped: false }]);
});
diff --git a/src/lib/GuaranteedJsonSession.ts b/src/lib/GuaranteedJsonSession.ts
index c691d3f..0dd3e76 100644
--- a/src/lib/GuaranteedJsonSession.ts
+++ b/src/lib/GuaranteedJsonSession.ts
@@ -7,8 +7,14 @@ class GuaranteedJsonSession {
#session: JsonSession;
#initFunction: () => T;
- constructor(initFunction: () => T) {
- this.#session = new JsonSession();
+ constructor({
+ keyName,
+ initFunction,
+ }: {
+ keyName: string;
+ initFunction: () => T;
+ }) {
+ this.#session = new JsonSession(keyName);
this.#initFunction = initFunction;
}
diff --git a/src/lib/JsonDataImporter.ts b/src/lib/JsonDataImporter.ts
deleted file mode 100644
index 50a3d7f..0000000
--- a/src/lib/JsonDataImporter.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export default class JsonDataImporter {
- #defaultData: T;
-
- constructor({ defaultData }: { defaultData: T }) {
- this.#defaultData = defaultData;
- }
-
- async import(listName: string): Promise {
- let data = this.#defaultData;
-
- try {
- data = (await import(`../data/${listName}.json`)).default;
- } catch (error) {
- console.error("Failed to load the data", error);
- }
-
- return data;
- }
-}
diff --git a/src/lib/JsonSession.test.ts b/src/lib/JsonSession.test.ts
index 246ce1a..04588b1 100644
--- a/src/lib/JsonSession.test.ts
+++ b/src/lib/JsonSession.test.ts
@@ -6,7 +6,7 @@ beforeEach(() => {
});
test("can store an array of cell data in the session", () => {
- const session = new JsonSession();
+ const session = new JsonSession("key");
session.sessionData = [
{ word: "Aardvark", stamped: false },
@@ -20,7 +20,7 @@ test("can store an array of cell data in the session", () => {
});
test("returns null if nothing is stored", () => {
- const session = new JsonSession();
+ const session = new JsonSession("Key");
expect(session.sessionData).toEqual(null);
});
diff --git a/src/lib/JsonSession.ts b/src/lib/JsonSession.ts
index 555ee80..f02ec72 100644
--- a/src/lib/JsonSession.ts
+++ b/src/lib/JsonSession.ts
@@ -1,6 +1,10 @@
class JsonSession {
#store = window.localStorage;
- #keyName = "sessionData";
+ #keyName: string;
+
+ constructor(keyName: string) {
+ this.#keyName = keyName;
+ }
get sessionData(): T | null {
const sessionDataString: string | null = this.#store.getItem(this.#keyName);
diff --git a/src/lib/importJsonData.ts b/src/lib/importJsonData.ts
new file mode 100644
index 0000000..35f5d8a
--- /dev/null
+++ b/src/lib/importJsonData.ts
@@ -0,0 +1,21 @@
+type EmptyObject = Record;
+type Result =
+ | { success: true; data: T }
+ | { success: false; data: EmptyObject };
+
+const importJsonData = async (listName: string): Promise> => {
+ try {
+ return {
+ success: true,
+ data: (await import(`../data/${listName}.json`)).default,
+ };
+ } catch (error) {
+ return {
+ success: false,
+ data: {},
+ };
+ console.error("Failed to load the data", error);
+ }
+};
+
+export default importJsonData;
diff --git a/src/loaders/configLoaders.ts b/src/loaders/configLoaders.ts
index f2a4af9..815a4e6 100644
--- a/src/loaders/configLoaders.ts
+++ b/src/loaders/configLoaders.ts
@@ -1,25 +1,34 @@
import defaultConfig from "../data/teamLindy.json";
import nullConfig from "../data/teamLindy.json";
-import JsonDataImporter from "../lib/JsonDataImporter";
+import importJsonData from "../lib/importJsonData";
import type { Params } from "react-router-dom";
import type { Config } from "../data/config";
-export const defaultConfigLoader = (): Config => {
- return defaultConfig;
+export type KeyedConfig = { id: string } & Config;
+
+const defaultKeyedConfig: KeyedConfig = { id: "teamLindy", ...defaultConfig };
+
+export const defaultConfigLoader = (): KeyedConfig => {
+ return defaultKeyedConfig;
};
export const configLoader = async ({
params,
}: {
params: Params;
-}): Promise => {
- if (params.gameName) {
- const importer = new JsonDataImporter({ defaultData: defaultConfig });
- return await importer.import(params.gameName);
+}): Promise => {
+ const id = params.gameName;
+ if (id) {
+ const { success, data } = await importJsonData(id);
+ if (success) {
+ return { id, ...data };
+ } else {
+ return defaultKeyedConfig;
+ }
} else {
console.error(
"expected a param of 'gameName' but didn't find one or it had a falsey value",
);
- return nullConfig;
+ return { id: "null", ...nullConfig };
}
};