Skip to content
Open
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
2 changes: 1 addition & 1 deletion .typesafe-i18n.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"adapter": "react",
"esmImports": true,
"$schema": "https://unpkg.com/typesafe-i18n@5.24.3/schema/typesafe-i18n.json"
"$schema": "https://unpkg.com/typesafe-i18n@5.26.2/schema/typesafe-i18n.json"
}
12,304 changes: 12,304 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

51 changes: 30 additions & 21 deletions src/GameStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { immer } from "zustand/middleware/immer";
*/

interface Actions {
setStartingArticle: (article: Article) => void;
setEndingArticle: (article: Article) => void;
setArticles: (articles: Article[]) => void;
setTargetArticle: (index: number) => void;
setIsGameRunning: (flag: boolean) => void;
addHistoryArticle: (article: ArticleHistory) => void;
resetStoreState: () => void;
Expand All @@ -31,8 +31,8 @@ export interface Article {
interface GameStore {
actions: Actions;
history: ArticleHistory[];
startingArticle: Article;
endingArticle: Article;
articles: Article[];
targetArticle: number;
isGameRunning: boolean;
cheatingAttempts: number;
}
Expand All @@ -48,24 +48,24 @@ const useGameStore = create<GameStore>()(
querystring(
immer((set) => ({
...initialState,
startingArticle: { pageid: "", title: "" },
endingArticle: { pageid: "", title: "" },
articles: [{ pageid: "", title: "" },{ pageid: "", title: "" }],
targetArticle: 1,
actions: {
setStartingArticle: (article: Article) =>
setArticles: (articles: Article[]) =>
set(
() => ({
startingArticle: article,
}),
(state) => {
state.articles = articles;
},
false,
"setStartingArticle"
"setArticles"
),
setEndingArticle: (article: Article) =>
setTargetArticle: (index: number) =>
set(
() => ({
endingArticle: article,
}),
(state) => {
state.targetArticle = index;
},
false,
"setEndingArticle"
"setTargetArticle"
),
setIsGameRunning: (flag: boolean) =>
set(
Expand Down Expand Up @@ -113,8 +113,8 @@ const useGameStore = create<GameStore>()(

return {
history: isWikiPage,
startingArticle: true,
endingArticle: true,
articles: true,
targetArticle: isWikiPage,
isGameRunning: false,
cheatingAttempts: isWikiPage,
};
Expand All @@ -129,16 +129,25 @@ const useGameStore = create<GameStore>()(

export const useGameStoreActions = () => useGameStore((state) => state.actions);
export const useIsGameRunning = () => useGameStore((state) => state.isGameRunning);
export const useStartingArticle = () => useGameStore((state) => state.startingArticle);
export const useEndingArticle = () => useGameStore((state) => state.endingArticle);
export const useArticles = () => useGameStore((state) => state.articles);
export const useTargetArticle = () => useGameStore((state) => state.targetArticle);
export const useHistory = () => useGameStore((state) => state.history);
export const useClicks = () =>
useGameStore((state) => (state.history.length > 1 ? state.history.length - 1 : 0));
export const useCurrentArticle = () => useGameStore((state) => state.history.slice(-1)?.[0]?.title);
export const useIsWin = () =>
useGameStore((state) => {
const currentArticle = state.history.slice(-1)?.[0]?.title;
return state.endingArticle.title === currentArticle;
if (state.articles[state.targetArticle]?.title === currentArticle){
if (state.articles.length === state.targetArticle + 1) {
return true;
}
else {
state.actions.setTargetArticle(state.targetArticle + 1);
return false;
}
}
return false;
});

export const useCheatingAttempts = () => useGameStore((state) => state.cheatingAttempts);
21 changes: 21 additions & 0 deletions src/components/ArticleAdd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useGameStoreActions, useArticles } from "../GameStore";
import { useI18nContext } from "../i18n/i18n-react";

export default function ArticleAdd() {
const { setArticles } = useGameStoreActions();
const { LL } = useI18nContext();
const articles = useArticles();

const addArticle = () => {
setArticles([...articles, { pageid: "", title: "" }]);
};

return (
<button className="border max-w-fit rounded hover:border-primary-blue" onClick={addArticle} type="button">
<span className="p-1 w-full flex justify-between">
<p>{LL.ADD_ARTICLE()}</p>
<p className="px-2">+</p>
</span>
</button>
);
}
5 changes: 3 additions & 2 deletions src/components/ArticleAutocomplete/ArticleAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface ArticleAutocompleteProps {
onSelect: (option: Article) => void;
defaultValue: string;
selectId: string;
className?: string;
}

interface AutocompleteOption {
Expand All @@ -40,7 +41,7 @@ interface AutocompleteOption {
}

const ArticleAutocomplete = (props: ArticleAutocompleteProps) => {
const { label, placeholder, required, onSelect, defaultValue, selectId } = props;
const { label, placeholder, required, onSelect, defaultValue, selectId, className } = props;
const language = useWikiLanguage();
const { LL } = useI18nContext();
const [inputText, setInputText] = useState("");
Expand Down Expand Up @@ -84,7 +85,7 @@ const ArticleAutocomplete = (props: ArticleAutocompleteProps) => {
};

return (
<div className="flex flex-1 flex-col min-w-0">
<div className={`flex flex-1 flex-col min-w-0 ${className}`}>
<label htmlFor={selectId}>{label}</label>
<Select
key={defaultValue} // dirty hack
Expand Down
21 changes: 21 additions & 0 deletions src/components/ArticleRemove.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useGameStoreActions, useArticles } from "../GameStore";

interface ArticleRemoveProps {
index: number;
}

export default function ArticleRemove(props: ArticleRemoveProps) {
const { setArticles } = useGameStoreActions();
const articles = useArticles();
const { index } = props;

const removeArticle = (index: number) => {
return () => {
const newArticles = [...articles];
newArticles.splice(index, 1);
setArticles(newArticles);
};
};

return <button onClick={removeArticle(index)} className="p-2 hover:text-primary-blue" type="button">✕</button>
}
5 changes: 2 additions & 3 deletions src/components/InterfaceLanguageSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@ export const InterfaceLanguageSelect = () => {
const { LL, setLocale } = useI18nContext();
const language = useInterfaceLanguage();
const { setInterfaceLanguage, setWikiLanguage } = useSettingsStoreActions();
const { setEndingArticle, setStartingArticle } = useGameStoreActions();
const { setArticles } = useGameStoreActions();

return (
<Select.Root
value={language}
onValueChange={async (locale: Locales) => {
await loadLocaleAsync(locale);
setInterfaceLanguage(locale);
setStartingArticle({pageid: "", title: ""});
setEndingArticle({pageid: "", title: ""});
setArticles([{pageid: "", title: ""}, {pageid: "", title: ""}]);
setWikiLanguage(LANGUAGES.filter((language) => language.isoCode === locale)[0].value);
setLocale(locale);
}}
Expand Down
16 changes: 11 additions & 5 deletions src/components/ResultDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import * as Dialog from "@radix-ui/react-dialog";
import {
useCheatingAttempts,
useClicks,
useEndingArticle,
useArticles,
useHistory,
useIsWin,
useStartingArticle,
} from "../GameStore";

import { StopwatchDisplay } from "./StopwatchDisplay";
Expand All @@ -31,8 +30,7 @@ export const ResultDialog = () => {
const [open, setOpen] = useState(false);
const resetGame = useResetGame();

const startingArticle = useStartingArticle();
const endingArticle = useEndingArticle();
const articles = useArticles();
const history = useHistory();
const [lastArticle] = history.slice(-1);
const clicks = useClicks();
Expand Down Expand Up @@ -67,7 +65,15 @@ export const ResultDialog = () => {
</ModalTitle>
<ModalDescription asChild>
<p className="mb-5 mt-[10px] text-lg font-bold ">
{startingArticle.title} → {endingArticle.title}
{
articles.map((article, index) => {
return (
<span>
{article.title}{index != articles.length - 1 && " → "}
</span>
);
}
)}
</p>
</ModalDescription>
<table className="mb-5 w-full table-auto">
Expand Down
Loading