This commit is contained in:
Ruidy Nemausat 2020-08-03 23:18:08 +02:00
parent 44a971ea50
commit 18235f577f
10 changed files with 130 additions and 89 deletions

View file

@ -0,0 +1,64 @@
import React, { FC, useState } from "react";
import { Link as RouterLink } from "react-router-dom";
import {
AppBar,
Link,
Toolbar,
Typography,
InputBase,
} from "@material-ui/core";
import SportsSoccerIcon from "@material-ui/icons/SportsSoccer";
import SearchIcon from "@material-ui/icons/Search";
import { withGame, IGameState } from "../../store/GameProvider";
import useStyles from "./styles";
interface IProps extends IGameState {
title: string;
}
const Header: FC<IProps> = ({ title, filterGamesByText }) => {
const [searchText, setSearchText] = useState("");
const classes = useStyles();
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
): void => setSearchText(e.target.value);
const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {
e.preventDefault();
filterGamesByText(searchText);
};
return (
<div className={classes.root}>
<AppBar position="static" color="transparent">
<Toolbar>
<Typography className={classes.title} variant="h6" noWrap>
<Link component={RouterLink} to="/" color="primary">
<SportsSoccerIcon /> {title}
</Link>
</Typography>
<form className={classes.search} onSubmit={handleSubmit}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
placeholder="Search…"
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
inputProps={{ "aria-label": "search" }}
onChange={handleChange}
value={searchText}
/>
</form>
</Toolbar>
</AppBar>
</div>
);
};
export default withGame((props: IProps) => <Header {...props} />);

View file

@ -1,19 +1,9 @@
import React, { FC } from "react";
import AppBar from "@material-ui/core/AppBar";
import Link from "@material-ui/core/Link";
import Toolbar from "@material-ui/core/Toolbar";
import IconButton from "@material-ui/core/IconButton";
import Typography from "@material-ui/core/Typography";
import InputBase from "@material-ui/core/InputBase";
import { import {
createStyles, createStyles,
fade, fade,
Theme, Theme,
makeStyles, makeStyles,
} from "@material-ui/core/styles"; } from "@material-ui/core/styles";
import SportsSoccerIcon from "@material-ui/icons/SportsSoccer";
import SearchIcon from "@material-ui/icons/Search";
import { Link as RouterLink } from "react-router-dom";
const useStyles = makeStyles((theme: Theme) => const useStyles = makeStyles((theme: Theme) =>
createStyles({ createStyles({
@ -72,35 +62,4 @@ const useStyles = makeStyles((theme: Theme) =>
}) })
); );
const Header: FC<{ title: string }> = ({ title }) => { export default useStyles;
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static" color="transparent">
<Toolbar>
<Typography className={classes.title} variant="h6" noWrap>
<Link component={RouterLink} to="/" color="primary">
<SportsSoccerIcon /> {title}
</Link>
</Typography>
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
placeholder="Search…"
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
inputProps={{ "aria-label": "search" }}
/>
</div>
</Toolbar>
</AppBar>
</div>
);
};
export default Header;

View file

@ -1,14 +1,7 @@
import React, { FC } from "react"; import React, { FC } from "react";
import { makeStyles } from "@material-ui/core/styles";
import CircularProgress from "@material-ui/core/CircularProgress"; import CircularProgress from "@material-ui/core/CircularProgress";
const useStyles = makeStyles({ import useStyles from "./styles";
root: {
position: "absolute",
top: "50vh",
left: "50vw",
},
});
const Loader: FC = () => { const Loader: FC = () => {
const classes = useStyles(); const classes = useStyles();

View file

@ -0,0 +1,11 @@
import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles({
root: {
position: "absolute",
top: "50vh",
left: "50vw",
},
});
export default useStyles;

View file

@ -1,18 +1,9 @@
import React, { FC } from "react"; import React, { FC } from "react";
import Moment from "react-moment"; import Moment from "react-moment";
import { Container, Typography, makeStyles } from "@material-ui/core"; import { Container, Typography } from "@material-ui/core";
import IGame from "../types/Game"; import IGame from "../../types/Game";
import useStyles from "./styles";
const useStyles = makeStyles({
root: {
marginTop: "16px",
marginBottom: "16px",
},
video: {
marginTop: "16px",
},
});
const MatchFull: FC<{ game: IGame }> = ({ game }) => { const MatchFull: FC<{ game: IGame }> = ({ game }) => {
const classes = useStyles(); const classes = useStyles();

View file

@ -0,0 +1,13 @@
import { makeStyles } from "@material-ui/core";
const useStyles = makeStyles({
root: {
marginTop: "16px",
marginBottom: "16px",
},
video: {
marginTop: "16px",
},
});
export default useStyles;

View file

@ -1,26 +1,18 @@
import React, { FC } from "react"; import React, { FC } from "react";
import Moment from "react-moment"; import Moment from "react-moment";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { makeStyles } from "@material-ui/core/styles"; import {
import Card from "@material-ui/core/Card"; Card,
import CardActionArea from "@material-ui/core/CardActionArea"; CardActionArea,
import CardActions from "@material-ui/core/CardActions"; CardActions,
import CardContent from "@material-ui/core/CardContent"; CardContent,
import CardMedia from "@material-ui/core/CardMedia"; CardMedia,
import Button from "@material-ui/core/Button"; Button,
import Typography from "@material-ui/core/Typography"; Typography,
} from "@material-ui/core";
import IGame from "../types/Game"; import IGame from "../../types/Game";
import useStyles from "./styles";
const useStyles = makeStyles({
root: {
maxWidth: 345,
marginTop: "16px",
},
media: {
height: 140,
},
});
const MatchItem: FC<IGame> = ({ const MatchItem: FC<IGame> = ({
title, title,

View file

@ -0,0 +1,13 @@
import { makeStyles } from "@material-ui/core";
const useStyles = makeStyles({
root: {
maxWidth: 345,
marginTop: "16px",
},
media: {
height: 140,
},
});
export default useStyles;

View file

@ -1,10 +1,10 @@
import React, { FC } from "react"; import React, { FC } from "react";
import { Container, Grid } from "@material-ui/core"; import { Container, Grid } from "@material-ui/core";
import { withGame, IGameState } from "../store/GameProvider"; import { withGame, IGameState } from "../../store/GameProvider";
import Loader from "./Loader"; import Loader from "../Loader";
import MatchItem from "./MatchItem"; import MatchItem from "../MatchItem";
const MatchList: FC<IGameState> = ({ games, loading }) => const MatchList: FC<IGameState> = ({ games, loading }) =>
loading ? ( loading ? (
@ -13,7 +13,7 @@ const MatchList: FC<IGameState> = ({ games, loading }) =>
<Container> <Container>
<Grid container justify="center" spacing={3}> <Grid container justify="center" spacing={3}>
{games.map((game, i) => ( {games.map((game, i) => (
<Grid key={i} item xs={3}> <Grid key={i} item sm={6} md={3}>
<MatchItem {...game} id={i} /> <MatchItem {...game} id={i} />
</Grid> </Grid>
))} ))}

View file

@ -9,6 +9,7 @@ export interface IGameState {
loading: boolean; loading: boolean;
setGames: React.Dispatch<React.SetStateAction<IGame[]>>; setGames: React.Dispatch<React.SetStateAction<IGame[]>>;
selectGameByID: (slug: string) => IGame; selectGameByID: (slug: string) => IGame;
filterGamesByText: (text: string) => void;
} }
export const GameContext = createContext<IGameState>({ export const GameContext = createContext<IGameState>({
@ -18,6 +19,7 @@ export const GameContext = createContext<IGameState>({
selectGameByID: () => { selectGameByID: () => {
return {} as IGame; return {} as IGame;
}, },
filterGamesByText: () => {},
}); });
const GameProvider: FC = ({ children }) => { const GameProvider: FC = ({ children }) => {
@ -26,10 +28,12 @@ const GameProvider: FC = ({ children }) => {
const selectGameByID = (slug: string): IGame => { const selectGameByID = (slug: string): IGame => {
const id = parseInt(slug); const id = parseInt(slug);
const game = games[id]; return games[id];
return game;
}; };
const filterGamesByText = (text: string): void =>
setGames(games.filter((g) => g.title.includes(text)));
useEffect(() => { useEffect(() => {
apiClient apiClient
.get("/") .get("/")
@ -39,13 +43,14 @@ const GameProvider: FC = ({ children }) => {
}) })
.catch((err) => { .catch((err) => {
setLoading(false); setLoading(false);
console.error(err);
return <div>{JSON.stringify(err, null, 2)}</div>; return <div>{JSON.stringify(err, null, 2)}</div>;
}); });
}, []); }, []);
return ( return (
<GameContext.Provider value={{ games, loading, setGames, selectGameByID }}> <GameContext.Provider
value={{ games, loading, setGames, selectGameByID, filterGamesByText }}
>
{children} {children}
</GameContext.Provider> </GameContext.Provider>
); );