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

Feature/80 add content to choose ninja #96

Merged
merged 7 commits into from
Nov 6, 2019
Merged
Show file tree
Hide file tree
Changes from 10 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
4 changes: 2 additions & 2 deletions src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import Explore from './components/explore';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Task from './components/task/task';
import Summary from './components/summary';
import Task from './components/task';
import Summary from './components/summary/summary';
import Home from './components/home/home';

const App = () => (
Expand Down
5 changes: 3 additions & 2 deletions src/components/explore/explore-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
input: {
outline: '0'
outline: '0',
textAlign: 'center'
}
})
);
Expand Down Expand Up @@ -55,7 +56,7 @@ const ExploreInput = (props: IProps) => {
alt={currentGameCharacter.name}
onAnimationEnd={() => setClassNames('')}
className={className}
/>
/>
</div>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/explore/explore-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const ExploreMenu = (props: IProps) => {
const setCharacterAction = props.setCharacter;

const headerText = 'Välj ninja';
const introText = 'Tryck tabb för att navigera. Välj genom att trycka på enter.';
const introText = 'Tryck pil ned eller upp för att navigera. Välj ninja genom att trycka på enter.';

const audioElementIntro: React.MutableRefObject<HTMLMediaElement | null> = useRef(null);
const menuElement = useRef<HTMLUListElement | null>(null);
Expand Down Expand Up @@ -116,7 +116,7 @@ const ExploreMenu = (props: IProps) => {
<Grid container alignItems="center" justify="center">
<Grid item xs={12} sm={12}>
<Typography variant="h1" align="center" gutterBottom>{headerText}</Typography>
<Typography variant="body2" align="center">{introText}</Typography>
<Typography variant="body1" align="center">{introText}</Typography>
<audio id="intro-audio" ref={audioElementIntro} src="" />
</Grid>
<Grid item xs={12} sm={5}>
Expand Down
17 changes: 10 additions & 7 deletions src/components/explore/explore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const useStyles = makeStyles((theme: Theme) =>
root: {
marginTop: theme.spacing(8),
alignItems: 'center'
},
alignCenter: {
textAlign: 'center'
}
})
);
Expand Down Expand Up @@ -56,8 +59,8 @@ const Explore = props => {
enum KEYROW { ONE, ZERO, MINUS_ONE };

const [timeCount, setTimeCount] = useState(0);
const [headerText, setHeaderText] = useState('Träna din ninja');
const [introText, setIntroText] = useState('Tryck på olika knappar på tangentbordet');
const [headerText, setHeaderText] = useState('Uppvärmning');
const [introText, setIntroText] = useState('Tryck på de olika tangenterna för att träna din ninja inför det första uppdraget. Börja nu!');

const timeForExercise = 60;
const maxInputs = 50;
Expand All @@ -78,7 +81,7 @@ const Explore = props => {

if (timeCount > timeForExercise || explore.typeCount > maxInputs) {
setHeaderText('Redo');
setIntroText(`Bra jobbat! ${currentGameCharacter.name} har nu fått ett gult bälte i karate och är redo för sitt första uppdrag.`);
setIntroText(`Bra jobbat! ${currentGameCharacter.name} har fått ett rött bälte och är redo för sitt första uppdrag, tryck enter för att starta.`);
completedAction();
} else {
interval = setInterval(() => setTimeCount(0), 1000);
Expand Down Expand Up @@ -144,25 +147,25 @@ const Explore = props => {

return (
<div className={classes.root}>
<Grid container alignItems="center" justify="center" spacing={8}>
<Grid container alignItems="center" justify="center" direction="column" spacing={8}>
<Grid item xs={12}>
<Typography variant="h1" align="center">{headerText}</Typography>
<Typography variant="body1" align="center">{introText}</Typography>
<audio id="intro-audio" ref={audioElementIntro} src="" />
</Grid>
<Grid item container xs={12} sm={3} md={3} lg={3} spacing={3} alignItems="center" justify="center">
{!explore.completed ?
<Grid item xs={12}>
<Grid item xs={12} className={classes.alignCenter} >
<ExploreInput handleKey={handleKey} />
</Grid>
:
<>
<Grid item xs={12}>
<Grid item xs={12} className={classes.alignCenter}>
<Button variant="outlined" to="/task" ref={buttonElement} component={Link1}>
Gå till nästa övning
</Button>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.alignCenter}>
<img
src={currentGameCharacter.image}
alt={currentGameCharacter.name}
Expand Down
2 changes: 1 addition & 1 deletion src/components/explore/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import ExploreMenu from './explore-menu';

const Routes = ({ match }) => (
<Switch>
<Route exact path={`${match.url}/play`} component={Explore} />
<Route path={`${match.url}/play`} component={Explore} />
<Route path={`${match.url}`} component={ExploreMenu} />
</Switch>
);
Expand Down
79 changes: 36 additions & 43 deletions src/components/home/home.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { useRef, useEffect } from 'react';
import { Link as RouterLink, LinkProps as RouterLinkProps } from 'react-router-dom';
import { Grid, Typography, Link } from '@material-ui/core';
import React, { useEffect } from 'react';
import { Grid, Typography } from '@material-ui/core';
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
import enterImage from '../../static/images/enter_button.svg';
import whiteImage from '../../static/images/vita_illustrationer.svg';
import logo from '../../static/images/logo.png';
import { IRootState } from '../../shared/reducers';
import { connect } from 'react-redux';
import InstructionLayout from '../../components/layout/InstructionLayout';
import { reset } from '../task/task.reducer';

const useStyles = makeStyles((theme: Theme) =>
createStyles({
Expand Down Expand Up @@ -49,63 +49,56 @@ const useStyles = makeStyles((theme: Theme) =>
})
);

const Link1 = React.forwardRef<HTMLAnchorElement, RouterLinkProps>((props, ref) => (
<RouterLink innerRef={ref} {...props} />
));

const mapStateToProps = (state: IRootState) => ({
gameCharacters: state.game.gameCharacters
const mapStateToProps = ({ game }: IRootState) => ({
gameCharacters: game.gameCharacters
});

const mapDispatchToProps = {
reset
};

type StateProps = ReturnType<typeof mapStateToProps>;
type IDispatchProps = typeof mapDispatchToProps;

export type IProps = StateProps;
export type IProps = StateProps & IDispatchProps;

const Home = (props: IProps) => {
const linkElement = useRef<HTMLAnchorElement | null>(null);
const {
gameCharacters
} = props;
const resetAction = props.reset;

useEffect(() => {
if (linkElement.current) {
linkElement.current.focus();
}
}, []);
resetAction();
}, [resetAction]);

const classes = useStyles();
return (
<Grid container className={classes.root}spacing={2}>
<img src={logo} alt="Logotyp for projektet" className={classes.logo} />
<Grid item xs={10}>
<Typography variant="h1">Välkommen till Typing in the dark</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<Typography variant="body1" align="left">I det här spelet kommer du att få göra olika uppdrag med hjälp av tangentbordet och
du spelar med en ninja. Du kommer få olika uppdrag att klara av och efter varje avklarat uppdrag få olika bälten från vit till svart.
Uppdragen består av allt ifrån att hitta saker i mörka grottor till att göra så många kombos av ninja moves som möjligt.
</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<Typography variant="body1" align="left">Målet är att klara alla uppdrag i spelet och att lära sig att skriva på tangentbordet,
utan att se det. När du har klarat alla uppdrag i spelet får du svart bälte i tangentbord.
</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<Typography variant="body1" align="left">
För att starta spelet tryck Enter, den knappen ligger till höger på tangentbordet format som ett upp och nedvänt L.
</Typography>
</Grid>
<InstructionLayout title="Välkommen till Typing in the dark" to="/explore">
<Grid item xs={12} sm={8}>
<Typography variant="body1" align="left">I det här spelet kommer du att få göra olika uppdrag med hjälp av tangentbordet och
du spelar med en ninja. Du kommer få olika uppdrag att klara av och efter varje avklarat uppdrag få olika bälten från vit till svart.
Uppdragen består av allt ifrån att hitta saker i mörka grottor till att göra så många kombos av ninja moves som möjligt.
</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<Typography variant="body1" align="left">Målet är att klara alla uppdrag i spelet och att lära sig att skriva på tangentbordet,
utan att se det. När du har klarat alla uppdrag i spelet får du svart bälte i tangentbord.
</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<Typography variant="body1" align="left">
För att starta spelet tryck Enter, den knappen ligger till höger på tangentbordet format som ett upp och nedvänt L.
</Typography>
</Grid>
</InstructionLayout>
<Grid item container justify="center" >
<Grid item xs={12} md={2}>
<Grid item xs={12} md={3}>
<img src={gameCharacters[0].image} alt={gameCharacters[0].name} />
</Grid>
<Grid item xs={12} md={2}>
<Link to="/explore" className={classes.link} ref={linkElement} component={Link1}>
<img src={enterImage} alt="Enter starta spelet" />
</Link>
</Grid>
<Grid item xs={12} md={2}>
<Grid item xs={12} md={3}>
<img src={gameCharacters[1].image} alt={gameCharacters[1].name} />
</Grid>
</Grid>
Expand All @@ -114,4 +107,4 @@ const Home = (props: IProps) => {
);
};

export default connect(mapStateToProps)(Home);
export default connect(mapStateToProps, mapDispatchToProps)(Home);
71 changes: 71 additions & 0 deletions src/components/layout/InstructionLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useRef, useEffect } from 'react';
import { Link as RouterLink, LinkProps as RouterLinkProps } from 'react-router-dom';
import { Grid, Typography, Link } from '@material-ui/core';
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
import enterImage from '../../static/images/enter_button.svg';
import { speak } from '../tts/tts';
import { playAudio } from '../audio/audio';

const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
textAlign: 'center'
},
link: {
outline: '0',
'&:focus img': {
borderRadius: 3,
border: '2px solid white'
}
}
})
);

const Link1 = React.forwardRef<HTMLAnchorElement, RouterLinkProps>((props, ref) => (
<RouterLink innerRef={ref} {...props} />
));

export interface IProps {
children: React.ReactNode;
title: string;
to: string;
instructionToSpeak?: string;
}

const InstructionLayout = (props: IProps) => {
const { children, title, to, instructionToSpeak } = props;
const classes = useStyles();
const linkElement = useRef<HTMLAnchorElement | null>(null);
const audioInstructionElement: React.MutableRefObject<HTMLMediaElement | null> = useRef(null);

useEffect(() => {
if (linkElement.current) {
linkElement.current.focus();
}
}, []);

useEffect(() => {
speak(instructionToSpeak).then(url => playAudio(audioInstructionElement, url));
}, [instructionToSpeak]);

return (
<Grid container className={classes.root} spacing={2}>
<Grid item xs={10}>
<Typography variant="h1">{title}</Typography>
</Grid>
<Grid item container xs={12} justify="center" spacing={2}>
{ children }
</Grid>
<Link to={to} className={classes.link} ref={linkElement} component={Link1}>
<img src={enterImage} alt="Enter knapp" />
</Link>
<audio ref={audioInstructionElement} src="" />
</Grid>
);
};

export default InstructionLayout;
11 changes: 0 additions & 11 deletions src/components/summary/index.tsx

This file was deleted.

46 changes: 18 additions & 28 deletions src/components/summary/summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,49 +16,39 @@ const useStyles = makeStyles((theme: Theme) =>
})
);

const mapStateToProps = ({ task }: IRootState) => ({
taskErrors: task.errors
const mapStateToProps = ({ game }: IRootState) => ({
currentGameCharacter: game.gameCharacter
});

type StateProps = ReturnType<typeof mapStateToProps>;

type ISummmaryProps = StateProps;

const Summmary = ({ taskErrors }: ISummmaryProps) => {
const Summmary = ({ currentGameCharacter }: ISummmaryProps) => {
const classes = useStyles();
const [feedbackText, setFeedbackText] = useState('');
const [feedbackText] = useState('Bra jobbat, du har samlat flera verktyg att klara nästa uppdrag.');
const audioElement: React.MutableRefObject<HTMLMediaElement | null> = useRef(null);

useEffect(() => {
// TODO: useEffect runs twice, for some reason...
if (taskErrors > 0) {
speak(`Resultat. Bra jobbat! Du hade bara ${taskErrors} fel.`).then(url => {
playAudio(audioElement, url).then(() => {
playAudio(audioElement, assetBaseUrl + 'done.mp3')
.catch(error => console.error('playAudio error', error));
}).catch(error => console.error('playAudio error', error));
playAudio(audioElement, assetBaseUrl + 'done.mp3').then(() => {
speak(feedbackText).then(url => {
playAudio(audioElement, url).catch(error => console.error('playAudio error', error));
}).catch(error => console.error('speak error', error));

setFeedbackText(`Bra Jobbat! Du hade bara ${taskErrors} fel!`);
} else {
speak('Resultat. Jättebra jobbat! Felfri.').then(url => {
playAudio(audioElement, url).then(() => {
playAudio(audioElement, assetBaseUrl + 'done.mp3')
.catch(error => console.error('playAudio error', error));
}).catch(error => console.error('playAudio error', error));
}).catch(error => console.error('speak error', error));

setFeedbackText('Jättebra jobbat! Felfri!');
}
}, [feedbackText, taskErrors]);
}).catch(error => console.error('play audio error', error));
}, [feedbackText]);

return (
<Grid container justify="center" alignItems="center" className={classes.root}>
<Grid item xs={12}>
<Typography variant="h2">Resultat</Typography>
<Grid container justify="center" direction="column" alignItems="center" spacing={2} className={classes.root}>
<Grid item xs={12} sm={7}>
<Typography variant="h2">Uppdraget klart</Typography>
</Grid>
<Grid item xs={12} sm={7}>
<Typography variant="body1">{feedbackText}</Typography>
<audio id="player" ref={audioElement} src="" autoPlay />
</Grid>
<Grid item xs={12} sm={7}>
<img src={currentGameCharacter.image} alt={currentGameCharacter.name} />
</Grid>
<audio id="player" ref={audioElement} src="" autoPlay />
</Grid>
);
};
Expand Down
Loading