diff --git a/Client/src/components/Form/Dropdown/Dropdown.tsx b/Client/src/components/Form/Dropdown/Dropdown.tsx index 9b77f48..9d455de 100644 --- a/Client/src/components/Form/Dropdown/Dropdown.tsx +++ b/Client/src/components/Form/Dropdown/Dropdown.tsx @@ -33,12 +33,12 @@ export function Dropdown(props: DropdownProps): React.ReactElement { className="dropdown-root" onChange={handleDropdownChanged} name={props.name} + value={props.value} > {props.options.map((option) => ( diff --git a/Client/src/components/Form/ErrorAlert/ErrorAlert.scss b/Client/src/components/Form/ErrorAlert/ErrorAlert.scss new file mode 100644 index 0000000..138ed5d --- /dev/null +++ b/Client/src/components/Form/ErrorAlert/ErrorAlert.scss @@ -0,0 +1,15 @@ +@import "../../../variables.scss"; + +.error-alert-root { + background-color: $error-color; + color: white; + padding: 10px; + border-radius: 5px; + margin-top: 20px; + margin-bottom: 20px; + text-align: center; +} + +.error-alert-bold { + font-weight: 500; +} diff --git a/Client/src/components/Form/ErrorAlert/ErrorAlert.tsx b/Client/src/components/Form/ErrorAlert/ErrorAlert.tsx new file mode 100644 index 0000000..a0da2ad --- /dev/null +++ b/Client/src/components/Form/ErrorAlert/ErrorAlert.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import "./ErrorAlert.scss"; + +export type ErrorAlertProps = { + message?: string | null; +} + +export function ErrorAlert(props: ErrorAlertProps): React.ReactElement | null { + const ref = React.useRef(null); + + React.useEffect(() => { + ref.current?.focus(); + }, [props.message]) + + if (!props.message) { + return null; + } + + return
+ Error! + {props.message}
+} diff --git a/Client/src/components/Form/ErrorAlert/index.ts b/Client/src/components/Form/ErrorAlert/index.ts new file mode 100644 index 0000000..e561fd8 --- /dev/null +++ b/Client/src/components/Form/ErrorAlert/index.ts @@ -0,0 +1 @@ +export * from './ErrorAlert'; diff --git a/Client/src/hooks/useCareerGame.ts b/Client/src/hooks/useCareerGame.ts index f2b125c..e978645 100644 --- a/Client/src/hooks/useCareerGame.ts +++ b/Client/src/hooks/useCareerGame.ts @@ -19,6 +19,9 @@ export function useCareerGame() { ); if (response.ok && response.data) { + if (response.data.round?.options?.length === 0) + throw new Error("InvalidCareerChoice"); + setGameId(response.data.conversationId) addRound({ ...response.data.round, @@ -26,7 +29,7 @@ export function useCareerGame() { }); } } catch (error: any) { - console.log(error) + throw new Error("FailedToStartGame") } finally { setLoading(false); } diff --git a/Client/src/index.scss b/Client/src/index.scss index 06dfeba..1fba056 100644 --- a/Client/src/index.scss +++ b/Client/src/index.scss @@ -36,6 +36,7 @@ button, input, select, textarea, +.focusable, #main { &:focus { outline: 2px dashed $background-dark; diff --git a/Client/src/screens/GameScreen/GameScreen.tsx b/Client/src/screens/GameScreen/GameScreen.tsx index 7ee7680..66a812b 100644 --- a/Client/src/screens/GameScreen/GameScreen.tsx +++ b/Client/src/screens/GameScreen/GameScreen.tsx @@ -26,11 +26,17 @@ export function GameScreen(): React.ReactElement { } = React.useContext(AppContext); const round = rounds[selectedRound]; + React.useEffect(() => { + if (!isLoading && !gameId) { + navigate("/"); + } + }, [gameId, navigate, isLoading]); + const handlePreviousRoundButtonClicked = () => { selectRound(selectedRound - 1); }; - const handleNextRoundbuttonClicked = () => { + const handleNextRoundButtonClicked = () => { selectRound(selectedRound + 1); }; @@ -86,7 +92,7 @@ export function GameScreen(): React.ReactElement { {isRoundCompleted && ( diff --git a/Client/src/screens/StartScreen/StartScreen.tsx b/Client/src/screens/StartScreen/StartScreen.tsx index 02d3df3..3e28fd6 100644 --- a/Client/src/screens/StartScreen/StartScreen.tsx +++ b/Client/src/screens/StartScreen/StartScreen.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { ErrorAlert } from "../../components/Form/ErrorAlert"; import { useCareerGame } from "../../hooks/useCareerGame"; import { IAppContext } from "../../models/IAppContext"; import { AppContext } from "../../context/AppContext"; @@ -18,10 +19,15 @@ export function StartScreen(): React.ReactElement { React.useContext(AppContext); const [title, setTitle] = React.useState(""); const navigate = useNavigate(); + const [error, setError] = React.useState(null); const handleStartButtonClicked = async (): Promise => { - await startGame(title); - navigate(`/career-game`); + try { + await startGame(title); + navigate(`/career-game`); + } catch { + setError("Please try again with a valid career choice."); + } }; React.useEffect(() => { @@ -38,6 +44,8 @@ export function StartScreen(): React.ReactElement {

Welcome!

What career would you like to explore?

+ +