<repo_name>heydrigh/TGL-react<file_sep>/src/store/modules/lotterys/actions/actionTypes.js
export const FETCH_LOTTERY = 'FETCH_LOTTERY';
export const FETCH_LOTTERY_START = 'FETCH_LOTTERY_START';
export const FETCH_LOTTERY_SUCCESS = 'FETCH_LOTTERY_SUCCESS';
export const FETCH_LOTTERY_FAIL = 'FETCH_LOTTERY_FAIL';
<file_sep>/src/pages/Account/index.jsx
import React, { useEffect } from 'react';
import * as S from './styles';
import { AiOutlineArrowRight, AiOutlineArrowLeft } from 'react-icons/ai';
import { useSelector } from 'react-redux';
import { useHistory, Link } from 'react-router-dom';
import { useForm } from 'react-hook-form';
import { toast } from 'react-toastify';
import api from '../../services/api';

const Account = () => {
  const { register, handleSubmit } = useForm();
  const history = useHistory();
  const auth = useSelector((state) => {
    return {
      isAuth: state.auth.isAuth,
      user: state.auth.user
    };
  });

  useEffect(() => {
    if (!auth.isAuth) {
      history.push('/');
    }
  }, [auth.isAuth, history]);

  const onSubmit = async (data) => {
    try {
      const response = await api.put('/users', data);
      console.log(response);
      toast.success('Suas alterações foram salvas');
      history.push('/dashboard');
    } catch (err) {
      console.log(err);
      toast.error('Falha em modificar seus dados, tente novamente mais tarde');
    }
  };

  return (
    <S.Wrapper>
      <S.Header>Account</S.Header>
      <S.Card onSubmit={handleSubmit(onSubmit)}>
        <S.InputsWrapper>
          <label>Nome</label>
          <input
            name="username"
            ref={register({ required: true })}
            type="text"
            placeholder={auth.user.username}
          />

          <label>Email</label>
          <input
            name="email"
            type="email"
            placeholder={auth.user.email}
            disabled
          />

          <label>Senha</label>
          <input
            name="password"
            ref={register({ required: true })}
            type="password"
          />

          <label>Confirmação de senha</label>
          <input
            name="password_confirmation"
            ref={register({ required: true })}
            type="password"
          />
        </S.InputsWrapper>

        <S.SubmitButton type="submit">
          Modify <AiOutlineArrowRight size={30} />
        </S.SubmitButton>
      </S.Card>

      <S.LastButton>
        <Link to="/dashboard">
          <AiOutlineArrowLeft size={30} />
          Back
        </Link>
      </S.LastButton>
    </S.Wrapper>
  );
};

export default Account;
<file_sep>/src/store/modules/lotterys/actions/index.js
export {
  fecthLottery,
  fetchLotterySuccess,
  fetchLotteryFail,
  fetchLotteryStart
} from './actions';
<file_sep>/src/pages/NewGame/index.jsx
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import * as S from './styles';
import Menu from '../../components/Menu';
import LotteryButton from '../../components/LotteryButton';
import Ball from '../../components/Ball';
import Cart from '../../components/Cart';
import * as lotteryActions from '../../store/modules/lotterys/actions/actions';
import * as betsActions from '../../store/modules/bets/actions/actions';
import Spinner from '../../components/Spinner';
import uuid from 'react-uuid';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { FiShoppingCart } from 'react-icons/fi';
import { useHistory } from 'react-router-dom';

const NewGame = (props) => {
  const [selectableNumbers, setSelectableNumbers] = useState([]);
  const [isActive, setIsActive] = useState([]);
  const [chosenGame, setChosenGame] = useState('');
  const [rules, setRules] = useState({});
  const [cartsGames, setCartGames] = useState([]);
  const [selectedNumbers, setSelectedNumbers] = useState([]);
  const [instruction, setInstruction] = useState(
    'Escolha um jogo para começar!'
  );
  const history = useHistory();

  useEffect(() => {
    props.onFecthLottery();

    if (!props.auth.isAuth) {
      history.push('/');
    }
  }, []);

  const handleSelectedGame = (gameRange, gameInstruction, gameName) => {
    let numbers = [];
    let gameInfos = [];
    for (let i = 1; i <= gameRange; i++) {
      numbers.push(i);
    }
    setSelectableNumbers(numbers);
    handleInstructions(gameInstruction);
    Object.values(props.types).map((name) => {
      gameInfos.push(name.type);
    });

    setChosenGame(gameName);

    let filteredGame = Object.values(props.types).filter((game) => {
      return game.type === gameName;
    });

    setRules(filteredGame[0]);
    console.log(props.types);
  };

  const handleInstructions = (gameInstructions) => {
    setInstruction(gameInstructions);
  };

  const handleBallClick = (number) => {
    const numbers = [...selectedNumbers];
    const actives = isActive;
    numbers.push(number);
    setSelectedNumbers(numbers);
    actives[number - 1] = !actives[number - 1];
    setIsActive(actives);
  };

  const completeGameHandler = () => {
    let numbers = [];
    let selected = selectedNumbers;

    const actives = isActive;
    for (let i = 1; i <= rules.range; i++) {
      numbers.push(i);
    }

    if (!chosenGame) {
      toast.error('Escolha um jogo');
      return;
    }
    if (selectedNumbers.length === rules.max_number) {
      toast.error('Número maximo de números ja escolhido');
    } else {
      while (selected.length < rules.max_number) {
        const filteredNumbers = numbers.filter((item) => {
          return !selected.includes(item);
        });
        let randomNumber =
          filteredNumbers[Math.floor(Math.random() * filteredNumbers.length)];
        selected.push(randomNumber);
        actives[randomNumber - 1] = !actives[randomNumber - 1];
        setIsActive(actives);
      }
      setSelectedNumbers([...selected]);
    }
  };

  const handleRemoveBet = (betId) => {
    setCartGames(cartsGames.filter((bet) => bet.id !== betId));
  };

  const addToCartHandler = () => {
    if (selectedNumbers.length === rules.max_number) {
      const gameDone = {
        ...rules,
        selectedNumbers,
        game_id: uuid()
      };
      gameDone.selectedNumbers.sort();
      setCartGames([...cartsGames, gameDone]);
      clearGameHandler();
      toastSuccess('Jogo adicionado ao carrinho com sucesso!');
      console.log(gameDone);
    } else {
      toastWarn(rules.max_number);
    }
  };

  const clearGameHandler = () => {
    const numbers = [];
    setSelectedNumbers([]);
    for (let i = 0; i < 80; i++) {
      numbers.push(false);
    }
    setIsActive(numbers);
  };

  const toastWarn = (maxNumber) => {
    toast.warn(`Por favor, escolha ${maxNumber} números para seu jogo`, {
      position: 'top-right',
      autoClose: 5000,
      hideProgressBar: false,
      closeOnClick: true,
      pauseOnHover: true,
      draggable: true,
      progress: undefined
    });
  };

  const toastSuccess = (message) => {
    toast.info(message, {
      position: 'top-right',
      autoClose: 5000,
      hideProgressBar: false,
      closeOnClick: true,
      pauseOnHover: true,
      draggable: true,
      progress: undefined
    });
  };

  return (
    <>
      <Menu
        homeText="Home"
        homeLink="/dashboard"
        accountText="Account"
        accountLink="/account"
        logOutText="Logout"
      />
      <S.Wrapper>
        <S.GamesWrapper>
          <S.GameHeader>
            <S.NewBet>New bet</S.NewBet>
            {chosenGame.length < 1 ? (
              <S.GameName>Click a game to begin</S.GameName>
            ) : (
              <S.GameName>For {chosenGame}</S.GameName>
            )}
          </S.GameHeader>
          <S.ChoiceWrapper>
            <S.ChoiceHeader>Choose a game</S.ChoiceHeader>
            {props.loading ? (
              <Spinner />
            ) : (
              <S.ChoicesButtons>
                {props.types &&
                  Object.values(props.types).map((lotteryButton) => (
                    <LotteryButton
                      clicked={() =>
                        handleSelectedGame(
                          lotteryButton.range,
                          lotteryButton.description,
                          lotteryButton.type
                        )
                      }
                      key={lotteryButton.type}
                      lotteryName={lotteryButton.type}
                      color={lotteryButton.color}
                      active={lotteryButton.type === chosenGame}
                    />
                  ))}
              </S.ChoicesButtons>
            )}
          </S.ChoiceWrapper>
          <S.InstructionsWrapper>
            <S.InstructionsHeader>Fill your bet</S.InstructionsHeader>
            <S.Instructions>{instruction}</S.Instructions>
          </S.InstructionsWrapper>
          <S.NumbersWrapper>
            {selectableNumbers &&
              selectableNumbers.map((number) => (
                <Ball
                  isActive={isActive[number - 1]}
                  disabled={isActive[number - 1]}
                  clicked={() => handleBallClick(number)}
                  number={number}
                  key={number}
                  color={rules.color}
                />
              ))}
          </S.NumbersWrapper>
          <S.ControlsWrapper>
            <S.CompleteAndClear>
              <button onClick={completeGameHandler}>Complete Game</button>
              <button onClick={clearGameHandler}>Clear Game</button>
            </S.CompleteAndClear>
            <S.CartControl>
              <button onClick={addToCartHandler}>
                <FiShoppingCart size={24} />
                Add to cart
              </button>
            </S.CartControl>
          </S.ControlsWrapper>
        </S.GamesWrapper>
        <Cart bets={cartsGames} deleted={handleRemoveBet} />
      </S.Wrapper>
    </>
  );
};

const mapStateToProps = (state) => {
  return {
    types: state.types.lottery[0],
    loading: state.types.loading,
    auth: state.auth
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    onFecthLottery: () => dispatch(lotteryActions.fecthLottery()),
    onSaveBet: (bets) => dispatch(betsActions.saveBetSuccess(bets))
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(NewGame);
<file_sep>/src/store/modules/bets/sagas/sagas.js
import api from '../../../../services/api';
import { put } from 'redux-saga/effects';
import * as actions from '../actions/actions';

export function* fetchBetsSaga(action) {
  yield put(actions.fetchBetStart());

  try {
    const response = yield api.get('/games');

    const fetchedGames = [];
    fetchedGames.push({
      ...response.data
    });
    yield put(actions.fetchBetSuccess(fetchedGames));
  } catch (error) {
    yield put(actions.fetchBetFail(error));
  }
}
<file_sep>/src/components/Cart/index.jsx
import React from 'react';
import * as S from './styles';
import { useHistory } from 'react-router-dom';
import { toast } from 'react-toastify';
import { BsTrash, BsArrowRight } from 'react-icons/bs';
import api from '../../services/api';

const Cart = ({ bets, deleted }) => {
  const totalPrice = bets.reduce((acc, bets) => acc + bets.price, 0);
  const history = useHistory();

  const handleSavedButton = async () => {
    let game_array = [];
    if (bets.length > 0) {
      bets.map((bet) => {
        const game = {
          type_id: bet.id,
          numbers: bet.selectedNumbers.join(',')
        };
        game_array.push(game);
      });
      try {
        const response = await api.post('/games', game_array);
        toast.success('Seu jogos foras salvos com sucesso!');
        console.log(response);
        history.push('/dashboard');
      } catch (err) {
        console.log(err);
        toast.error(
          'Ocorreu um erro ao realizar esta ação, tente novamente mais tarde.'
        );
      }
    } else {
      toastWarn('Seu carrinho está vazio. Por favor faça ao menos uma aposta.');
    }
  };

  const toastWarn = (message) => {
    toast.warn(message, {
      position: 'top-right',
      autoClose: 5000,
      hideProgressBar: false,
      closeOnClick: true,
      pauseOnHover: true,
      draggable: true,
      progress: undefined
    });
  };

  return (
    <>
      <S.Wrapper>
        <S.Cart>
          <S.Header>CART</S.Header>
          <S.BetsWrapper>
            {bets.length > 0 ? (
              bets.map((bet) => (
                <S.Bet key={bet.id}>
                  <S.DeleteButton onClick={() => deleted(bet.id)}>
                    <BsTrash size={26} />
                  </S.DeleteButton>
                  <S.BetDetails color={bet.color}>
                    <S.BetNumbers>{bet.selectedNumbers.join()}</S.BetNumbers>
                    <S.NameAndPrice>
                      <S.LotteryName color={bet.color}>
                        {bet.type}
                      </S.LotteryName>
                      <S.LoteryPrice>
                        {' '}
                        {bet.price.toLocaleString('pt-br', {
                          style: 'currency',
                          currency: 'BRL'
                        })}
                      </S.LoteryPrice>
                    </S.NameAndPrice>
                  </S.BetDetails>
                </S.Bet>
              ))
            ) : (
              <span>Carrinho vazio. Faça uma aposta!</span>
            )}
          </S.BetsWrapper>

          <S.CartTotal>
            <strong>CART</strong> TOTAL:{' '}
            {totalPrice.toLocaleString('pt-br', {
              style: 'currency',
              currency: 'BRL'
            })}
          </S.CartTotal>
        </S.Cart>
        <S.SaveButton onClick={handleSavedButton}>
          Save <BsArrowRight size={38} />
        </S.SaveButton>
      </S.Wrapper>
    </>
  );
};

export default Cart;
<file_sep>/src/store/modules/bets/actions/actionTypes.js
export const FETCH_BET_START = 'FETCH_BET_START';
export const FETCH_BET_SUCCESS = 'FETCH_BET_SUCCESS';
export const FETCH_BET_FAIL = 'FETCH_BET_FAIL';
export const FETCH_BET = 'FETCH_BET';

export const SAVE_BET_START = 'SAVE_BET_START';
export const SAVE_BET_SUCCESS = 'SAVE_BET_SUCCESS';
export const SAVE_BET_FAIL = 'SAVE_BET_FAIL';
<file_sep>/src/components/CardForm/styles.js
import styled from 'styled-components';

export const Wrapper = styled.div`
  display: flex;
  flex-direction: column;
`;

export const Header = styled.h1`
  text-align: center;
  font: italic normal bold 35px Arial;
  letter-spacing: 0px;
  color: #707070;
  margin-bottom: 25px;
`;

export const Card = styled.form`
  display: flex;
  flex-direction: column;
  width: 352px;
  background: #ffffff 0% 0% no-repeat padding-box;
  box-shadow: 0px 3px 25px #00000014;
  border: 1px solid #dddddd;
  border-radius: 14px;
`;

export const InputsWrapper = styled.form`
  display: flex;
  flex: 1;
  flex-direction: column;
  div {
    display: flex;
    flex-direction: column;
    label {
      text-align: left;
      font: italic normal bold 17px Arial;
      margin-top: 34px;
      margin-left: 30px;
      letter-spacing: 0px;
      color: #9d9d9d;
    }

    input {
      flex: 1;
      border-bottom: 2px solid #ebebeb;
      color: #9d9d9d;
      padding-left: 20px;
    }
  }
`;

export const OptionalLink = styled.span`
  flex: 1;
  text-align: right;
  font: italic normal normal 17px Arial;
  letter-spacing: 0px;
  color: #c1c1c1;
  margin-top: 27px;
  margin-right: 27px;
  a {
    text-decoration: none;
    color: #c1c1c1;
  }
`;

export const SubmitButton = styled.button`
  flex: 1;
  text-align: center;
  font: italic normal bold 35px Arial;
  letter-spacing: 0px;
  color: #b5c401;
  background: none;
  margin-top: 44px;
  margin-bottom: 43px;
  svg {
    vertical-align: middle;
  }
  a {
    text-decoration: none;
    color: #b5c401;
  }
`;

export const LastButton = styled.span`
  flex: 1;
  text-align: center;
  font: italic normal bold 35px Arial;
  letter-spacing: 0px;
  color: #707070;
  margin-top: 30px;

  a {
    text-decoration: none;
    color: #707070;
  }
`;
<file_sep>/src/pages/NewGame/styles.js
import styled, { keyframes } from 'styled-components';
import media from 'styled-media-query';
import { shade, lighten } from 'polished';

const appearFromLeft = keyframes`
  from {
    opacity: 0;
    transform: translateX(-50px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
`;

export const Wrapper = styled.div`
  display: flex;
  align-self: center;
  justify-content: center;
  flex-direction: row;
  margin-top: 72px;
  align-items: center;
  overflow-x: hidden;

  animation: ${appearFromLeft} 1s;

  ${media.lessThan('medium')`
    margin-top: 70px;
    flex-direction: column;
  `}
`;

export const GamesWrapper = styled.div`
  width: 1080px;
  display: flex;
  align-self: center;
  flex-direction: column;

  ${media.lessThan('medium')`
    margin-bottom: 20px;
    margin-left: 400px;
    margin: auto;
    padding: 20px;
  `}
`;

export const GameHeader = styled.div`
  display: flex;
  text-align: left;
  text-transform: uppercase;

  ${media.lessThan('medium')`
    flex-direction: row;
    margin-bottom: 20px;
  `}
`;

export const NewBet = styled.h1`
  text-align: center;
  font: italic normal bold 24px Arial;
  letter-spacing: 0px;
  color: #707070;
  margin-right: 10px;

  ${media.lessThan('medium')`
    flex-direction: row;
  `}
`;

export const GameName = styled.h1`
  text-align: center;
  font: italic normal 300 24px Arial;
  letter-spacing: 0px;
  color: #707070;

  ${media.lessThan('medium')`
    flex-direction: row;
    margin-bottom: 20px;
  `}
`;

export const ChoiceWrapper = styled.div`
  display: flex;
  flex-direction: column;
  margin-top: 33px;

  ${media.lessThan('medium')`
    flex-direction: row;
    margin-bottom: 20px;

  `}
`;

export const ChoiceHeader = styled.div`
  text-align: left;
  font: italic normal bold 17px Arial;
  letter-spacing: 0px;
  color: #868686;

  ${media.lessThan('medium')`
  text-align: center;
  `}
`;

export const ChoicesButtons = styled.div`
  display: flex;
  margin-top: 20px;

  ${media.lessThan('medium')`
    flex-direction: column;
    margin-bottom: 20px;
    margin-top: 20px;
  `}
`;

export const InstructionsWrapper = styled.div`
  margin-top: 37px;
`;

export const InstructionsHeader = styled.p`
  font: italic normal bold 17px Arial;
  letter-spacing: 0px;
`;

export const Instructions = styled.p`
  width: 65%;
  font: italic normal normal 17px Arial;
  letter-spacing: 0px;
`;

export const NumbersWrapper = styled.div`
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 20px;
  margin-top: 25px;
  width: 60%;
  margin-bottom: 44px;

  ${media.lessThan('medium')`
  grid-template-columns: repeat(6, 1fr);
  gap: 5px;
  width: 200px;
  `}
`;

export const ControlsWrapper = styled.div`
  width: 60%;
  display: flex;
  justify-content: space-around;

  ${media.lessThan('medium')`
  width: 400px;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  `}
`;

export const CompleteAndClear = styled.div`
  button {
    height: 52px;
    border: 1px solid #27c383;
    border-radius: 10px;
    font: normal normal medium 16px Arial;
    letter-spacing: 0px;
    color: #27c383;
    background: none;
    transition: background-color 0.4s;
    padding: 8px;

    &:hover {
      background-color: ${shade(0.2, '#27c383')};
      color: #fff;
    }

    & + button {
      margin-left: 25px;
    }
  }

  ${media.lessThan('medium')`
  margin-bottom: 10px;
  `}
`;

export const CartControl = styled.div`
  button {
    width: 209px;
    height: 52px;
    background: #27c383 0% 0% no-repeat padding-box;
    border: 1px solid #27c383;
    border-radius: 10px;
    font: normal normal bold 16px Arial;
    letter-spacing: 0px;
    color: #ffffff;
    transition: background-color 0.4s;

    &:hover {
      background-color: ${lighten(0.05, '#27c383')};
      color: #fff;
    }
  }

  svg {
    vertical-align: middle;
    margin-right: 28px;
    color: #fff;
  }
`;
<file_sep>/src/store/modules/lotterys/sagas/sagas.js
import api from '../../../../services/api';
import { put } from 'redux-saga/effects';
import * as actions from '../actions/actions';

export function* fetchedLotterySaga(action) {
  yield put(actions.fetchLotteryStart());

  try {
    const response = yield api.get('/types');
    const fetchedLottery = [];
    fetchedLottery.push({
      ...response.data
    });
    yield put(actions.fetchLotterySuccess(fetchedLottery));
  } catch (error) {
    yield put(actions.fetchLotteryFail(error));
  }
}
<file_sep>/src/store/modules/bets/reducers/reducer.js
import * as actionTypes from '../actions/actionTypes';
import { updateObject } from '../../../utility';

const initialState = {
  bets: [],
  loading: true,
  error: false
};

const saveBet = (state, action) => {
  const updatedState = {
    bets: action.bets.concat(state.bets)
  };
  return updateObject(state, updatedState);
};

const fetchBetStart = (state, action) => {
  return updateObject(state, { loading: true });
};

const fetchBetFail = (state, action) => {
  return updateObject(state, { loading: false });
};

const fetchBetFinished = (state, action) => {
  return updateObject(state, { loading: false });
};

const fetchBets = (state, action) => {
  return updateObject(state, {
    bets: action.bets
  });
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.SAVE_BET_SUCCESS:
      return saveBet(state, action);
    case actionTypes.FETCH_BET_START:
      return fetchBetStart(state, action);
    case actionTypes.FETCH_BET_FAIL:
      return fetchBetFail(state, action);
    case actionTypes.FETCH_BET_SUCCESS:
      return fetchBets(state, action);
    default:
      return state;
  }
};

export default reducer;
<file_sep>/src/pages/ResetPassword/index.jsx
import React from 'react';
import * as S from './styles';

import Header from '../../components/Header';
import CardForm from '../../components/CardForm';
import Footer from '../../components/Footer';

const ResetPassword = () => {
  const inputFields = [
    {
      label: 'Email',
      type: 'text',
      name: 'email'
    }
  ];

  return (
    <>
      <S.Wrapper>
        <Header />
        <CardForm
          header="Reset password"
          inputFields={inputFields}
          submitButtonText="Send link"
          lastButtonLink="/"
          lastButtonText="Back"
          methor="forgot"
        />
      </S.Wrapper>
      <Footer />
    </>
  );
};

export default ResetPassword;
<file_sep>/src/store/modules/lotterys/actions/actions.js
import * as actionTypes from './actionTypes';

export const fetchLotteryStart = () => {
  return {
    type: actionTypes.FETCH_LOTTERY_START
  };
};

export const fetchLotterySuccess = (lottery) => {
  return {
    type: actionTypes.FETCH_LOTTERY_SUCCESS,
    lottery: lottery
  };
};

export const fetchLotteryFail = (error) => {
  return {
    type: actionTypes.FETCH_LOTTERY_FAIL,
    error: error
  };
};

export const fecthLottery = () => {
  return {
    type: actionTypes.FETCH_LOTTERY
  };
};
<file_sep>/src/components/LotteryButton/styles.js
import styled, { css } from 'styled-components';
import { shade } from 'polished';
import media from 'styled-media-query';

export const Wrapper = styled.button`
  width: 113px;
  height: 34px;
  background: #ffffff 0% 0% no-repeat padding-box;
  margin-right: 25px;
  border-radius: 100px;
  text-align: center;
  font: italic normal bold 14px Arial;
  letter-spacing: 0px;

  transition: background-color 0.2s;

  ${media.lessThan('medium')`
    margin-bottom: 10px;
    ;
  `}

  ${(props) =>
    props.color &&
    css`
      color: ${props.color};
      border: 2px solid ${props.color};
      &:hover {
        background: ${shade(0.1, `${props.color}`)};
        color: #ffffff;
      }
    `}

  ${(props) =>
    props.active &&
    css`
      color: ${props.color};
      background: ${shade(0.1, `${props.color}`)};
      color: #ffffff;
    `}
`;
<file_sep>/src/styles/themes.js
export default {
  font: {
    family:
      "Arial ,Roboto, Ubuntu, 'Open Sans',  sans-serif",
    bold: 600,
  },
  colors: {
    primary: '##F7F7F7',
    primaryHover: '#ADC0C4',
    lotofacil: '#7F3992',
    megasena: '#10AC66',
    lotomania: '#FAAE31',
    cartbg: '#FFFFFF',
    boxBg: '#FAFAFA',
    texts: '#707070',
    white: '#FFFFFF',
    black: '#000000',
    gray: '#7B7373'
  },
}
<file_sep>/src/pages/Dashboard/styles.js
import styled, { keyframes } from 'styled-components';
import media from 'styled-media-query';

const appearFromLeft = keyframes`
  from {
    opacity: 0;
    transform: translateX(-50px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
`;

export const Wrapper = styled.div`
  display: flex;
  width: 70%;
  flex-direction: column;
  align-items: flex-start;
  margin-left: 390px;
  margin-top: 75px;
  animation: ${appearFromLeft} 1s;

  ${media.lessThan('medium')`
    margin-bottom: 20px;
    margin: auto;
  `}
`;

export const GamesHeader = styled.div`
  display: flex;
  ${media.lessThan('medium')`
    justify-content: center;
    align-items: center;
  `}
`;

export const Recent = styled.h4`
  font: italic normal bold 24px Arial;
  letter-spacing: 0px;
  color: #707070;
  text-transform: uppercase;
`;

export const FilterWrapper = styled.div`
  display: flex;
  margin-left: 46px;
  ${media.lessThan('medium')`
   flex-direction: column;
   margin-left: 0;
  `}
`;
export const FilterSpan = styled.span`
  font: italic normal normal 17px Arial;
  letter-spacing: 0px;
  padding-top: 4px;
  color: #868686;

  ${media.lessThan('medium')`
   text-align: center;
   margin-left: -6px;
   margin-bottom: 4px;
  `}
`;

export const FiltersContainer = styled.div`
  margin-left: 16px;
`;

export const NewBet = styled.div`
  font: italic normal bold 24px Arial;
  letter-spacing: 0px;

  margin-left: 200px;
  a {
    color: #b5c401;
    text-decoration: none;
  }
  svg {
    vertical-align: middle;
  }
  ${media.lessThan('medium')`
    margin-left: 0;
  `}
`;

export const GamesWrapper = styled.div`
  margin-top: 38px;
  span {
    font: normal normal normal 20px Arial;
    letter-spacing: 0px;
    color: #868686;
  }

  ${media.lessThan('medium')`
    left: 0;
  `}
`;

export const Game = styled.div`
  display: flex;
  margin-bottom: 30px;
  hr {
    border: 3px solid ${(props) => props.color && props.color};
    border-radius: 10px;
    margin-right: 15px;
  }
`;

export const GameDetails = styled.div``;

export const GameNumbers = styled.div`
  font: italic normal bold 20px Arial;
  letter-spacing: 0px;
  color: #868686;
  margin-bottom: 15px;
`;

export const DateAndCost = styled.div`
  font: normal normal normal 17px Arial;
  letter-spacing: 0px;
  color: #868686;
  margin-bottom: 11px;
`;

export const GameName = styled.div`
  font: italic normal bold 20px Arial;
  letter-spacing: 0px;
  color: ${(props) => props.color && props.color};
`;
<file_sep>/src/routes/index.jsx
import React from 'react';
import { Switch, Route } from 'react-router-dom';

import Home from '../pages/Home';
import ResetPassword from '../pages/ResetPassword';
import Register from '../pages/Register';
import NewGame from '../pages/NewGame';
import Dashboard from '../pages/Dashboard';
import Account from '../pages/Account';

const Routes = () => (
  <Switch>
    <Route path="/" exact component={Home} />
    <Route path="/dashboard" component={Dashboard} />
    <Route path="/account" component={Account} />
    <Route path="/resetpassword" component={ResetPassword} />
    <Route path="/register" component={Register} />
    <Route path="/newgame" component={NewGame} />
  </Switch>
);

export default Routes;
<file_sep>/src/components/Footer/styles.js
import styled from 'styled-components';
import media from 'styled-media-query';

export const Wrapper = styled.footer`
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #707070;
  border-top: 2px solid #ebebeb;
  border-bottom: 2px solid #ebebeb;
  font-size: 15px;

  ${media.lessThan('medium')`
    display: none;
  `}
`;
<file_sep>/src/pages/Register/index.jsx
import React from 'react';
import * as S from './styles';

import CardForm from '../../components/CardForm';
import Header from '../../components/Header';
import Footer from '../../components/Footer';

const Register = () => {
  const inputFields = [
    {
      label: 'Name',
      type: 'text',
      name: 'username'
    },
    {
      label: 'Email',
      type: 'email',
      name: 'email'
    },
    {
      label: 'Password',
      type: '<PASSWORD>',
      name: '<PASSWORD>'
    },
    {
      label: 'Password Confirmation',
      type: 'password',
      name: 'password_confirmation'
    }
  ];
  return (
    <>
      <S.Wrapper>
        <Header />
        <CardForm
          header="Registration"
          inputFields={inputFields}
          submitButtonText="Register"
          lastButtonLink="/"
          lastButtonText="Back"
          method="signUp"
        />
      </S.Wrapper>
      <Footer />
    </>
  );
};

export default Register;
<file_sep>/src/store/modules/bets/actions/actions.js
import * as actionTypes from './actionTypes';

export const saveBetStart = () => {
  return {
    type: actionTypes.SAVE_BET_START
  };
};

export const saveBetSuccess = (bets) => {
  return {
    type: actionTypes.SAVE_BET_SUCCESS,
    bets: bets
  };
};

export const saveBetFail = (error) => {
  return {
    type: actionTypes.SAVE_BET_FAIL,
    error: error
  };
};

export const fetchBetStart = (token) => {
  return {
    type: actionTypes.FETCH_BET_START,
    token
  };
};

export const fetchBetSuccess = (bets) => {
  return {
    type: actionTypes.FETCH_BET_SUCCESS,
    bets: bets,
    loading: false
  };
};

export const fetchBetFail = (error) => {
  return {
    type: actionTypes.FETCH_BET_FAIL,
    error: error
  };
};

export const fecthBet = () => {
  return {
    type: actionTypes.FETCH_BET
  };
};
<file_sep>/src/components/Ball/index.jsx
import React from 'react';
import * as S from './styles';

const Ball = ({ number, clicked, isActive, disabled, color }) => {
  return (
    <S.Wrapper
      color={color}
      disabled={disabled}
      isActive={isActive}
      onClick={clicked}
    >
      <span>{number}</span>
    </S.Wrapper>
  );
};

export default Ball;
<file_sep>/src/store/modules/bets/sagas/index.js
import { takeEvery } from 'redux-saga/effects';
import * as actionTypes from '../actions/actionTypes';

import { fetchBetsSaga } from './sagas';

export function* watchBets() {
  yield takeEvery(actionTypes.FETCH_BET, fetchBetsSaga);
}
<file_sep>/src/components/Menu/styles.js
import styled from 'styled-components';
import media from 'styled-media-query';

export const Wrapper = styled.nav`
  display: flex;
  top: 0;
  padding-top: 15px;
  padding-left: 141px;
  padding-right: 200px;
  height: 76px;
  width: 100vw;
  border-bottom: 2px solid #ebebeb;
  justify-content: space-around;
  ${media.lessThan('medium')`
    margin-left: 12px;
    `}
`;

export const LogoAndHome = styled.div`
  display: flex;
`;

export const Logo = styled.div`
  text-align: center;
  font: italic normal bold 44px Arial;
  letter-spacing: 0px;
  color: #707070;

  hr {
    border: 4px solid #b5c401;
    border-radius: 6px;
    width: 106px;
    margin-top: 6px;
  }
`;

export const Home = styled.div`
  justify-content: center;
  align-items: center;
  text-align: center;
  font: italic normal bold 20px Arial;
  letter-spacing: 0px;
  margin-left: 74px;
  margin-top: 16px;
  ${media.lessThan('medium')`
    margin-left: 10px;
    margin-top: 10px;
    `}
  a {
    color: #707070;
    text-decoration: none;
  }
`;

export const AccountAndLogout = styled.div`
  padding-top: 10px;
  span {
    text-align: center;
    font: italic normal bold 20px Arial;
    letter-spacing: 0px;
    color: #707070;
  }

  a {
    text-align: center;
    font: italic normal bold 20px Arial;
    letter-spacing: 0px;
    color: #707070;
    text-decoration: none;
    margin-left: 40px;

    svg {
      vertical-align: middle;
      ${media.lessThan('medium')`
      display: none;
    `}
    }
  }

  ${media.lessThan('medium')`
    margin-left: 10px;
    `}
`;

export const LogoutButton = styled.button`
  text-align: center;
  font: italic normal bold 20px Arial;
  letter-spacing: 0px;
  color: #707070;
  text-decoration: none;
  margin-left: 40px;
  background: none;
  svg {
    vertical-align: middle;
    ${media.lessThan('medium')`
      display: none;
    `}
  }
`;
<file_sep>/src/pages/Home/index.jsx
import React, { useEffect } from 'react';
import * as S from './styles';
import CardForm from '../../components/CardForm';
import Header from '../../components/Header';
import Footer from '../../components/Footer';
import { useHistory } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { toast } from 'react-toastify';

const Home = () => {
  const history = useHistory();
  const auth = useSelector((state) => {
    return {
      isAuth: state.auth.isAuth,
      error: state.auth.error
    };
  });

  useEffect(() => {
    if (auth.isAuth) {
      history.push('/dashboard');
    }

    if (auth.error) {
      toast.error(
        'Algo deu errado ao fazer login, verifique seu email e senha.'
      );
    }
  }, [auth.isAuth, history, auth]);
  const inputFields = [
    {
      label: 'Email',
      type: 'text',
      name: 'email'
    },
    {
      label: 'Password',
      type: 'password',
      name: 'password'
    }
  ];

  return (
    <>
      <S.Wrapper>
        <Header />
        <CardForm
          header="Authentication"
          optionalLink="/resetpassword"
          optionalText="I forgot my password"
          inputFields={inputFields}
          submitButtonText="Log In"
          submitButtonLink="/dashboard"
          lastButtonLink="/register"
          lastButtonText="Sign Up"
          lastIconRight={true}
          method="login"
        />
      </S.Wrapper>

      <Footer />
    </>
  );
};

export default Home;
<file_sep>/src/store/modules/auth/sagas/index.js
import { takeEvery } from 'redux-saga/effects';
import * as actionTypes from '../actions/actionTypes';

import { authSagas } from './sagas';

export function* watchAuth() {
  yield takeEvery(actionTypes.AUTH_REQUEST, authSagas);
}
<file_sep>/src/pages/Register/styles.js
import styled, { keyframes } from 'styled-components';
import media from 'styled-media-query';

const appearFromRight = keyframes`
  from {
    opacity: 0;
    transform: translateX(50px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
`;

export const Wrapper = styled.div`
  display: flex;
  flex-direction: row;
  margin-top: 154px;
  align-items: center;
  justify-content: space-evenly;
  overflow-x: hidden;

  animation: ${appearFromRight} 1s;

  ${media.lessThan('medium')`
    flex-direction: column;
    margin-top: 70px;
  `}
`;
<file_sep>/src/components/Ball/styles.js
import styled from 'styled-components';
import { shade } from 'polished';

export const Wrapper = styled.button`
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 50%;
  width: 65px;
  height: 65px;
  font: normal normal bold 20px Arial;
  letter-spacing: 0px;
  color: #ffffff;
  transition: cursor 0.2s;

  background: ${(props) => (props.isActive ? props.color : '#adc0c4;')};

  /* &:hover {
    background: ${shade(0.4, '#adc0c4')};
    cursor: pointer;
  } */

  &:disabled {
    cursor: not-allowed;
    :hover {
      background-color: ${(props) => props.color && props.color};
    }
  }
`;
