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 {
createStyles,
fade,
Theme,
makeStyles,
} 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) =>
createStyles({
@ -72,35 +62,4 @@ const useStyles = makeStyles((theme: Theme) =>
})
);
const Header: FC<{ title: string }> = ({ title }) => {
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;
export default useStyles;

View file

@ -1,14 +1,7 @@
import React, { FC } from "react";
import { makeStyles } from "@material-ui/core/styles";
import CircularProgress from "@material-ui/core/CircularProgress";
const useStyles = makeStyles({
root: {
position: "absolute",
top: "50vh",
left: "50vw",
},
});
import useStyles from "./styles";
const Loader: FC = () => {
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 Moment from "react-moment";
import { Container, Typography, makeStyles } from "@material-ui/core";
import { Container, Typography } from "@material-ui/core";
import IGame from "../types/Game";
const useStyles = makeStyles({
root: {
marginTop: "16px",
marginBottom: "16px",
},
video: {
marginTop: "16px",
},
});
import IGame from "../../types/Game";
import useStyles from "./styles";
const MatchFull: FC<{ game: IGame }> = ({ game }) => {
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 Moment from "react-moment";
import { Link } from "react-router-dom";
import { makeStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardActionArea from "@material-ui/core/CardActionArea";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import CardMedia from "@material-ui/core/CardMedia";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
import {
Card,
CardActionArea,
CardActions,
CardContent,
CardMedia,
Button,
Typography,
} from "@material-ui/core";
import IGame from "../types/Game";
const useStyles = makeStyles({
root: {
maxWidth: 345,
marginTop: "16px",
},
media: {
height: 140,
},
});
import IGame from "../../types/Game";
import useStyles from "./styles";
const MatchItem: FC<IGame> = ({
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 { Container, Grid } from "@material-ui/core";
import { withGame, IGameState } from "../store/GameProvider";
import { withGame, IGameState } from "../../store/GameProvider";
import Loader from "./Loader";
import MatchItem from "./MatchItem";
import Loader from "../Loader";
import MatchItem from "../MatchItem";
const MatchList: FC<IGameState> = ({ games, loading }) =>
loading ? (
@ -13,7 +13,7 @@ const MatchList: FC<IGameState> = ({ games, loading }) =>
<Container>
<Grid container justify="center" spacing={3}>
{games.map((game, i) => (
<Grid key={i} item xs={3}>
<Grid key={i} item sm={6} md={3}>
<MatchItem {...game} id={i} />
</Grid>
))}

View file

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