Skip to content

Commit

Permalink
feat: add instructions (#20)
Browse files Browse the repository at this point in the history
* change stage order and increase button size

* change width for general instructions

* change width for sound check

* fix font size

* fix button font size

* add container for instructions during transition

* add instructions for visual pairs memorize

* add instructions for choice reaction

* add instructions for visual pairs recall

* add instructions for digit symbols

* add instructions for spatial memory

* optimize choice reaction instruction

* add instructions for memory recall

* change figures for visual pairs instructions

* add ending page

* fix text

* disable focus
  • Loading branch information
wenhwang97 authored Oct 17, 2024
1 parent 3cc3357 commit 92a920d
Show file tree
Hide file tree
Showing 19 changed files with 528 additions and 46 deletions.
Binary file added public/assets/click.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions src/components/Ending.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FC, useEffect } from "react";
import { Box, Divider, Typography } from "@mui/material";

export const Ending: FC = () => {
useEffect(() => {
sessionStorage.clear();
}, []);

return (
<>
<Box marginX="auto" position="absolute" top="10%" width="85%" sx={{ transform: "translateX(-50%)" }}>
<Typography variant="h4" textAlign="initial" fontWeight="bold" marginBottom={1}>
Congratulations
</Typography>
<Divider />
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginY={2}>
You have completed the test. Thank you for participating.
</Typography>
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginY={2}>
You may now close the tab.
</Typography>
</Box>
</>
);
};
32 changes: 26 additions & 6 deletions src/components/GeneralDirection.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,40 @@
import { FC, useContext } from "react";
import { Button } from "@mui/material";
import { Box, Button, Divider, Typography } from "@mui/material";
import { GeneralContext, Stage } from "../contexts/general.context";

export const GeneralDirection: FC = () => {
const cxt = useContext(GeneralContext);

const continueButtonHandler = () => {
cxt?.setStage(Stage.SOUND_CHECK);
cxt?.setStage(Stage.TRANSITION);
};

return (
<>
<h2>General Direction Placeholder</h2>
<Button variant="contained" onClick={continueButtonHandler}>
Continue
</Button>
<Box marginX="auto" position="absolute" top="10%" width="85%" sx={{ transform: "translateX(-50%)" }}>
<Typography variant="h4" textAlign="initial" fontWeight="bold" marginBottom={1}>
Directions
</Typography>
<Divider />
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginY={2}>
Please do <strong>NOT</strong> use paper! Solve all questions in your mind. Click "Begin Test" to proceed.
</Typography>
</Box>
<Box
sx={{
position: "fixed",
bottom: 0,
left: 0,
right: 0,
display: "flex",
justifyContent: "center",
p: 1,
}}
>
<Button variant="contained" sx={{ fontSize: 18, padding: 1.5 }} fullWidth onClick={continueButtonHandler}>
Begin Test
</Button>
</Box>
</>
);
};
13 changes: 7 additions & 6 deletions src/components/SoundCheck.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Grid, IconButton, Typography } from "@mui/material";
import { Box, Divider, Grid, IconButton, Typography } from "@mui/material";
import { FC, useContext, useEffect, useState } from "react";
import { soundCheckConfig as uiConfig } from "../config/ui.config";
import { GeneralContext, Stage } from "../contexts/general.context";
Expand Down Expand Up @@ -89,7 +89,7 @@ export const SoundCheck: FC = () => {

if (index === cxt?.soundCheckNumber) {
setTimeout(() => {
cxt?.setStage(Stage.TRANSITION);
cxt?.setStage(Stage.GENERAL_DIRECTION);
}, 2000);
} else {
setTimeout(() => {
Expand Down Expand Up @@ -126,18 +126,19 @@ export const SoundCheck: FC = () => {
};

return (
<Box marginX="auto">
<Box marginX="auto" position="absolute" top="10%" width="85%" sx={{ transform: "translateX(-50%)" }}>
<Typography variant="h4" textAlign="initial" fontWeight="bold" marginBottom={1}>
Sound Check
</Typography>
<Typography variant="body1" fontSize={20} textAlign="initial" width="80vw">
<Divider />
<Typography variant="body1" fontSize={18} textAlign="initial" marginTop={2}>
If you can hear this message, click the announced number.
</Typography>
<Typography variant="body1" fontSize={20} textAlign="initial" width="80vw">
<Typography variant="body1" fontSize={18} textAlign="initial" marginBottom={2}>
Otherwise, please increase your speaks volume.
</Typography>
<OverlayWrapper>
<Grid container direction="column" spacing={1} marginTop={1}>
<Grid container direction="column" spacing={1} marginTop={1} marginX="auto">
{Array.from({ length: 3 }).map((_, rowIndex) => (
<Grid container item spacing={1} key={rowIndex}>
{Array.from({ length: 3 }).map((_, colIndex) => {
Expand Down
43 changes: 37 additions & 6 deletions src/components/Transition.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { FC, useContext } from "react";
import { FC, useContext, useState } from "react";
import { GeneralContext } from "../contexts/general.context";
import { generalConfig as testConfig } from "../config/test.config";
import { ProgressTracker } from "./ProgressTracker";
import { Button } from "@mui/material";
import { Box, Button } from "@mui/material";
import { InstructionContainer, instructionComponents } from "./instructions/InstructionContainer";

interface TransitionProps {
handleTransition: () => void;
Expand All @@ -11,12 +12,42 @@ interface TransitionProps {
export const Transition: FC<TransitionProps> = ({ handleTransition }) => {
const cxt = useContext(GeneralContext);

const [displayInstructions, setDisplayInstructions] = useState<boolean>(false);

return (
<>
<ProgressTracker id={testConfig.testOrder.findIndex((phase) => phase === cxt!.testPhase)} />
<Button variant="contained" onClick={handleTransition}>
Continue
</Button>
{!displayInstructions && (
<Box marginX="auto" position="absolute" top="5%" width="85%" sx={{ transform: "translateX(-50%)" }}>
<ProgressTracker id={testConfig.testOrder.findIndex((phase) => phase === cxt!.testPhase)} />
</Box>
)}
{displayInstructions && <InstructionContainer phase={cxt!.testPhase} handleTransition={handleTransition} />}
<Box
sx={{
position: "fixed",
bottom: 0,
left: 0,
right: 0,
display: "flex",
justifyContent: "center",
p: 1,
}}
>
{instructionComponents[cxt!.testPhase]!.length <= 0 ? (
<Button variant="contained" sx={{ fontSize: 18, padding: 1.5 }} fullWidth onClick={handleTransition}>
Start
</Button>
) : (
<Button
variant="contained"
sx={{ fontSize: 18, padding: 1.5 }}
fullWidth
onClick={() => setDisplayInstructions(true)}
>
Continue
</Button>
)}
</Box>
</>
);
};
72 changes: 72 additions & 0 deletions src/components/instructions/ChoiceReactionTime.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Box, Typography } from "@mui/material";
import { FC } from "react";
import { choiceReactionTimeConfig as uiConfig } from "../../config/ui.config";
import { generalConfig as testConfig } from "../../config/test.config";

const color0 = uiConfig.choiceColor.color0;
const color1 = uiConfig.choiceColor.color1;

interface CRTVisualProps {
symbols: string[];
colors: string[];
}

const CRTVisual: FC<CRTVisualProps> = ({ symbols, colors }) => (
<Box display="flex" flexDirection="column" alignItems="center" marginY={2}>
{symbols.map((symbol, index) => (
<Box
key={index}
width={60}
height={60}
display="flex"
alignItems="center"
justifyContent="center"
border={1}
marginY={1}
sx={{
backgroundColor: colors[index],
}}
>
<Typography variant="h3" fontWeight="bold" color="black">
{symbol}
</Typography>
</Box>
))}
</Box>
);

export const crtInstructions: JSX.Element[] = [
<>
<CRTVisual symbols={[">", "<", ">"]} colors={[color0, color1, color1]} />
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginTop={2}>
Look at the 3 colored squares.
</Typography>
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginBottom={2}>
Two squares are the same color, one is different (ODD-COLOR).
</Typography>
</>,
<>
<CRTVisual symbols={[">", "<", ">"]} colors={[color0, color1, color1]} />
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginTop={2}>
Now look at the ARROW inside the ODD-COLOR.
</Typography>
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginBottom={2}>
When the odd-color arrow points <strong>right</strong>, tap the <strong>RIGHT-ARROW</strong> button at the{" "}
<strong>bottom</strong> of the screen with your <strong>right</strong> hand.
</Typography>
</>,
<>
<CRTVisual symbols={[">", "<", "<"]} colors={[color0, color0, color1]} />
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginY={2}>
When the odd-color arrow points <strong>left</strong>, tap the <strong>LEFT-ARROW</strong> button at the{" "}
<strong>bottom</strong> of the screen with your <strong>left</strong> hand.
</Typography>
</>,
<>
<CRTVisual symbols={[">", "<", "<"]} colors={[color0, color0, color1]} />
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginY={2}>
You will see {Object.keys(testConfig.choiceReactionTimeAns).length} sets of ARROWs. Please response as fast as you
can.
</Typography>
</>,
];
64 changes: 64 additions & 0 deletions src/components/instructions/DigitSymbolMatching.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Divider, Grid, Typography } from "@mui/material";
import { FC } from "react";
import { Cell } from "../tests/DigitSymbolMatchingMain";
import { digitSymbolConfig as testConfig } from "../../config/test.config";
import { generalConfig } from "../../config/test.config";
import { digitSymbolConfig as uiConfig } from "../../config/ui.config";

const DSMVisual: FC = () => (
<Grid container spacing={0} display="flex" justifyContent="center" marginY={2}>
{testConfig.symbolPairs.map((symbol, index) => (
<Grid item key={index}>
<Cell
leftBox={index === 0}
rightBox={index === testConfig.symbolPairs.length - 1}
display="flex"
flexDirection="column"
justifyContent="center"
alignItems="center"
>
<img
src={symbol.image}
style={{
marginLeft: 1,
marginRight: 1,
marginTop: 2,
marginBottom: 2,
height: "8vw",
}}
/>
<Divider sx={{ width: "100%", borderBottom: "1px solid black" }} />
<Typography variant="h3" margin="5px" fontSize={uiConfig.listFontSize}>
{symbol.num}
</Typography>
</Cell>
</Grid>
))}
</Grid>
);

export const dsmInstructions: JSX.Element[] = [
<>
<DSMVisual />
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginY={2}>
Each <strong>symbol</strong> has a <strong>number</strong>.
</Typography>
</>,
<>
<img src={testConfig.symbolPairs[0].image} style={{ marginTop: "1rem", height: "14vw" }} />
<DSMVisual />
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginBottom={2}>
When a symbol appears at the top, press its number on the <strong>number pad</strong> at the{" "}
<strong>bottom</strong> of the screen (here it is 1).
</Typography>
</>,
<>
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginTop={2}>
You will see {Object.keys(generalConfig.digitSymbolAns).length} questions in this test.
</Typography>
<Typography variant="body1" gutterBottom fontSize={18} textAlign="initial" marginBottom={2}>
Your score will be how many correct responeses you make, so try to be <strong>accurate</strong> and{" "}
<strong>quick</strong>!
</Typography>
</>,
];
83 changes: 83 additions & 0 deletions src/components/instructions/InstructionContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { FC, useState } from "react";
import { TestPhase } from "../../contexts/general.context";
import { Box, Button, Divider, Typography } from "@mui/material";
import { vpmInstructions, vprInstructions } from "./VisualPairs";
import { crtInstructions } from "./ChoiceReactionTime";
import { dsmInstructions } from "./DigitSymbolMatching";
import { smInstructions } from "./SpatialMemory";
import { mrdInstructions, mriInstructions } from "./MemoryRecall";

const titleMapping: { [key in TestPhase]?: string } = {
[TestPhase.MEMORY_RECALL_IMMEDIATE]: "Memory - Immediate Recall",
[TestPhase.VISUAL_PAIRS_MEMORIZE]: "Visual Paired Associates - Learn",
[TestPhase.CHOICE_REACTION_TIME]: "Choice Reaction Time",
[TestPhase.VISUAL_PAIRS_RECALL]: "Visual Paired Associates - Test",
[TestPhase.DIGIT_SYMBOL_MATCHING]: "Digit Symbol Matching",
[TestPhase.SPATIAL_MEMORY]: "Spatial Memory",
[TestPhase.MEMORY_RECALL_DELAYED]: "Memory - Delayed Recall",
};

export const instructionComponents: { [key in TestPhase]?: JSX.Element[] } = {
[TestPhase.MEMORY_RECALL_IMMEDIATE]: mriInstructions,
[TestPhase.VISUAL_PAIRS_MEMORIZE]: vpmInstructions,
[TestPhase.CHOICE_REACTION_TIME]: crtInstructions,
[TestPhase.VISUAL_PAIRS_RECALL]: vprInstructions,
[TestPhase.DIGIT_SYMBOL_MATCHING]: dsmInstructions,
[TestPhase.SPATIAL_MEMORY]: smInstructions,
[TestPhase.MEMORY_RECALL_DELAYED]: mrdInstructions,
};

interface InstructionContainerProps {
phase: TestPhase;
handleTransition: () => void;
}

export const InstructionContainer: FC<InstructionContainerProps> = ({ phase, handleTransition }) => {
const [instructionIdx, setInstructionIdx] = useState<number>(0);

return (
<>
<Box marginX="auto" position="absolute" top="10%" width="85%" sx={{ transform: "translateX(-50%)" }}>
<Typography variant="h5" textAlign="initial" fontWeight="bold" marginBottom={1}>
{titleMapping[phase]}
</Typography>
<Divider />
{instructionComponents[phase]![instructionIdx]}
</Box>
<Box
sx={{
position: "fixed",
bottom: 0,
left: 0,
right: 0,
display: "flex",
justifyContent: "center",
p: 1,
zIndex: 100,
}}
>
{instructionIdx + 1 < instructionComponents[phase]!.length ? (
<Button
variant="contained"
color="inherit"
sx={{ fontSize: 18, padding: 1.5 }}
fullWidth
onClick={() => setInstructionIdx((idx) => idx + 1)}
>
Tap here to Continue
</Button>
) : (
<Button
variant="contained"
color="primary"
sx={{ fontSize: 18, padding: 1.5 }}
fullWidth
onClick={handleTransition}
>
Start
</Button>
)}
</Box>
</>
);
};
Loading

0 comments on commit 92a920d

Please sign in to comment.