<|start_filename|>src/components/homepage/top-players/rankPlayers.js<|end_filename|>
import axios from "axios";
import {
  BASE_URL,
  RANK_PLAYERS,
} from "../../../redux/user/service/root-endpoints";

export const rankPlayers = (descendingOrderOfPlayers) => {
  try {
    let rankingTempholder = [];

    // Rank the player based on their descending order position - set rank
    descendingOrderOfPlayers.forEach((player, index) => {
      // Index starts from 0, rank start from 1
      player.rank = index + 1;

      // Store the player in order of rank in the temp holder
      return rankingTempholder.push(player);
    });

    // Update the players rank in the database if there is a ranking
    if (rankingTempholder) {
      rankingTempholder?.forEach(async (player) => {
        const { id, rank } = player;
        //Update user record with the new rank
        const payload = {
          id: id,
          rank: Number(rank),
        };
        // Update the player details
        const res = await axios.put(BASE_URL + RANK_PLAYERS, payload);
      });
    }
  } catch (error) {
    console.log(error);
  }
};


<|start_filename|>src/redux/user/reducers/user.reducers.js<|end_filename|>
import {
  SET_SCREEN_MESSAGE,
  CLEAR_SCREEN_MESSAGE,
  REGISTRATION_SUCCESSFUL,
  LOGIN_SUCCESSFULL,
  USER_LOADED,
  PLAYER_GAME_RECORD_LOADED,
  LOGOUT,
  CLEAR_NOTIFICATION,
  SET_NOTIFICATION,
} from "./../../types/index";

const INITIAL_STATE = {
  user: null,
  notification: null,
  gameRecord: null,
  screenMessage: {
    message: null,
    type: null,
  },
  isLoggedIn: false,
};

// redux reducer function
const userReducer = (state = INITIAL_STATE, action) => {
  // Destructure type and payload from action
  const { type, payload } = action;

  switch (type) {
    case SET_SCREEN_MESSAGE: // Handles all NOTIFICATIONS, i.e no need for registration/login error cases
      return {
        ...state,
        screenMessage: {
          message: payload.message,
          type: payload.type,
        },
      };
    case CLEAR_SCREEN_MESSAGE: // Clear all error
      return {
        ...state,
        screenMessage: {
          message: null,
          type: null,
        },
      };
    case REGISTRATION_SUCCESSFUL:
      return {
        ...state,
      };
    case LOGIN_SUCCESSFULL:
      return {
        ...state,
        isLoggedIn: true,
      };
    case USER_LOADED:
      return {
        ...state,
        user: payload,
        isLoggedIn: true,
      };
    case PLAYER_GAME_RECORD_LOADED:
      return {
        ...state,
        gameRecord: payload,
      };

    case SET_NOTIFICATION:
      return {
        ...state,
        notification: payload,
      };

    case CLEAR_NOTIFICATION:
      return {
        ...state,
        notification: null,
      };

    case LOGOUT:
      return {
        user: null,
        gameRecord: null,
        screenMessage: {
          message: null,
          type: null,
        },
        isLoggedIn: false,
      };

    default:
      // return the state by default else react will shout
      return state;
  }
};

export default userReducer;


<|start_filename|>src/components/layouts/notification/overheadnotify/OverHeadNotify.js<|end_filename|>
import React from 'react';
import './overheadnotify.css';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faFacebookF, faLinkedinIn, faTwitter } from '@fortawesome/free-brands-svg-icons';
import { GithubStar } from './github-star/GithubStar';

export const OverHeadNotify = () => {
    return (
        <React.Fragment>
            <div className="over-head-notification">

                {/* Project Github star */}
                <section className="github-star-wrapper">
                    <GithubStar />
                </section>

                {/* Social Media Section */}
                <section className="social-media--follow">
                    <a 
                        href="https://www.facebook.com/sharer/sharer.php?u=https://unclebigbay.hashnode.dev" 
                        target="_blank"
                        rel="noopener noreferrer"
                    >
                        <abbr title="Share to facebook">
                            <FontAwesomeIcon icon={faFacebookF} />
                        </abbr>
                    </a>
                    <a 
                        target="_blank"
                        rel="noopener noreferrer"
                        data-size="large"
                        href="https://twitter.com/intent/follow?screen_name=unclebigbay143"
                    >
                        <abbr title="Follow us on twitter">
                            <FontAwesomeIcon icon={faTwitter} />
                        </abbr>
                    </a>
                    <a 
                        href="https://www.linkedin.com/in/unclebigbay" 
                        target="_blank" 
                        rel="noopener noreferrer"
                    >
                        <abbr title="Follow us on twitter">
                            <FontAwesomeIcon icon={faLinkedinIn} />
                        </abbr>
                    </a>
                </section>
            </div>
        </React.Fragment>
    )
}


<|start_filename|>src/components/layouts/notification/flier-notification/notify.css<|end_filename|>
.notify-container {
  padding: 1rem;
  z-index: 1000;
  position: relative;
  background-color: white;
}

.notify-content {
  display: flex;
  justify-content: center;
}

.close--notify {
  margin-left: 2rem;
  color: var(--warning-color);
  font-weight: 700;
  cursor: pointer;
}

.notify-content p {
  font-weight: 550;
}

.notify-content a {
  color: #4c96e8;
  text-transform: capitalize;
}

.notify-content .black-link {
  color: initial;
}

.notify-content .no-underline {
  text-decoration: none;
}

.notify-content .no-underline:hover {
  text-decoration: underline;
}


<|start_filename|>src/components/layouts/navbar/navbar.css<|end_filename|>
.navbar{
    height: 5rem;
    padding: 0 4vw;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.navbar--brand{
    padding-right: 2rem;
    color: var(--white-color);
    font-size: 1.3rem;
}

.navbar--brand code{
    font-family: var(--poppins);

}

.left-items-links{
    display: none;
}

.left-items-links a{
    color: var(--white-color);
    text-decoration: none;
    margin-right: 1rem;
    padding-bottom: 0.3rem;
    font-size: 0.934rem;
    font-weight: 600;
    position: relative;
}

.left-items-links a:hover{
    border-bottom: 2px solid var(--white-color);
}

.right-items .button:last-child{
    display: none;
}

@media(min-width: 1100px){

    .left-items{
        display: flex;
        align-items: center;
    }

    .left-items-links{
        display: block;
    }
    
    .right-items .button:first-child{
        margin-right: 0.5rem;
    }

    .right-items .button:last-child{
        display: inline;
    }
}

<|start_filename|>src/components/pageurl/index.js<|end_filename|>
export const pageurl = {
  HOMEPAGE: "/",
  REGISTER: "/get-started",
  WELCOME_ONBOARD: "/welcome",
  LOGIN: "/login",
  FORGOT_PASSWORD: <PASSWORD>",
  FORGOT_PASSWORD_CONFIRMATION: "/success",
  DASHBOARD: "/dashboard",
  GAME_RESULT: "/dashboard/result",
  USER_PROFILE: "/dashboard/me",
  UPDATE_PROFILE: "/dashboard/update",
};


<|start_filename|>src/components/game/typingboard/Timer.js<|end_filename|>
import React, { useEffect, useState } from "react";

export const Timer = ({ startingTime = 10, start }) => {
  const [timeRemaining, setTimeRemaining] = useState(startingTime);
  const [isTimeRunning, setIsTimeRunning] = useState(start);

  useEffect(() => {
    if (isTimeRunning && timeRemaining > 0) {
      setTimeout(() => {
        setTimeRemaining((time) => time - 1);
      }, 1000);
    } else if (timeRemaining === 0) {
      endGame();
    }
  }, [timeRemaining, isTimeRunning]);

  function endGame() {
    setIsTimeRunning(false);
  }

  return <span>{timeRemaining}</span>;
};


<|start_filename|>src/components/authentication/login/login.css<|end_filename|>
.login {
  background: var(--primary-color);
  width: 100%;
  min-height: 100vh;
  display: flex;
  flex-direction: column-reverse;
  justify-content: center;
  padding: 15vh 7.3vw;
}

.login .form-heading {
  line-height: 1.5;
  margin: 1rem 0;
  color: var(--white-color);
  font-size: 2rem;
}

form {
  width: fit-content;
}

.login .input-wrapper {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.input-wrapper label {
  color: var(--white-color);
  font-size: 1.5rem;
  margin-bottom: 1rem;
}

.login .error-message {
  font-size: 0.78rem;
  text-align: right;
  color: var(--white-color);
  font-weight: 600;
  position: relative;
  top: 30px;
}

.login .input-wrapper input {
  margin: 0.5rem 0 1rem 0;
  padding: 12px;
  height: 44px;
  width: 100%;
  padding-top: 11px;
  padding-bottom: 13px;
  font-size: 0.987rem;
  line-height: 1.33333333;
  border-radius: 4px;
  border: 2px solid var(--white-color);
  font-family: var(--poppins);
}

.login .input-wrapper input:focus {
  outline: 1px double var(--primary-color);
}

.login .input-wrapper:last-child {
  margin-top: 0.4rem;
}

.login .input-wrapper button {
  background-color: var(--touch-color);
  color: var(--white-color);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.5;
  font-family: var(--poppins);
  padding: 0.75rem 1rem;
}

.forgot-password {
  position: relative;
  top: 1.3rem;
}

.forgot-password a {
  color: var(--white-color);
  text-decoration: none;
  padding-bottom: 0.3rem;
}

.forgot-password a:hover {
  border-bottom: 0.09rem solid var(--white-color);
}

.login-image {
  display: none;
}

.type-writer {
  width: 100%;
  height: 100%;
}

@media (min-width: 900px) {
  .login {
    flex-direction: row;
    align-items: center;
    padding: 0 4vw;
  }

  .login .form-heading {
    line-height: 2;
    margin-bottom: 1rem;
    margin-top: 3rem;
    color: var(--white-color);
    font-size: 2rem;
  }

  .login-image {
    display: block;
    width: 50%;
  }

  .login-image .type-writer {
    margin: 8rem 1rem 2rem 2rem;
  }
}


<|start_filename|>src/components/layouts/navbar/Navbar.js<|end_filename|>
import React from "react";

// styles
import "./navbar.css";

// components
import { Button } from "../button/Button";
import { pageurl } from "../../pageurl";

export const Navbar = () => {
  return (
    <React.Fragment>
      <header>
        <nav className="navbar">
          <section className="left-items">
            <div className="navbar--brand">
              <h1>
                <code>&lt;/ Typing&gt;</code>
              </h1>
            </div>

            <div className="left-items-links">
              <a
                href="https://unclebigbay.com/introducing-developer-typing-game-platform-powered-by-the-hern-stack"
                target="_blank"
                rel="noopener noreferrer"
              >
                Features
              </a>
              <a
                href="https://unclebigbay.dev/"
                target="_blank"
                rel="noopener noreferrer"
              >
                Team
              </a>
              <a
                href="https://www.youtube.com/watch?v=25E6FPy9SPc"
                target="_blank"
                rel="noopener noreferrer"
              >
                Demo
              </a>
              <a
                href="https://www.buymeacoffee.com/unclebigbay"
                target="_blank"
                rel="noopener noreferrer"
              >
                Buy Me a coffee
              </a>
              <a
                href="https://unclebigbay.com/introducing-developer-typing-game-platform-powered-by-the-hern-stack"
                target="_blank"
                rel="noopener noreferrer"
              >
                Contribute
              </a>
            </div>
          </section>
          <section className="right-items">
            <div className="right-items-links">
              <Button
                look="custom--btn-outline link-btn"
                label="Start Typing"
                linkUrl={pageurl.LOGIN}
              />

              <Button
                label="create a new account"
                look="link-btn"
                linkUrl={pageurl.REGISTER}
              />
            </div>
          </section>
        </nav>
      </header>
    </React.Fragment>
  );
};


<|start_filename|>src/components/winner/winner.css<|end_filename|>
.winner-alert.open-alert {
  display: flex;
  justify-content: center;
}

.winner-alert.close-alert {
  display: none;
}

.winner-alert--wrapper {
  padding: 2rem;
  height: 100%;
  width: 100%;
  position: absolute;
  background: hsl(70, 31%, 85%);
  z-index: 1000;
}

.close-winner--alert {
  text-align: right;
  margin-bottom: 1rem;
}

.close-winner--alert svg {
  font-size: 2rem;
  color: var(--grey-color);
  cursor: pointer;
}

/* text */

.content {
  text-align: center;
  line-height: 2;
  margin-bottom: 2rem;
}

.winner-alert .content h1 {
  color: #799ed2;
  text-transform: uppercase;
  font-size: 2.5rem;
}

.congratulation-name {
  text-transform: uppercase;
  font-size: 1.3rem;
  color: #8882c9;
  color: #c9c85e;
  font-weight: 700;
}

.winner-alert .content p {
  text-transform: capitalize;
  color: #66cc86;
  font-size: 1.2rem;
}

/* Balloon styles */

.balloon-container {
  text-align: center;
}

.balloon {
  display: inline-block;
  width: 120px;
  height: 145px;
  background: hsl(215, 50%, 65%);
  border-radius: 80%;
  position: relative;
  box-shadow: inset -10px -10px 0 rgba(0, 0, 0, 0.07);
  margin: 20px 30px;
  transition: transform 0.5s ease;
  z-index: 10;
  animation: balloons 4s ease-in-out infinite;
  transform-origin: bottom center;
}

@keyframes balloons {
  0%,
  100% {
    transform: translateY(0) rotate(-4deg);
  }
  50% {
    transform: translateY(-25px) rotate(4deg);
  }
}

.balloon:before {
  content: "▲";
  font-size: 20px;
  color: hsl(215, 30%, 50%);
  display: block;
  text-align: center;
  width: 100%;
  position: absolute;
  bottom: -12px;
  z-index: -100;
}

.balloon:after {
  display: inline-block;
  top: 153px;
  position: absolute;
  height: 250px;
  height: 150px;
  width: 1px;
  margin: 0 auto;
  content: "";
  background: rgba(0, 0, 0, 0.2);
}

.balloon:nth-child(2) {
  background: hsl(245, 40%, 65%);
  animation-duration: 3.5s;
}
.balloon:nth-child(2):before {
  color: hsl(245, 40%, 65%);
}

.balloon:nth-child(3) {
  background: hsl(139, 50%, 60%);
  animation-duration: 3s;
}
.balloon:nth-child(3):before {
  color: hsl(139, 30%, 50%);
}

.balloon:nth-child(4) {
  background: hsl(59, 50%, 58%);
  animation-duration: 4.5s;
}
.balloon:nth-child(4):before {
  color: hsl(59, 30%, 52%);
}

.balloon:nth-child(5) {
  background: hsl(23, 55%, 57%);
  animation-duration: 5s;
}
.balloon:nth-child(5):before {
  color: hsl(23, 44%, 46%);
}


<|start_filename|>src/components/game/music/AudioPlayer.js<|end_filename|>
import { faPauseCircle, faPlayCircle } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useRef, useState } from "react";
import "./audioplayer.css";

import loffyMusic from "./../../../assets/audio/ES_Deprived - Guustavv.mp3";

export const AudioPlayer = () => {
  const [playing, setPlaying] = useState(false);
  const audioElement = useRef(false);
  // const [audioName, setAudioName] = useState("Playing...");
  // SPLIT THE URL BY /
  const splitUrl = audioElement.current.currentSrc?.split("/");
  // THE URL IS THE LAST ARRAY
  const audioName = splitUrl && splitUrl[splitUrl.length - 1];

  const handleMusic = () => {
    if (playing) {
      // IF THE AUDIO IS PLAYING, PAUSE IT
      audioElement.current.pause();
      setPlaying(false);
    } else {
      // HENCE THE AUDIO IS PAUSED, PLAY THE MUSIC
      setPlaying(true);
      audioElement.current.play();
    }
  };

  return (
    <React.Fragment>
      <div className="audio-name">
        {playing && <marquee scrollamount="1">{audioName}</marquee>}
      </div>
      <div className="music-player">
        <audio ref={audioElement} loop>
          <source src={loffyMusic} type="audio/mp3" />
          <source src="horse.mp3" type="audio/mpeg" />
          Your browser does not support the audio element.
        </audio>
        <abbr title="Lofi Music">
          <FontAwesomeIcon
            icon={playing ? faPauseCircle : faPlayCircle}
            onClick={handleMusic}
          />
        </abbr>
      </div>
    </React.Fragment>
  );
};


<|start_filename|>src/components/game/sidebar/Sidebar.js<|end_filename|>
import { faCloud, faHome, faSun } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useEffect, useState } from "react";
import { Link, useLocation } from "react-router-dom";
import { pageurl } from "../../pageurl";
import { AudioPlayer } from "../music/AudioPlayer";
import "./sidebar.css";
import dummyImage from "./../../../assets/img/no-image-avatar.png";

import { SidebarMenu } from "./SidebarMenu";
import { comingSoon } from "../../comingSoon";
import { useDispatch, useSelector } from "react-redux";

export const Sidebar = ({ themeCallback }) => {
  const [darkTheme, setDarkTheme] = useState(false);
  const location = useLocation();
  const { notification } = useSelector((state) => state.user);

  const [showHomeButton, setShowHomeButton] = useState(false);
  const [openMenu, setOpenMenu] = useState(false);
  const dispatch = useDispatch();
  let prefferedTheme = JSON.parse(localStorage.getItem("_dark_theme"));

  // check if the current path is the dashboard
  const currentPageNotDashboard =
    location.pathname === pageurl.DASHBOARD ? false : true;

  useEffect(() => {
    setDarkTheme(prefferedTheme);

    // If the current page is not dashboard
    if (currentPageNotDashboard) {
      setShowHomeButton(true);
    } else {
      // If the current page is dashboard, hide the icon
      setShowHomeButton(false);
    }

    // themeCallback(prefferedTheme)
  }, [prefferedTheme, currentPageNotDashboard]);

  const handleThemeSwitch = () => {
    // CHECK THE LOCALSTORAGE FOR USER'S PREVIOUS THEME
    localStorage.setItem("_dark_theme", !darkTheme);
    // UPDATE THE SIDEBAR STATE FOR ICON SWITCH
    setDarkTheme(!darkTheme);
    // UPDATE THE CALLBACK - GameArea
    themeCallback(!darkTheme);
  };

  return (
    <React.Fragment>
      <aside className={`sidebar ${notification && "custom-pt-5"} `}>
        <section className="sidebar-items-top">
          <div className="select-pro-language">
            <select
              className="form-control d-none"
              onChange={() => dispatch(comingSoon("Language Selection"))}
            >
              <option>javascript</option>
              <option>html</option>
              <option>css</option>
            </select>
          </div>

          {showHomeButton && (
            <div className="navigation-icon">
              <Link to={pageurl.DASHBOARD}>
                <abbr title="Dashboard">
                  <FontAwesomeIcon icon={faHome} />
                </abbr>
              </Link>
            </div>
          )}
        </section>

        <section className="sidebar-items-down">
          <AudioPlayer />
          <div className="theme-toggle">
            <abbr title="Switch Theme">
              <FontAwesomeIcon
                icon={darkTheme ? faCloud : faSun}
                onClick={handleThemeSwitch}
              />
            </abbr>
          </div>
          <div
            to={pageurl.GAME_RESULT}
            className={`profile-image ${notification && "lift"}`}
            onClick={() => setOpenMenu(!openMenu)}
          >
            <img src={dummyImage} alt="player profile" />
          </div>
        </section>
        <SidebarMenu openMenu={openMenu} />
      </aside>
    </React.Fragment>
  );
};


<|start_filename|>src/components/game/typingboard/typingboard.css<|end_filename|>
.typing-board {
  width: 70%;
  max-width: 70%;
  margin: 0 auto;
  font-family: var(--poppins);
  z-index: 999;
}

.rank-info {
  display: flex;
  justify-content: center;
  align-items: center;
  font-weight: 700;
  margin-bottom: 0.253rem;
  padding-right: 0.456rem;
}

.rank-info svg {
  color: var(--orange-color);
}

.rank-info .position {
  margin-left: 0.5rem;
  font-size: 1.897rem;
}

.typing-text .instruction {
  color: var(--grey-color);
  margin-left: 1rem;
  font-size: 0.975rem;
  font-weight: 700;
  text-transform: capitalize;
}

.typing-wrapper,
.typing-input-wrapper {
  display: none;
}

.no-mobile-version {
  bottom: 3rem;
  text-align: right;
  text-transform: capitalize;
  color: var(--white-color);
}

.show-smiley {
  color: var(--grey-color);
  line-height: 2;
  text-align: center;
}

@media (max-width: 900px) {
  .show-smiley {
    display: none;
  }
}

.typing-text {
  width: 88%;
  white-space: nowrap;
  overflow: hidden;
}

.typing-wrapper .typing-text code {
  line-height: 2;
  color: var(--touch-color);
  /* color: #1f2937; */
  font-size: 1.5rem;
  font-weight: 900;
  /* opacity: 0.8; */
}

.typing-wrapper.dark .typing-text code {
  color: var(--grey-color);
}

.typing-wrapper.light .typing-text .character-out {
  color: var(--primary-color);
}

.typing-wrapper.dark .typing-text .character-out {
  color: var(--primary-color);
}

.typing-input-wrapper {
  width: 88%;
  background-color: var(--white-color);
  border: 2px solid var(--touch-color);
}

.typing-input-wrapper textarea {
  height: 200px;
  line-height: 2;
  resize: none;
  display: block;
  font-family: var(--poppins);
  font-size: 1.25rem;
  outline: none;
  border: none;
  /* opacity: .9; */
  color: var(--touch-color);
  background-color: rgba(74, 21, 75, 0.2);
  font-weight: 600;
  width: 100%;
  padding: 1rem 12rem 2rem 2rem;
}

.dark.typing-input-wrapper textarea {
  color: #1f2937;
  opacity: 0.8;
}

@media (min-width: 900px) {
  .no-mobile-version {
    display: none;
  }

  .typing-wrapper,
  .typing-input-wrapper {
    display: block;
    border-radius: 0.4rem;
  }

  .typing-wrapper {
    margin-bottom: 3rem;
    width: 88%;
  }

  .show-smiley {
    text-align: left;
  }
}


<|start_filename|>src/redux/user/service/user.services.js<|end_filename|>
// React
import axios from "axios";
import axiosInstance from "../../../axios";

// Endpoints
import {
  BASE_URL,
  LOAD_PLAYER_GAME_RECORD,
  LOAD_USER_ENDPOINT,
  LOGIN,
  REGISTER,
  UPDATE_USER_PROFILE_ENDPOINT,
} from "./root-endpoints";

// Registration service function
const registerNewPlayer = async (username, email, password) => {
  const payload = {
    userName: username,
    email,
    password,
  };

  // Async/Await
  try {
    const res = await axios.post(BASE_URL + REGISTER, payload, {
      // Access 400 message object
      validateStatus: function (status) {
        return status < 500; // Reject only if the status code is greater than or equal to 500
      },
    });

    // return response to action
    return res;
  } catch (error) {
    // Return error
    return error;
  }
};

// Login service function
const loginPlayer = async (username, password) => {
  const payload = {
    userName: username,
    password: password,
  };

  // Async/Await
  try {
    const res = await axios.post(BASE_URL + LOGIN, payload, {
      // Access 400 message object from response
      validateStatus: function (status) {
        return status < 500; // Reject only if the status code is greater than or equal to 500
      },
    });

    // Return response to action
    return res;
  } catch (error) {
    // Return error
    return error;
  }
};

// Load user
const loadPlayerProfile = async () => {
  // Async/Await
  try {
    const res = await axiosInstance.get(BASE_URL + LOAD_USER_ENDPOINT, {
      // Access 400 message object
      validateStatus: function (status) {
        return status < 500; // Reject only if the status code is greater than or equal to 500
      },
    });

    // Return response to action
    return res;
  } catch (error) {
    // Return error
    return error;
  }
};

// Update user profile (twitter for now)
export const updatePlayerProfile = async (twitterHandle) => {
  try {
    const res = await axiosInstance.put(
      BASE_URL + UPDATE_USER_PROFILE_ENDPOINT,
      twitterHandle
    );
    return res;
  } catch (err) {
    console.log(err);
  }
};

// Load user
const loadPlayerGameRecord = async () => {
  // Async/Await
  try {
    const res = await axiosInstance.get(BASE_URL + LOAD_PLAYER_GAME_RECORD, {
      // Access 400 message object
      validateStatus: function (status) {
        return status < 500; // Reject only if the status code is greater than or equal to 500
      },
    });

    // Return response to action
    return res;
  } catch (error) {
    // Return error
    return error;
  }
};

// Export object of service functions
const UserService = {
  registerNewPlayer,
  loginPlayer,
  loadPlayerProfile,
  updatePlayerProfile,
  loadPlayerGameRecord,
};

export default UserService;


<|start_filename|>src/components/confirmation/passwordConfirmation/passwordConfirmation.css<|end_filename|>
.mail-icon {
  font-size: 3rem;
}


<|start_filename|>src/components/_helper/validator/schema.js<|end_filename|>
import * as yup from "yup";

// REGISTRATION SCHEMA
export const registerationSchema = yup.object().shape({
  email: yup
    .string()
    .email("Check your email address")
    .required("Email is required"),
  username: yup.string().required("Username is required"),
  password: yup
    .string()
    .min(5, "Not strong enough")
    .required("Password <PASSWORD>"),
});

// LOGIN SCHEMA
export const loginSchema = yup.object().shape({
  username: yup.string().required("Username is required"),
  password: yup.string().required("Password <PASSWORD>"),
});

// FORGOT PASSWORD SCHEMA
export const forgotPasswordSchema = yup.object().shape({
  email: yup.string().email().required("Email is required"),
});

// UPDATE PROGILE
export const updateProfileSchema = yup.object().shape({
  twitterHandle: yup.string().required("🙏 Required"),
});


<|start_filename|>src/components/confirmation/welcome/welcome.css<|end_filename|>
.welcome-onboard {
  background: var(--primary-color);
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.welcome-body {
  width: 90%;
  min-height: 65%;
  border-radius: 0.125rem;
  background-color: var(--white-color);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.welcome-body--heading {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.welcome-body--heading h1 {
  color: var(--touch-color);
  font-size: 30px;
  text-transform: capitalize;
  padding: 1rem;
  text-align: center;
}

.welcome-body--heading img {
  width: 5rem;
}

.welcome-body--message {
  padding: 2rem 0;
  width: 70%;
  margin: 0 auto;
  text-align: center;
  line-height: 1.6;
}

.welcome-body--message .redirection {
  margin-top: 1rem;
}

.welcome-body--message .redirection a {
  font-weight: 700;
}

/* MEDIA QUERY */
@media (min-width: 1000px) {
  .welcome-body {
    width: 70%;
    min-height: 60%;
  }

  .welcome-body--heading {
    /* flex-direction: row; */
  }

  .welcome-body--heading h1 {
    font-size: 45px;
  }

  .welcome-body--message {
    width: 70%;
  }
}


<|start_filename|>src/components/game/sidebar/SidebarMenu.js<|end_filename|>
import React, { useEffect, useState } from "react";
import "./sidebar-menu.css";

// Image
import dummyImage from "./../../../assets/img/no-image-avatar.png";

// Fontawesome
import {
  faBorderAll,
  faSignOutAlt,
  faUserCircle,
  faUserEdit,
  faUserFriends,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { pageurl } from "../../pageurl";
import { useDispatch, useSelector } from "react-redux";
import { logOut } from "../../../redux/user/actions/user.actions";
import { comingSoon } from "../../comingSoon";

export const SidebarMenu = ({ openMenu }) => {
  const dispatch = useDispatch();
  const [playerProfile, setPlayerProfile] = useState({});
  const { user, gameRecord } = useSelector((state) => state.user);
  const { userName } = playerProfile;
  const { rank } = gameRecord || {};

  useEffect(() => {
    if (user) {
      setPlayerProfile(user);
    }
  }, [user]);

  return (
    <React.Fragment>
      <div className={`sidebar-menu ${openMenu ? "open" : "closed"}`}>
        <section className="sidebar-menu--1">
          <img src={dummyImage} alt="empty profile avatar" />
          <div className="menu-1--item">
            {userName} <br />
            <p>Rank: {rank}</p>
          </div>
        </section>
        <section className="sidebar-menu--2">
          <a className="sidebar-link" href={`#${pageurl.USER_PROFILE}`}>
            <div className="link-icon">
              <FontAwesomeIcon icon={faUserCircle} className="logout-icon" />
            </div>
            View profile
          </a>

          <a
            href={pageurl.HOMEPAGE}
            className="sidebar-link"
            // target="_blank" uncomment when there is a live update
            // rel="noopener noreferrer"
          >
            <div className="link-icon">
              <FontAwesomeIcon icon={faBorderAll} className="logout-icon" />
            </div>
            Leader Board
          </a>

          <div
            className="sidebar-link"
            // href="#"
            // target="_blank"
            // rel="noopener noreferrer"
            onClick={() => dispatch(comingSoon("Multiplayer"))}
          >
            <div className="link-icon">
              <FontAwesomeIcon icon={faUserFriends} className="logout-icon" />
            </div>
            Multi Player
          </div>

          <a className="sidebar-link" href={`#${pageurl.UPDATE_PROFILE}`}>
            <div className="link-icon">
              <FontAwesomeIcon icon={faUserEdit} className="logout-icon" />
            </div>
            Update profile
          </a>
        </section>
        <section className="sidebar-menu--3" onClick={() => dispatch(logOut())}>
          <FontAwesomeIcon icon={faSignOutAlt} className="logout-icon" />
          <span>Log out</span>
        </section>
      </div>
    </React.Fragment>
  );
};


<|start_filename|>src/components/game/music/audioplayer.css<|end_filename|>
.music-player{
    margin-bottom: 2rem;
}

.music-player svg{
    cursor: pointer;
    font-size: 2rem;
}

.audio-name{
    position: absolute;
    top: 23rem;
    white-space: nowrap;
}


@media(min-width: 900px){
    .music-player{
        text-align: center;
    }
}

<|start_filename|>src/components/user/profile/UserProfile.js<|end_filename|>
import React, { useEffect, useState } from "react";
import "./userprofile.css";
// Image
import dummyImage from "./../../../assets/img/no-image-avatar.png";
import { useSelector } from "react-redux";
import { pageurl } from "../../pageurl";
import { Link } from "react-router-dom";

export const UserProfile = () => {
  const { user, gameRecord } = useSelector((state) => state.user);
  const { userName, email, twitterHandle } = user || {};
  const { rank } = gameRecord || {};
  const [darkTheme, setDarkTheme] = useState("");
  let prefferedTheme = JSON.parse(localStorage.getItem("_dark_theme"));

  // Set user preferred theme
  useEffect(() => {
    setDarkTheme(prefferedTheme);
  }, [prefferedTheme]);

  if (!user) {
    return <h4 className="no-network">Please wait...</h4>;
  }

  return (
    <React.Fragment>
      <div className={`user ${darkTheme ? "dark" : "light-mode"}`}>
        <img src={dummyImage} alt="empty profile avatar" />
        <h4 className="user-name">{userName}</h4>
        <p className="user-twitter-handle">
          @
          {twitterHandle || (
            <Link className="text-white" to={pageurl.UPDATE_PROFILE}>
              Update twitter handle
            </Link>
          )}
        </p>
        <p className="user-email-address">{email}</p>
        <span className="user-rank">Rank: {rank}</span>
      </div>
    </React.Fragment>
  );
};


<|start_filename|>src/redux/user/actions/user.actions.js<|end_filename|>
import {
  CLEAR_SCREEN_MESSAGE,
  LOGIN_SUCCESSFULL,
  PLAYER_GAME_RECORD_LOADED,
  REGISTRATION_SUCCESSFUL,
  SET_SCREEN_MESSAGE,
  USER_LOADED,
  LOGOUT,
} from "../../types";
import UserService from "../service/user.services";

// Registration
export const register =
  ({ username, email, password }, { setSubmitting }) =>
  (dispatch) => {
    UserService.registerNewPlayer(username, email, password)
      .then((response) => {
        // handle error 400 - bad request
        if (response.status === 400) {
          dispatch({
            // Display error to the screen
            type: SET_SCREEN_MESSAGE,
            payload: {
              message: response.data.message,
              type: "danger",
            },
          });
          setSubmitting(false);
        }
        // If the registration is successful
        if (response.status === 200) {
          dispatch({
            type: REGISTRATION_SUCCESSFUL,
          });
          setSubmitting(false);
          window.location.assign("/#/welcome");
        }
      })
      .catch((error) => {
        dispatch({
          // Display other errors to the screen
          type: SET_SCREEN_MESSAGE,
          payload: error,
        });
      });
  };

// Login
export const login =
  ({ username, password }, { setSubmitting }) =>
  async (dispatch) => {
    try {
      const response = await UserService.loginPlayer(username, password);
      // handle error 400 - bad request
      if (response.status === 400) {
        dispatch({
          // Display error to the screen
          type: SET_SCREEN_MESSAGE,
          payload: {
            message: response.data.message,
            type: "danger",
          },
        });
        setSubmitting(false);
      }

      // If the login is successful
      if (response.status === 200) {
        //
        dispatch({
          type: LOGIN_SUCCESSFULL,
        });

        // Clear the current message
        dispatch({
          type: CLEAR_SCREEN_MESSAGE,
        });

        // Stop form loading state
        setSubmitting(false);

        // Store jwt to localstorage
        localStorage.setItem("jwt-token", response.data.token);

        // Redirect user to dashboard
        window.location.assign("/#/dashboard");
      }
    } catch (error) {
      dispatch({
        // Display other errors to the screen
        type: SET_SCREEN_MESSAGE,
        payload: error,
      });
    }
  };

// Load player profile
export const loadProfile = () => async (dispatch) => {
  try {
    const userProfile = await UserService.loadPlayerProfile();
    // Set user profile to redux
    if (userProfile) {
      dispatch({
        type: USER_LOADED,
        payload: userProfile.data.data[0],
      });
    }
  } catch (error) {
    console.log(error);
  }
};

// Update user profile (twitter for now)
export const updateProfile =
  (twitterHandle, { setSubmitting }) =>
  async (dispatch) => {
    try {
      const response = await UserService.updatePlayerProfile(twitterHandle);
      if (response) {
        setSubmitting(false);
        dispatch(loadProfile());
        return response;
      }
    } catch (error) {
      console.log(error);
    }
  };

// Load player game record
export const loadPlayerGameRecord = () => async (dispatch) => {
  try {
    const gameRecord = await UserService.loadPlayerGameRecord();
    // Set user profile to redux
    if (gameRecord) {
      dispatch({
        type: PLAYER_GAME_RECORD_LOADED,
        payload: gameRecord.data.data[0],
      });
    }
  } catch (error) {
    console.log(error);
  }
};

// Logout
export const logOut = () => (dispatch) => {
  dispatch({
    type: LOGOUT,
  });

  // remove token from local-storage
  localStorage.removeItem("jwt-token");

  // Redirect user to landing page
  window.location.assign("/#/");
};


<|start_filename|>src/components/game/gamearea/GameArea.js<|end_filename|>
import React, { useEffect, useState } from "react";
import "./gamearea.css";

// COMPONENTS
import { TypingBoard } from "../typingboard/TypingBoard";
import { Sidebar } from "../sidebar/Sidebar";
import { GameResult } from "../GameResult.js/GameResult";
import { Route, Switch, useHistory } from "react-router";
import { pageurl } from "../../pageurl";
import {
  loadPlayerGameRecord,
  loadProfile,
} from "../../../redux/user/actions/user.actions";
import { useDispatch, useSelector } from "react-redux";
import { UserProfile } from "../../user/profile/UserProfile";
import { UpdateProfile } from "../../user/profile/UpdateProfile";
import { WinnerAlert } from "../../winner/WinnerAlert";
import { NotifyPlayer } from "../../layouts/notification/flier-notification/Notify";
import { CLEAR_NOTIFICATION, SET_NOTIFICATION } from "../../../redux/types";

export const GameArea = () => {
  // STATE TO BE PASSED TO SIDEBAR FOR TOGGLE
  let prefferedTheme = JSON.parse(localStorage.getItem("_dark_theme"));
  const [darkTheme, setDarkTheme] = useState(prefferedTheme);
  const dispatch = useDispatch();
  const history = useHistory();
  const { user } = useSelector((state) => state.user);
  const { twitterHandle } = user || {};

  // Get user jwt token
  const token = localStorage.getItem("jwt-token");

  // Set user preferred theme
  useEffect(() => {
    setDarkTheme(prefferedTheme);
  }, [prefferedTheme]);

  // Load user profile
  useEffect(() => {
    dispatch(loadProfile());
    dispatch(loadPlayerGameRecord());
  }, [dispatch]);

  // Notify user to update profile
  useEffect(() => {
    if (user && !twitterHandle) {
      dispatch({
        type: SET_NOTIFICATION,
        payload: {
          message: `your profile with your twitter handle to get more followers when you reach `,
          url: pageurl.UPDATE_PROFILE,
          urlLabel: "update",
          moreUrl: {
            url1: pageurl.HOMEPAGE,
            url1Label: "top 10 players.",
          },
        },
      });
    } else {
      dispatch({
        type: CLEAR_NOTIFICATION,
      });
    }
  }, [twitterHandle, user, dispatch]);

  // redirect to login page if not authenticated
  if (!token) {
    history.push(pageurl.LOGIN);
  }

  return (
    <React.Fragment>
      <WinnerAlert />
      <NotifyPlayer />
      <main className={`game-container ${darkTheme ? "dark" : "light-mode"}`}>
        <Switch>
          <Route exact path={pageurl.GAME_RESULT} component={GameResult} />
          <Route exact path={pageurl.DASHBOARD} component={TypingBoard} />
          <Route exact path={pageurl.USER_PROFILE} component={UserProfile} />
          <Route
            exact
            path={pageurl.UPDATE_PROFILE}
            component={UpdateProfile}
          />
        </Switch>
      </main>
      <Sidebar themeCallback={setDarkTheme} />
    </React.Fragment>
  );
};


<|start_filename|>src/components/game/sidebar/sidebar-menu.css<|end_filename|>
/* @media (min-width: 300px) { */
.sidebar-menu.open {
  display: flex;
}

.sidebar-menu {
  position: absolute;
  z-index: 999;
  background: rgba(74, 21, 75, 1) !important;
  bottom: 0;
  left: 129px;
  height: 80%;
  width: 20rem;
  padding: 1rem;
  border-top-right-radius: 0.5rem;
  flex-direction: column;
  justify-content: space-between;
  border: 1px solid var(--white-color);
  display: none;
}

.sidebar-menu--1 {
  display: flex;
  border-bottom: 1px solid var(--white-color);
  padding: 0.9rem 0;
  text-transform: capitalize;
}

.sidebar-menu--1 img {
  width: 3rem;
  cursor: pointer;
  margin-right: 1rem;
}

.sidebar-menu--2 {
  display: flex;
  flex-direction: column;
}

.sidebar-menu--2 .sidebar-link {
  color: var(--grey-color);
  text-decoration: none;
  line-height: 2.5;
  text-transform: capitalize;
  font-weight: 600;
  font-size: 0.9rem;
  display: flex;
  margin-bottom: 1rem;
  cursor: pointer;
}

.sidebar-menu--2 .sidebar-link:hover {
  color: var(--white-color);
}

.sidebar-menu--2 .link-icon {
  width: 3rem;
}

.sidebar-menu--2 svg {
  margin-right: 2rem;
  font-size: 1.5rem;
}

.sidebar-menu--3 {
  display: flex;
  align-items: center;
  cursor: pointer;
  border-top: 1px solid var(--white-color);
  padding: 1rem 0;
}

.sidebar-menu--3 .logout-icon {
  font-size: 1.5rem;
  margin-right: 0.4rem;
}

.sidebar-menu--3 span {
  font-weight: 600;
  font-size: 0.9rem;
  text-transform: capitalize;
  margin-right: 2rem;
}
/* } */


<|start_filename|>src/components/layouts/navbar/FormNavbar.js<|end_filename|>
import React from "react";
import { pageurl } from "../../pageurl";
import { Button } from "../button/Button";
import "./formnavbar.css";

export const FormNavbar = ({ loginPage }) => {
  return (
    <React.Fragment>
      <header className="formnavbar-header">
        {/* <div className="navbar--brand">
                    <h1><code>&lt;/ Typing&gt;</code></h1>
                </div> */}
        <nav className="form-navbar">
          {/* LOGIN BUTTON */}

          {loginPage ? (
            <Button
              label="Create a new account"
              linkUrl={pageurl.REGISTER}
              look="custom--btn-touch new-account-btn link-btn"
            />
          ) : (
            <Button
              label="Start Typing"
              linkUrl={pageurl.LOGIN}
              look="custom--btn-touch login-btn link-btn"
            />
          )}

          {/* HOME BUTTON */}
          <Button
            label="Learder Board"
            linkUrl={pageurl.HOMEPAGE}
            look="custom--btn-outline-primary explore-btn link-btn"
          />
        </nav>
      </header>
    </React.Fragment>
  );
};


<|start_filename|>src/components/homepage/social-media-share/ShareButtons.js<|end_filename|>
import React, { useState } from "react";
import "./share-buttons.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
  faFacebookF,
  faLinkedinIn,
  faTwitter,
} from "@fortawesome/free-brands-svg-icons";
import { faClipboard } from "@fortawesome/free-solid-svg-icons";
import { copyToClipBoard } from "../../_helper/clipBoard/copyToClipBoard";

export const ShareButtons = () => {
  const [copied, setCopied] = useState(false);

  const handleCopy = () => {
    // get the input that conatins the caption
    const copyText = document.querySelector(".media-caption");
    // invoke the copy function
    copyToClipBoard(copyText);
    setCopied(true);
  };
  return (
    <React.Fragment>
      <section className="social-media-share">
        <h1>Help Us Reach More Audience.</h1>
        <div>
          <input
            className="media-caption"
            value="Checkout developer typing game by @unclebigbay143 on https://developer-typing-game.netlify.app/#/"
            hidden
            readOnly
          />
          <abbr title="Copy to clipboard" onClick={() => handleCopy()}>
            <FontAwesomeIcon
              icon={faClipboard}
              className={`${copied && "copied"}`}
            />
          </abbr>
          <a
            href="https://www.facebook.com/sharer/sharer.php?u=https://developer-typing-game.netlify.app/"
            target="_blank"
            rel="noopener noreferrer"
          >
            <abbr title="Share to facebook">
              <FontAwesomeIcon icon={faFacebookF} />
            </abbr>
          </a>
          <a
            className="twitter-share-button"
            target="_blank"
            rel="noopener noreferrer"
            data-size="large"
            href="https://twitter.com/intent/tweet?text=Checkout developer typing game by @unclebigbay143 on https://developer-typing-game.netlify.app/#/"
          >
            <abbr title="Make a tweet about us">
              <FontAwesomeIcon icon={faTwitter} />
            </abbr>
          </a>
          <a
            href="https://www.linkedin.com/sharing/share-offsite/?url=https://developer-typing-game.netlify.app/"
            target="_blank"
            rel="noopener noreferrer"
          >
            <abbr title="Share on LinkedIn">
              <FontAwesomeIcon icon={faLinkedinIn} />
            </abbr>
          </a>
        </div>
      </section>
    </React.Fragment>
  );
};


<|start_filename|>src/components/homepage/top-players/top-players.css<|end_filename|>
.rank-section {
  margin-top: 120px;
  padding-bottom: 160px;
  max-width: 62.875rem;
  margin-left: auto;
  margin-right: auto;
}

/* Loading state style */
.rank-section.loading {
  color: var(--white-color);
  display: flex;
  justify-content: center;
  align-items: center;
  height: 60vh;
}

.rank-section.rank-section.loading svg {
  font-size: 3rem;
}

/*  */

.welcome-user {
  display: flex;
  justify-content: center;
  align-items: center;
  /* border-bottom: 4px solid var(--touch-color); */
  background-color: var(--primary-color);
  color: var(--white-color);
  padding-bottom: 2rem;
}

.waving-hand {
  display: none;
}

.greeting-text {
  font-size: 1.9rem;
  display: block;
  text-align: center;
}

.rank-board {
  background-color: var(--white-color);
  border-top: 4px solid var(--touch-color);
  border-radius: 0.23rem;
  padding-bottom: 1rem;
}

.rank-board--heading {
  padding: 1rem;
  color: var(--touch-color);
  background-color: #ecdeec;
  font-size: 1.125rem;
}

.top-player {
  padding: 1rem;
}

.top-player .left-info {
  display: flex;
  align-items: center;
}

.right-info {
  margin-top: 0.95256rem;
}

.right-info .button {
  width: 100%;
  font-size: 14px;
  font-weight: 700;
  background-color: var(--primary-color);
}

.right-info .button:hover {
  box-shadow: inset 0 0 0 1px var(--white-color);
}

.top-player--image {
  height: 75px;
  width: 75px;
}

.top-player--image img {
  border-radius: 5px;
  height: 100%;
}

.player-information {
  margin-left: 1rem;
  white-space: nowrap;
}

.player-information .player-name {
  color: var(--touch-color);
  color: var(--primary-color);
  text-transform: capitalize;
}

.player-information .player-details {
  display: flex;
  align-items: flex-end;
}

.player-details .player-star {
  margin-right: 1rem;
}

.player-details .score-time {
  font-weight: 600;
  color: #696969;
  color: var(--primary-color);
  font-size: 0.775rem;
  line-height: 20px;
  opacity: 0.7;
}

.player-star svg {
  color: #cccccc;
}

.player-star svg.checked-rank {
  color: orange;
}

.board-toggler {
  text-align: center;
}

.board-toggler button {
  padding: 0.75rem 1rem;
}

@media (min-width: 900px) {
  .rank-section {
    margin-top: 50px;
  }

  .waving-hand {
    /* font-size: 2.9rem; */
    display: inline;
  }

  .top-player {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .right-info {
    margin-top: 0.256rem;
  }
}


<|start_filename|>src/components/homepage/announcementCircle/announcement-circle.css<|end_filename|>
.announcement-circle {
  position: relative;
  top: 100px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: auto;
  min-height: 90px;
  max-width: 81.25rem;
  padding: 0 20px;
  margin-top: -80px;
  margin-left: auto;
  margin-right: auto;
  background-color: var(--touch-color);
  color: var(--white-color);
  transition: 3s all;
  margin-bottom: 160px;
}

.dark.home .announcement-circle {
  background-color: var(--primary-color);
}

.announcement-circle.close-circle {
  display: none;
}

.announcement-circle--content {
  display: block;
}

.announcement-circle h1 {
  font-size: 0.93rem;
  font-weight: 600;
  letter-spacing: 1px;
}

.lets-go {
  display: flex;
  justify-content: center;
  transition: 0.6s ease;
}

.lets-go:hover {
  padding-left: 0.5rem;
}

.lets-go a {
  display: none;
}

.lets-go-icon {
  display: none;
}

.announcement-circle--close {
  display: none;
}

@media (min-width: 900px) {
  .announcement-circle--content {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
    padding: 0 1rem;
  }
  .lets-go {
    align-items: center;
    width: 100px;
    cursor: pointer;
  }

  .lets-go-icon {
    margin-left: 0.4rem;
    margin-bottom: 0.2rem;
    display: block;
  }

  .lets-go a {
    display: block;
    color: var(--white-color);
    font-weight: 700;
    text-decoration: none;
    border-bottom: 1px solid var(--white-color);
    padding-bottom: 0.2rem;
  }
}

@media (min-width: 1100px) {
  .announcement-circle {
    padding: 0 100px;
    border-radius: 3.125rem;
    min-height: 80px;
  }

  .announcement-circle--content {
    display: flex;
    justify-content: unset;
    gap: 10px;
  }

  .announcement-circle--close {
    display: block;
    font-size: 20px;
    font-weight: 600;
    cursor: pointer;
  }

  .announcement-circle--close:hover {
    transform: scale(1.1);
  }
}


<|start_filename|>src/redux/game/service/game.service.js<|end_filename|>
import axiosInstance from "../../../axios";
import {
  BASE_URL,
  UPDATE_GAME_RECORD,
} from "../../user/service/root-endpoints";

// Update player's game
const updatePlayerGameRecord = async (wpm, accuracy) => {
  const payload = {
    wpm,
    accuracy,
  };
  try {
    const response = await axiosInstance.put(
      BASE_URL + UPDATE_GAME_RECORD,
      payload
    );

    console.log(response);
  } catch (error) {
    console.log(error);
  }
};

const GameService = {
  updatePlayerGameRecord,
};

export default GameService;


<|start_filename|>src/redux/store.js<|end_filename|>
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./rootReducer";

const middleware = [thunk];

//  Middleware to use when in development mode (redux dev tool)
const devCompose = compose(
  applyMiddleware(...middleware),
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

// Middleware to apply use when in production mode (redux dev tool causing issues)
const prodCompose = compose(applyMiddleware(...middleware));

// Check the node environment status and apply compose accordingly
const useCompose =
  process.env.NODE_ENV === "production" ? prodCompose : devCompose;

// Store instance
const store = createStore(rootReducer, useCompose);

export default store;


<|start_filename|>src/components/game/sidebar/sidebar.css<|end_filename|>
.sidebar {
  background-color: var(--touch-color);
  height: 100%;
  position: absolute;
  top: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 1rem;
  color: var(--grey-color);
}

.custom-pt-5.sidebar {
  padding-top: 5rem;
}

.select-pro-language select {
  border-radius: 0.4rem;
  text-transform: capitalize;
  border: 1px solid var(--touch-color);
  outline: none;
  font-family: var(--poppins);
  cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--white-color);
  padding: 0.125rem;
}

option {
  font-size: 0.9rem;
}

.sidebar-items-top {
  width: 100%;
}

.navigation-icon {
  margin-top: 6rem;
  padding-right: 0.5rem;
  text-align: right;
}

.navigation-icon a {
  color: var(--white-color);
}

.navigation-icon svg {
  font-size: 2rem;
  cursor: pointer;
}

.theme-toggle {
  margin-bottom: 2rem;
}

.theme-toggle svg {
  cursor: pointer;
  font-size: 2rem;
}

.profile-image {
  width: 3rem;
  cursor: pointer;
}

.profile-image img {
  display: block;
  border-radius: 3rem;
  width: 100%;
  height: 100%;
}

.lift.profile-image img {
  filter: drop-shadow(0px 10px 3px white);
}

@media (min-width: 900px) {
  .sidebar {
    overflow: unset;
  }
  .navigation-icon {
    margin-top: 3rem;
  }
  .theme-toggle {
    text-align: center;
  }

  .profile-image,
  .sidebar-items-down {
    align-self: flex-end;
  }
}


<|start_filename|>src/components/authentication/register/Registration.js<|end_filename|>
// React
import React from "react";
import { useDispatch } from "react-redux";

// Formik
import { ErrorMessage, Field, Form, Formik } from "formik";
import { registerationSchema } from "../../_helper/validator/schema";

// Components
import { FormNavbar } from "../../layouts/navbar/FormNavbar";
import typeWriter from "./../../../assets/img/type-writer.svg";

// Action
import { register } from "../../../redux/user/actions/user.actions";

// Css
import "./registration.css";
import { pageurl } from "../../pageurl";
import { useHistory } from "react-router";

export const Registration = () => {
  const dispatch = useDispatch();
  const history = useHistory();

  // Get user jwt token
  const token = localStorage.getItem("jwt-token");

  // Redirect authenticated users
  if (token) {
    history.push(pageurl.DASHBOARD);
  }
  return (
    <React.Fragment>
      <FormNavbar />
      <section className="registration">
        <Formik
          initialValues={{
            username: "",
            password: "",
            email: "",
          }}
          // Yup should validate form
          validationSchema={registerationSchema}
          // Handle form submission
          onSubmit={(values, action) => {
            // Send credentials to backend
            dispatch(register(values, action));
          }}
        >
          {({ isSubmitting }) => (
            <Form>
              <div className="form-heading">
                <h1>Create new account</h1>
              </div>
              <div className="input-wrapper">
                <div className="input-heading">
                  <div className="input-label">
                    <label htmlFor="email">Email</label>
                  </div>
                  <ErrorMessage
                    className="error-message"
                    name="email"
                    component="div"
                  />
                </div>
                <Field
                  type="email"
                  name="email"
                  id="email"
                  placeholder="Enter your email"
                />
              </div>
              <div className="input-wrapper">
                <div className="input-heading">
                  <div className="input-label">
                    <label htmlFor="username">Username</label>
                  </div>
                  <ErrorMessage
                    className="error-message"
                    name="username"
                    component="div"
                  />
                </div>

                <Field
                  type="text"
                  name="username"
                  id="username"
                  placeholder="Create username"
                />
              </div>
              <div className="input-wrapper">
                <div className="input-heading">
                  <div className="input-label">
                    <label htmlFor="password">Password</label>
                  </div>
                  <ErrorMessage
                    className="error-message"
                    name="password"
                    component="div"
                  />
                </div>
                <Field
                  type="password"
                  name="password"
                  id="password"
                  placeholder="<PASSWORD>"
                  autoComplete="on"
                />
              </div>
              <div className="input-wrapper">
                <button
                  type="submit"
                  className="custom--btn"
                  disabled={isSubmitting}
                >
                  {isSubmitting ? "Working on it..." : "Get Started"}
                </button>
              </div>
            </Form>
          )}
        </Formik>

        <div className="registration-image">
          {/* social media signup layout goes well here in case you want to add it, import share button here */}
          <img
            className="type-writer"
            data-aos="zoom-in"
            src={typeWriter}
            alt="two people with typewriter"
          />
        </div>
      </section>
    </React.Fragment>
  );
};


<|start_filename|>src/redux/user/service/root-endpoints.js<|end_filename|>
export const BASE_URL = process.env.REACT_APP_BASE_URL;
export const REGISTER = "/user/register";
export const LOGIN = "/user/login";
export const LOAD_USER_ENDPOINT = "/players/profile";
export const UPDATE_USER_PROFILE_ENDPOINT = "/players/profile/update";
export const LOAD_ALL_PLAYERS = "/players/all";
export const RANK_PLAYERS = "/players/rank";
export const LOAD_PLAYER_GAME_RECORD = "/players/game-record";
export const UPDATE_GAME_RECORD = "/games/update";


<|start_filename|>src/App.css<|end_filename|>
@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,900;1,200;1,300;1,400;1,500;1,600;1,800;1,900&display=swap");

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

:root {
  --poppins: "Poppins", sans-serif;
  --touch-color: #4a154b;
  --primary-color: #2696e8;
  /* --primary-color: #4A154B;
    --touch-color: #2696E8; */
  --orange-color: orange;
  --black-color: #000000;
  --white-color: #ffffff;
  --grey-color: #cccccc;
  --green-color: rgba(4, 189, 101, 1);
  --light-blue-color: rgba(59, 130, 246, 0.5);
  --warning-color: rgba(255, 101, 78, 1);
}


<|start_filename|>src/components/game/gamearea/gamearea.css<|end_filename|>
.game-container {
  height: 100vh;
  max-height: 100vh;
  overflow: hidden;
  padding: 10rem 6vw;
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: var(--poppins);
  background-color: var(--white-color);
  transition: 0.5s ease;
  /* background: linear-gradient(394deg, var(--touch-color), transparent); */
}

.dark.game-container {
  background: var(--touch-color);
}

@media (max-width: 900px) {
  .game-container {
    background-color: var(--touch-color);
  }
}


<|start_filename|>src/components/game/performance/PlayerPerformance.js<|end_filename|>
import { faStar } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useState } from "react";
import { useSelector } from "react-redux";
import "./playerperformance.css";

export const PlayerPerformance = ({ currentGameWpm, currentGameAccuracy }) => {
  const [togglePerformance, setTogglePerformance] = useState(false);
  const { notification } = useSelector((state) => state.user);

  const { gameRecord } = useSelector((state) => state.user);
  const { rank, wpm, accuracy } = gameRecord || {};
  return (
    <React.Fragment>
      <section
        className={`typist-performance 
        ${notification && "custom-mt-4"}  
        ${togglePerformance && "collapse-typist-performance"}`}
        onClick={() => setTogglePerformance(!togglePerformance)}
      >
        <div className="rank-info">
          <FontAwesomeIcon icon={faStar} />
          <span className="position">{rank || "0"}</span>
        </div>
        <div className="current-performance">
          <span className="wpm">CPM: {currentGameWpm} </span> |{" "}
          <span className="accuracy"> ACC: {currentGameAccuracy}%</span>
        </div>
        <div
          className={`full-performance ${
            togglePerformance && "display-full-performance"
          }`}
        >
          <p>CPM: {wpm}</p>
          <p>ACCURACY: {accuracy}%</p>
        </div>
      </section>
    </React.Fragment>
  );
};


<|start_filename|>src/components/authentication/login/Login.js<|end_filename|>
import { ErrorMessage, Field, Form, Formik } from "formik";
import React, { useState } from "react";
import "./login.css";
import typeWriter from "./../../../assets/img/type-writer.svg";
import { loginSchema } from "../../_helper/validator/schema";
import { FormNavbar } from "../../layouts/navbar/FormNavbar";
import { Link, useHistory } from "react-router-dom";
import { login } from "../../../redux/user/actions/user.actions";
import { useDispatch } from "react-redux";
import { pageurl } from "../../pageurl";

export const Login = () => {
  const dispatch = useDispatch();
  const [nextStep, setnextStep] = useState("Password");
  const history = useHistory();

  // Get user jwt token
  const token = localStorage.getItem("jwt-token");

  // Redirect authenticated users
  if (token) {
    history.push(pageurl.DASHBOARD);
  }

  return (
    <React.Fragment>
      <FormNavbar loginPage={true} />
      <section className="login">
        <Formik
          initialValues={{
            username: "",
            password: "",
          }}
          // Yup should validate form
          validationSchema={loginSchema}
          // Handle form submission
          onSubmit={(values, action) => {
            // Send credentials to backend
            dispatch(login(values, action));
          }}
        >
          {({ isSubmitting }) => (
            <Form>
              <div className="form-heading">
                <h1>Login your account</h1>
              </div>
              <div className="input-wrapper">
                <div className="input-heading">
                  <div className="input-label">
                    <label htmlFor="username">Username</label>
                  </div>

                  <ErrorMessage
                    className="error-message"
                    name="username"
                    component="div"
                  />
                </div>

                <Field
                  type="text"
                  name="username"
                  id="username"
                  placeholder="What is your username?"
                />
              </div>
              <div className="input-wrapper">
                <div className="input-heading">
                  <div className="input-label">
                    <label htmlFor="password">Password</label>
                  </div>

                  <ErrorMessage
                    className="error-message"
                    name="password"
                    component="div"
                  />
                </div>
                <Field
                  type="password"
                  name="password"
                  id="password"
                  onClick={() => setnextStep("Now enter your password")}
                  placeholder={`${nextStep}`}
                  autoComplete="on"
                />
              </div>
              <div className="input-wrapper">
                <button
                  className="custom--btn"
                  type="submit"
                  disabled={isSubmitting}
                >
                  {isSubmitting ? "Please wait..." : "Login"}
                </button>
                <div className="forgot-password">
                  <Link to="reset-password">I forgot my password 😫</Link>
                </div>
              </div>
            </Form>
          )}
        </Formik>

        <div className="login-image" data-aos="zoom-in">
          <img
            className="type-writer"
            src={typeWriter}
            alt="two people with typewriter"
          />
        </div>
      </section>
    </React.Fragment>
  );
};


<|start_filename|>src/components/homepage/social-media-share/share-buttons.css<|end_filename|>
.social-media-share {
  text-align: center;
  padding-bottom: 3rem;
}

.social-media-share h1 {
  color: var(--white-color);
  font-size: 1.1rem;
  font-weight: 500px;
}

.social-media-share svg {
  color: var(--white-color);
  font-size: 1.4rem;
  margin: 20px;
  cursor: pointer;
}

.social-media-share .copied {
  color: var(--green-color);
}

@media (min-width: 900px) {
  .social-media-share h1 {
    font-size: 1.3rem;
  }

  .social-media-share svg {
    font-size: 1.7rem;
  }
}


<|start_filename|>src/components/confirmation/welcome/Welcome.js<|end_filename|>
// React
import React from "react";

// Css
import "./welcome.css";

// Component
import wavingHand from "./../../../assets/img/waving-hand.gif";
import { pageurl } from "../../pageurl";
import { Link } from "react-router-dom";

export const Welcome = () => {
  return (
    <React.Fragment>
      <div className="welcome-onboard">
        <div className="welcome-body">
          <section className="welcome-body--heading">
            <h1>Welcome onboard</h1>
            <img src={wavingHand} alt="waving hand" />
          </section>
          <section className="welcome-body--message">
            <p>
              we are happy to have you join us, a welcome{" "}
              <strong>message</strong> has been sent to your registered mail box
            </p>

            <p className="redirection">
              Continue to <Link to={pageurl.LOGIN}>Login</Link>
            </p>
          </section>
        </div>
      </div>
    </React.Fragment>
  );
};


<|start_filename|>src/components/user/profile/updateprofile.css<|end_filename|>
.update-profile {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.update-profile form {
  width: 60%;
}
.update-profile .form-heading {
  color: var(--white-color);
  line-height: 4;
  text-transform: uppercase;
}

.update-profile input {
  margin: 0.5rem 0 1rem 0;
  padding: 12px;
  height: 44px;
  width: 100%;
  padding-bottom: 13px;
  font-size: 0.987rem;
  line-height: 1.33333333;
  border-radius: 4px;
  border: 2px solid var(--white-color);
  font-family: var(--poppins);
}

.update-profile label {
  color: var(--white-color);
  font-size: 1.5rem;
  margin-bottom: 0rem;
  line-height: 0;
  padding-bottom: 0;
}

.update-profile button {
  width: 100%;
  font-weight: 700;
  font-size: 1rem;
  padding: 0.75rem 1rem;
}

.update-profile .error-message {
  font-size: 0.78rem;
  text-align: right;
  color: var(--white-color);
  font-weight: 600;
  position: relative;
  /* top: -20px; */
}

/* light mode */

.light-mode.update-profile * {
  color: var(--touch-color);
}

.light-mode.update-profile input {
  border: 1px solid var(--touch-color);
}

.light-mode.update-profile input:disabled {
  background-color: var(--grey-color);
}

.light-mode.update-profile button {
  background-color: var(--touch-color);
  color: var(--white-color);
}

.light-mode.update-profile button:hover {
  box-shadow: inset 0 0 0 1px var(--white-color);
}


<|start_filename|>src/components/layouts/navbar/formnavbar.css<|end_filename|>
.formnavbar-header {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 2vh 7.3vw;
  position: absolute;
  z-index: 999;
  width: 100%;
  top: 0;
  left: 0;
  background-color: var(--white-color);
}

.formnavbar-header .navbar--brand {
  color: var(--touch-color);
  font-size: 0.7rem;
}

.form-navbar button:first-child {
  margin-right: 0.67rem;
}

@media (max-width: 900px) {
  .form-navbar {
    width: 100%;
    display: flex;
    justify-content: space-between;
  }
}

@media (max-width: 400px) {
  .new-account-btn,
  .login-btn {
    font-size: 0.66rem;
  }

  .explore-btn {
    font-size: 0.6rem;
  }
}


<|start_filename|>src/components/game/GameResult.js/GameResult.js<|end_filename|>
import { faTwitter } from "@fortawesome/free-brands-svg-icons";
import { faReply } from "@fortawesome/free-solid-svg-icons";
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { useHistory } from "react-router";
import { RegularButton } from "../../layouts/button/Button";
import { pageurl } from "../../pageurl";
import "./gameresult.css";

export const GameResult = () => {
  const { wpm, accuracy } = useSelector((state) => state.game);
  // STATE TO BE PASSED TO SIDEBAR FOR TOGGLE
  let prefferedTheme = JSON.parse(localStorage.getItem("_dark_theme"));
  const [darkTheme, setDarkTheme] = useState(prefferedTheme);
  const history = useHistory();

  // Set user preferred theme
  useEffect(() => {
    setDarkTheme(prefferedTheme);
  }, [prefferedTheme]);

  if (!wpm && !accuracy) {
    history.push(pageurl.DASHBOARD);
  }
  return (
    <React.Fragment>
      <div className={`result-container ${darkTheme ? "dark" : "light-mode"}`}>
        {/*  */}
        <section className="">
          <div className="result-heading">
            <h1>Typing Result 😀</h1>
          </div>
        </section>

        {/* SCORE POINTS     */}
        <section className="result-body">
          <div className="heading">
            <span>CPM</span>
            <span>ACCURACY</span>
          </div>
          <div className="point-heading">
            <span>{wpm}</span>
            <span>{accuracy}%</span>
          </div>
        </section>

        {/*  */}
        <section className="share-point">
          <RegularButton
            type="custom--btn-outline twitter-share-button"
            linkUrl={`#${pageurl.DASHBOARD}`}
            icon={faReply}
            label="Play Again"
          />
          <RegularButton
            type="custom--btn-outline twitter-share-button"
            target="_blank"
            rel="noopener noreferrer"
            linkUrl={`https://twitter.com/intent/tweet?text=I just scored ${wpm}cpm and had ${accuracy} accuracies on developers typing game website developed by @unclebigbay143 @hashnode @harperdbio 
            
            
            Check out how fast your coding speed is on https://developer-typing-game.netlify.app/`}
            icon={faTwitter}
            label="Tweet"
            abbrTitle="Share your achievement"
          />
        </section>
      </div>
    </React.Fragment>
  );
};


<|start_filename|>src/components/layouts/notification/popnotify/PopNotify.js<|end_filename|>
import React, { useState, useEffect } from "react";
import { faCheck, faTimes } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import "./popnotify.css";
import { useDispatch, useSelector } from "react-redux";
import { CLEAR_SCREEN_MESSAGE } from "../../../../redux/types";

// Generate icon based on message Type
const iconPicker = (messageType) => {
  // Set notification icon
  switch (messageType) {
    case "success":
      return faCheck;
    case "danger":
      return faTimes;
    default:
      break;
  }
};

export const PopNotify = () => {
  const dispatch = useDispatch();

  // Pull out screenMessage from user reducer
  const { screenMessage } = useSelector((state) => state.user);

  // Component state for screen message
  const [currentMessage, setCurrentMessage] = useState(null);

  // Pull out message and message-type from currentMessage
  const { message, type } = currentMessage || {};

  // Run whenever there is a message from redux
  useEffect(() => {
    // Set message from redux to the component state for screen message
    if (screenMessage.message) setCurrentMessage(screenMessage);
  }, [screenMessage.message, screenMessage]);

  // Handle the screenMessage timeout
  useEffect(() => {
    // delay time in seconds
    const duration = 5000;
    // start the counter when there is a message on screen
    const screenDelay =
      currentMessage &&
      setTimeout(() => {
        dispatch({
          // Remove screen message from redux
          type: CLEAR_SCREEN_MESSAGE,
        });
      }, duration);
    return () => {
      // Remove setTimeout
      clearTimeout(screenDelay);
    };
  }, [dispatch, currentMessage]);

  // Clear screen message from redux on user click
  const handleClose = () => {
    dispatch({
      type: CLEAR_SCREEN_MESSAGE,
    });
  };
  // If no screen message display nothing
  if (!screenMessage.message) return null;
  return (
    <React.Fragment>
      <section className={`pop-notifier ${type}`} onClick={() => handleClose()}>
        {/* Only render icon when there is a type - solve null error message on console*/}
        {type && <FontAwesomeIcon icon={iconPicker(type)} />}
        {message}
      </section>
    </React.Fragment>
  );
};


<|start_filename|>src/components/layouts/button/Button.js<|end_filename|>
import React from "react";
import PropTypes from "prop-types";
import "./button.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Link } from "react-router-dom";

export const Button = (props) => {
  const { icon, label, look, size, linkUrl, func, abbrTitle } = props;
  return (
    <React.Fragment>
      <button className={`button custom--btn ${look} ${size}`} onClick={func}>
        {linkUrl && (
          <abbr title={abbrTitle}>
            <Link to={linkUrl}>
              {" "}
              {icon && <FontAwesomeIcon icon={icon} />} {label}
            </Link>
          </abbr>
        )}
      </button>
    </React.Fragment>
  );
};

export const RegularButton = (props) => {
  const { icon, label, look, size, linkUrl, func, abbrTitle, target } = props;
  return (
    <React.Fragment>
      <button className={`button custom--btn ${look} ${size}`} onClick={func}>
        <abbr title={abbrTitle}>
          <a href={linkUrl} target={target}>
            {" "}
            {icon && <FontAwesomeIcon icon={icon} />} {label}
          </a>
        </abbr>
      </button>
    </React.Fragment>
  );
};

Button.propTypes = {
  label: PropTypes.string,
  look: PropTypes.string,
  size: PropTypes.string,
  func: PropTypes.func,
};


<|start_filename|>src/components/layouts/notification/overheadnotify/overheadnotify.css<|end_filename|>
.over-head-notification{
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 1.256rem;
    padding: 0.4234rem 4vw;
}


.over-head-notification .social-media--follow a{
    color: var(--primary-color);
    margin-left: 2rem;
}


@media(min-width: 900px){
    .over-head-notification{
        justify-content: flex-end;
    }
    
}

<|start_filename|>src/components/game/typingboard/TypingBoard.js<|end_filename|>
import React, { useEffect, useState } from "react";
import "./typingboard.css";
import useKeyPress from "../../../hooks/useKeyPress";
import { codeQuotes } from "./codeQuotes";
import { currentTime } from "../../_helper/time/time";
import { PlayerPerformance } from "../performance/PlayerPerformance";
import { smileyMode } from "./smileyMode";
import { pageurl } from "../../pageurl";
import { useHistory } from "react-router";
import { updatePlayerGameRecord } from "../../../redux/game/actions/game.action";
import { useDispatch, useSelector } from "react-redux";

export const TypingBoard = () => {
  const { javascript } = codeQuotes;
  const { notification } = useSelector((state) => state.user);
  const history = useHistory();
  const dispatch = useDispatch();
  const [preferredLanguage, setPreferredLanguage] = useState(javascript);
  const [outgoingChars, setOutgoingChars] = useState("");
  const [currentCharBlockIndex, setCurrentCharBlockIndex] = useState(0);
  const [leftPadding, setLeftPadding] = useState(
    new Array(5).fill(" ").join("")
  );
  const [currentChar, setCurrentChar] = useState(
    preferredLanguage[currentCharBlockIndex].charAt(0)
  );
  const [incomingChars, setIncomingChars] = useState(
    preferredLanguage[currentCharBlockIndex].substr(1)
  );
  const [startTime, setStartTime] = useState();
  const [wordCount, setWordCount] = useState(0);
  const [wpm, setWpm] = useState(0);
  const [accuracy, setAccuracy] = useState(0);
  const [typedChars, setTypedChars] = useState("");
  const [darkTheme, setDarkTheme] = useState("");
  let prefferedTheme = JSON.parse(localStorage.getItem("_dark_theme"));

  // Count down
  const [timeRemaining, setTimeRemaining] = useState(60);
  const [isTimeRunning, setIsTimeRunning] = useState(false);

  // Set user preferred theme
  useEffect(() => {
    setDarkTheme(prefferedTheme);
  }, [prefferedTheme]);

  useKeyPress((key) => {
    // 1 TEMPORARY HOLDER FOR LATER USE
    let updatedOutgoingChars = outgoingChars;
    let updatedIncomingChars = incomingChars;

    //2 - ENSURES THE USER ENTERS THE CORRECT KEYWORD BEFORE NEXT
    if (key === currentChar) {
      //3
      if (leftPadding.length > 0) {
        setLeftPadding(leftPadding.substring(10));
      }

      //4
      updatedOutgoingChars += currentChar;
      setOutgoingChars(updatedOutgoingChars);

      //5
      setCurrentChar(incomingChars.charAt(0));

      //6
      updatedIncomingChars = incomingChars.substring(1);
      // if (updatedIncomingChars.split(' ').length === 1) {
      if (updatedIncomingChars.length === 20) {
        updatedIncomingChars += " " + nextCode(preferredLanguage);
      }

      setIncomingChars(updatedIncomingChars);
    }

    // 1 -START TIME WHEN THE USER BEGINS TO TYPE
    if (!startTime) {
      // Set the typing start time
      setStartTime(currentTime());
      // Start the count down
      setIsTimeRunning(true);
    }

    /* WPM LOGIC */

    //2 - IF THE USER HIT THE CORRECT BAR SPACE
    if (incomingChars.charAt(0) === " ") {
      //4 - INCREASE THE WORD COUNT
      setWordCount(wordCount + 1);

      //5 - TIME SPENT TYPING
      const durationInMinutes = (currentTime() - startTime) / 60000.0;

      //6 // SET WPM
      setWpm(((wordCount + 1) / durationInMinutes).toFixed(2));
    }

    /* ACCURACY LOGIC */

    //1 -ADD ALL PRESSED KEYS
    const updatedTypedChars = typedChars + key;
    setTypedChars(updatedTypedChars);

    //3 -DIVIDE THE OUTGOING CHARACTERS WITH THE TYPED CHARACTERS
    setAccuracy(
      ((updatedOutgoingChars.length * 100) / updatedTypedChars.length).toFixed(
        2
      )
    );
  });

  // FUNCTION THAT GETS THE NEXT CODE FROM THE ARRAY
  const nextCode = (array) => {
    // ONLY RUN IF THERE IS MORE CODE
    if (
      currentCharBlockIndex >= 0 &&
      currentCharBlockIndex < array.length - 1
    ) {
      // GET THE NEXT CODE ITEM
      const nextItem = array[currentCharBlockIndex + 1];

      // UPDATE THE setCurrentCharBlockIndex WITH THE CURRENT ITEM INDEX
      setCurrentCharBlockIndex(currentCharBlockIndex + 1);

      return nextItem;
    }

    // RETURN EMPTY STRING WHEN THE ARRAY IS ZERO INSTEAD OF FUNCTION DEFAULT UNDEFINED
    return "";
  };

  useEffect(() => {
    // HANDLE GAME TIMING
    if (isTimeRunning && timeRemaining > 0) {
      setTimeout(() => {
        setTimeRemaining((time) => time - 1);
      }, 1000);
    } else if (timeRemaining === 0) {
      endGame();
    }
  }, [timeRemaining, isTimeRunning]);

  // END GAME
  function endGame() {
    setIsTimeRunning(false);
    dispatch(updatePlayerGameRecord(Math.round(wpm), Math.round(accuracy)));
    history.push(pageurl.GAME_RESULT);
  }

  return (
    <React.Fragment>
      <div className="typing-board">
        <PlayerPerformance
          currentGameWpm={wpm}
          currentGameAccuracy={accuracy}
        />
        <h1 className="no-mobile-version">Switch to pc</h1>
        <h1 className="show-smiley">
          {" "}
          {timeRemaining} {smileyMode(wpm, accuracy)}
        </h1>
        <section className={`typing-wrapper ${darkTheme ? "dark" : "light"}`}>
          <div className="typing-text">
            <code className="character-out">
              {(leftPadding + outgoingChars).slice(-20)}
            </code>

            <code className="current-incoming-character">
              {currentChar}
              {incomingChars.substr(0, 200)}
            </code>
          </div>
        </section>
        <section className="typing-input-wrapper">
          <textarea
            placeholder="Start coding..."
            value={outgoingChars}
            spellCheck="false"
            autoFocus
            readOnly
          ></textarea>
        </section>
      </div>
    </React.Fragment>
  );
};


<|start_filename|>src/components/game/performance/playerperformance.css<|end_filename|>
.typist-performance {
  position: absolute;
  top: 0;
  right: 0;
  padding: 1rem 3rem;
  line-height: 1.5;
  background-color: var(--touch-color);
  color: var(--white-color);
  display: flex;
  flex-direction: column;
  border-bottom-left-radius: 0.4rem;
  cursor: pointer;
  overflow: hidden;
}

.custom-mt-4.typist-performance {
  margin-top: 4rem !important;
}

/* SHOW FULL PERFORMANCE */
.collapse-typist-performance {
  height: 100%;
  border-bottom-left-radius: 0rem;
  background-color: aliceblue;
  color: var(--touch-color);
}

/* HIDE FULL PERFORMANCE */
.full-performance {
  display: none;
}

.display-full-performance {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 50%;
  margin-top: 1rem;
}

.full-performance p {
  line-height: 3;
}

.typist-performance span {
  font-size: 1rem;
  font-weight: 600;
}

.current-performance {
  text-align: center;
}

.current-performance .wpm {
  margin-right: 1rem;
}

.current-performance .accuracy {
  margin-left: 1rem;
}

@media (min-width: 900px) {
  .typist-performance {
    width: 350px;
  }
}


<|start_filename|>src/components/game/GameResult.js/gameresult.css<|end_filename|>
.result-container {
  color: var(--white-color);
  border: 2px solid var(--white-color);
  width: 50%;
  padding: 2rem 0;
}

.light-mode.result-container {
  background-color: var(--touch-color);
}

.result-heading {
  font-size: 1.5rem;
  line-height: 1.5;
  text-align: center;
  margin-bottom: 2rem;
}

.new-record-heading {
  text-align: center;
  margin-bottom: 1rem;
}

.result-body .heading,
.point-heading {
  display: flex;
  justify-content: center;
}

.result-body .heading span,
.point-heading span {
  width: 50%;
  text-align: center;
}

.result-body .heading {
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 2;
}

.share-point {
  text-align: center;
  margin-top: 3rem;
}

.share-point .link-btn a {
  padding: 0rem !important;
}

.share-point button:not(:first-child) {
  margin: 0 1rem;
}

.share-point button:hover {
  box-shadow: inset 0 0 0 1px transparent;
  box-shadow: inset 0 0 0 1px var(--light-blue-color);

  transform: scale(1.03);
}

.share-point abbr {
  text-decoration: none;
}


<|start_filename|>src/components/layouts/button/button.css<|end_filename|>
.custom--btn {
  border-radius: 0.25rem;
  appearance: none;
  border: none;
  cursor: pointer;
  text-align: center;
  font-weight: 700;
  line-height: 1.28571429;
  letter-spacing: 0.8px;
  font-size: 0.875rem;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--primary-color);
}

.custom--btn:hover {
  box-shadow: inset 0 0 0 1px var(--primary-color);
}

.custom--btn.link-btn.button {
  padding: 0rem;
}

.custom--btn a {
  text-decoration: none;
  color: inherit;
  display: block;
  padding: 0.75rem 1rem;
}

.custom--btn-outline {
  box-shadow: inset 0 0 0 1px var(--white-color);
  color: var(--white-color);
  background-color: var(--primary-color);
}

.custom--btn-outline:hover {
  box-shadow: inset 0 0 0 1px var(--white-color);
  transform: scale(1.03);
}

.custom--btn-outline-primary {
  box-shadow: inset 0 0 0 1px var(--touch-color);
  color: var(--touch-color);
}

.custom--btn-outline-primary:hover {
  box-shadow: inset 0 0 0 1px var(--touch-color);
  color: var(--touch-color);
}

.custom--btn-touch {
  background-color: var(--touch-color);
  color: var(--white-color);
}

.custom--btn-touch:hover {
  box-shadow: inset 0 0 0 1px var(--white-color);
  background-color: var(--touch-color);
  color: var(--white-color);
}

.custom--btn-primary {
  background-color: var(--primary-color);
  color: var(--white-color);
}


<|start_filename|>src/components/winner/WinnerAlert.js<|end_filename|>
import { faTimes } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { RegularButton } from "../layouts/button/Button";
import "./winner.css";

export const WinnerAlert = () => {
  const { gameRecord } = useSelector((state) => state.user);
  const [congratulate, setCongratulate] = useState(false);
  const { rank, userName } = gameRecord || {};
  const [rankWord, setrankWord] = useState();
  useEffect(() => {
    if (rank > 0 && rank < 6) {
      setCongratulate(true);
    }
  }, [rank]);

  useEffect(() => {
    if (rank && congratulate) {
      switch (rank) {
        case 1:
          setrankWord("1st");
          break;
        case 2:
          setrankWord("2nd");
          break;
        case 3:
          setrankWord("3rd");
          break;
        case 4:
          setrankWord("4th");
          break;
        case 5:
          setrankWord("5th");
          break;
        default:
          break;
      }
    }
  }, [rank, congratulate]);

  return (
    <React.Fragment>
      <div
        className={`winner-alert ${
          congratulate ? "open-alert" : "close-alert"
        }`}
      >
        <section className="winner-alert--wrapper">
          <section
            className="close-winner--alert"
            onClick={() => setCongratulate(false)}
          >
            <FontAwesomeIcon icon={faTimes} />
          </section>

          <section className="content">
            <h1>Congratulations!!!</h1>
            <p>
              <span className="congratulation-name">{userName}</span>, you are
              the {rankWord} fastest developer
            </p>
            <span>
              <RegularButton
                type="custom--btn-outline twitter-share-button"
                target="_blank"
                rel="noopener noreferrer"
                linkUrl={`
                
                https://twitter.com/intent/tweet?text=I am the ${rankWord} fastest typist on the developers typing game website developed by @unclebigbay143

                Check out how fast your coding speed is on https://developer-typing-game.netlify.app/`}
                label="Tweet"
                abbrTitle="Share your achievement"
              />
            </span>
          </section>
          <section className="balloon-container">
            <div className="balloon"></div>
            <div className="balloon"></div>
            <div className="balloon"></div>
            <div className="balloon"></div>
            <div className="balloon"></div>
          </section>
        </section>
      </div>
    </React.Fragment>
  );
};


<|start_filename|>src/redux/game/actions/game.action.js<|end_filename|>
import { LAST_GAME_RESULT } from "../../types";
import GameService from "../service/game.service";

export const updatePlayerGameRecord = (wpm, accuracy) => (dispatch) => {
  dispatch({
    type: LAST_GAME_RESULT,
    payload: {
      wpm,
      accuracy,
    },
  });
  return GameService.updatePlayerGameRecord(Number(wpm), Number(accuracy));
};


<|start_filename|>src/redux/types/index.js<|end_filename|>
// General
export const SET_SCREEN_MESSAGE = "SET_SCREEN_MESSAGE";
export const CLEAR_SCREEN_MESSAGE = "CLEAR_SCREEN_MESSAGE";
// Authentications
export const REGISTRATION_SUCCESSFUL = "REGISTRATION_SUCCESSFUL";
export const LOGIN_SUCCESSFULL = "LOGIN_SUCCESSFULL";
export const USER_LOADED = "USER_LOADED";
export const PLAYER_GAME_RECORD_LOADED = "PLAYER_GAME_RECORD_LOADED";
export const LOGOUT = "LOGOUT";

// Games
export const LAST_GAME_RESULT = "LAST_GAME_RESULT";

// Notification
export const SET_NOTIFICATION = "SET_NOTIFICATION";
export const CLEAR_NOTIFICATION = "CLEAR_NOTIFICATION";


<|start_filename|>src/components/user/profile/userprofile.css<|end_filename|>
.no-network {
  color: var(--white-color);
}

.user {
  color: var(--white-color);
  padding: 2rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  line-height: 1.5;
}

.light-mode.user {
  color: var(--touch-color);
}

.user img {
  width: 30%;
}

.user .user-name {
  text-transform: uppercase;
  font-size: 2rem;
}

.user .user-twitter-handle a {
  color: var(--primary-color);
  margin-left: 0.1rem;
}

.user-email-address {
  margin-top: 1.5rem;
}

.user-email-address:hover {
  text-decoration: underline;
}

.user .user-rank {
  line-height: 2;
  font-weight: 600;
}


<|start_filename|>src/components/comingSoon.js<|end_filename|>
import { SET_SCREEN_MESSAGE } from "../redux/types";

export const comingSoon = (feature) => (dispatch) => {
  dispatch({
    type: SET_SCREEN_MESSAGE,
    payload: {
      type: "success",
      message: `${feature} Coming soon 🚀`,
    },
  });
};


<|start_filename|>src/components/game/typingboard/smileyMode.js<|end_filename|>
export const smileyMode = (wpm, accuracy) => {
  if (wpm === 0) return "👋";
  if (wpm > 100) return "💪";
  if (wpm > 80) return "😜 Boss";
  if (wpm > 50) return "🤗";
  if (wpm > 20) return "😲";
  if (wpm > 10) return "🤪";
  if (wpm < 10) return "😭";
};


<|start_filename|>src/components/user/profile/UpdateProfile.js<|end_filename|>
import React, { useEffect, useState } from "react";
import { ErrorMessage, Field, Form, Formik } from "formik";
import "./updateprofile.css";
import { updateProfileSchema } from "../../_helper/validator/schema";
import { updateProfile } from "../../../redux/user/actions/user.actions";
import { useDispatch, useSelector } from "react-redux";
import { pageurl } from "../../pageurl";
import { useHistory } from "react-router";

export const UpdateProfile = () => {
  const dispatch = useDispatch();
  const history = useHistory();
  const { user } = useSelector((state) => state.user);
  const { email, userName, twitterHandle } = user || {};
  const [darkTheme, setDarkTheme] = useState("");
  let prefferedTheme = JSON.parse(localStorage.getItem("_dark_theme"));

  // Set user preferred theme
  useEffect(() => {
    setDarkTheme(prefferedTheme);
  }, [prefferedTheme]);

  return (
    <div className={`update-profile ${darkTheme ? "dark" : "light-mode"}`}>
      <Formik
        initialValues={{
          twitterHandle: "",
        }}
        // Yup validate form
        validationSchema={updateProfileSchema}
        // Handle form submission
        onSubmit={(values, action) => {
          dispatch(updateProfile(values, action)).then((res) => {
            history.push(pageurl.USER_PROFILE);
          });
        }}
      >
        {({ isSubmitting }) => (
          <Form>
            <div className="form-heading">
              <h1>Update Profile</h1>
            </div>
            <div className="input-wrapper">
              <div className="input-heading">
                <div className="input-label">
                  <label htmlFor="username">Username</label>
                </div>
                <ErrorMessage
                  className="error-message"
                  name="username"
                  component="div"
                />
              </div>
              <Field
                type="text"
                name="username"
                id="username"
                placeholder={userName}
                disabled={true}
              />
            </div>
            <div className="input-wrapper">
              <div className="input-heading">
                <div className="input-label">
                  <label htmlFor="email">Email</label>
                </div>
                <ErrorMessage
                  className="error-message"
                  name="email"
                  component="div"
                />
              </div>
              <Field
                type="text"
                name="email"
                id="email"
                placeholder={email}
                disabled={true}
              />
            </div>
            <div className="input-wrapper">
              <div className="input-heading">
                <div className="input-label">
                  <label htmlFor="twitterHandle">Twitter Handle</label>
                </div>
                <ErrorMessage
                  className="error-message"
                  name="twitterHandle"
                  component="div"
                />
              </div>
              <Field
                type="text"
                name="twitterHandle"
                id="twitterHandle"
                placeholder={twitterHandle ? twitterHandle : "@username"}
              />
            </div>
            <div className="input-wrapper">
              <button
                type="submit"
                className="custom--btn custom--btn-primary"
                disabled={isSubmitting}
              >
                {isSubmitting ? "Working on it..." : "Update Profile"}
              </button>
            </div>
          </Form>
        )}
      </Formik>
    </div>
  );
};


<|start_filename|>src/components/layouts/notification/overheadnotify/github-star/GithubStar.js<|end_filename|>
import React from "react";
import GitHubButton from "react-github-btn";
import "./github-star.css";

export const GithubStar = () => {
  return (
    <React.Fragment>
      <GitHubButton
        href="https://github.com/unclebay143/typing-game"
        data-icon="octicon-star"
        data-show-count="true"
        aria-label="Star unclebay143/typing-game on GitHub"
        data-size="large"
      >
        {/* Star */}
      </GitHubButton>
    </React.Fragment>
  );
};


<|start_filename|>src/components/homepage/homepage.css<|end_filename|>
.home {
  min-height: 100vh;
  background-color: var(--primary-color);
}

.dark.home {
  background-color: var(--touch-color);
}


<|start_filename|>src/components/homepage/Homepage.js<|end_filename|>
import React, { useEffect, useState } from "react";
import { Navbar } from "../layouts/navbar/Navbar";
import "./homepage.css";
import { AnnouncementCircle } from "./announcementCircle/AnnouncementCircle";
import { TopPlayers } from "./top-players/TopPlayers";
import { ShareButtons } from "./social-media-share/ShareButtons";
import { OverHeadNotify } from "../layouts/notification/overheadnotify/OverHeadNotify";

// Animate on scroll
import AOS from "aos";
import "aos/dist/aos.css";
AOS.init();

export const Homepage = () => {
  let isToken = localStorage.getItem("jwt-token");
  const [darkTheme, setDarkTheme] = useState("");
  let prefferedTheme = JSON.parse(localStorage.getItem("_dark_theme"));

  const theme = ["dark", "light"];
  const randomTheme = theme[Math.floor(Math.random() * theme.length)];
  const [useRandomTheme, setUseRandomTheme] = useState();

  // Set user preferred theme
  useEffect(() => {
    // if user is logged in use their theme
    if (isToken) {
      setDarkTheme(prefferedTheme);
    } else {
      //else random theme
      setUseRandomTheme(randomTheme);
    }
  }, [prefferedTheme, isToken, randomTheme]);

  return (
    <React.Fragment>
      {/* Over head navbar notification */}
      <OverHeadNotify />

      {/* component route */}
      <div className={`home ${darkTheme ? "dark" : useRandomTheme}`}>
        <Navbar />
        <AnnouncementCircle />
        <TopPlayers />
        <ShareButtons />
      </div>
    </React.Fragment>
  );
};


<|start_filename|>src/components/homepage/announcementCircle/AnnouncementCircle.js<|end_filename|>
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
  faArrowAltCircleRight,
  faTimes,
} from "@fortawesome/free-solid-svg-icons";
import React, { useEffect, useState } from "react";
import "./announcement-circle.css";
import { Link } from "react-router-dom";
import { pageurl } from "../../pageurl";
import axios from "axios";
import {
  BASE_URL,
  LOAD_ALL_PLAYERS,
} from "../../../redux/user/service/root-endpoints";

export const AnnouncementCircle = () => {
  const [closeAnnouncement, setCloseAnnouncement] = useState(false);
  const [registeredUsername, setRegisteredUsername] = useState({});

  useEffect(() => {
    // don't forget to convert this function into service (reusable)
    async function getAllPlayers() {
      try {
        const players = await axios.get(BASE_URL + LOAD_ALL_PLAYERS);
        const playersUsername = players.data[0].map(
          (player) => player.userName
        );

        setRegisteredUsername(playersUsername);
      } catch (error) {
        console.log(error);
      }
    }

    getAllPlayers();
  }, []);

  return (
    <React.Fragment>
      <section
        data-aos="zoom-in"
        className={`announcement-circle ${closeAnnouncement && "close-circle"}`}
      >
        <div className="announcement-circle--content">
          <h1>
            Join {"unclebigbay"}, {registeredUsername[0] || "grace"} and{" "}
            {registeredUsername.length || "12"}+ developers improving their
            typing speed.
          </h1>
          <div className="lets-go">
            <h1>
              <Link to={pageurl.REGISTER}>Let's go</Link>
            </h1>
            <FontAwesomeIcon
              className="lets-go-icon"
              icon={faArrowAltCircleRight}
            />
          </div>
        </div>
        <span
          className="announcement-circle--close"
          onClick={() => setCloseAnnouncement(true)}
        >
          <FontAwesomeIcon icon={faTimes} />
        </span>
      </section>
    </React.Fragment>
  );
};


<|start_filename|>src/App.js<|end_filename|>
import "./App.css";
import { Homepage } from "./components/homepage/Homepage";
import { Route, Switch } from "react-router";
import { pageurl } from "./components/pageurl";
import { Registration } from "./components/authentication/register/Registration";
import { Login } from "./components/authentication/login/Login";
import { ForgotPassword } from "./components/authentication/forgot-password/ForgotPassword";
import { GameArea } from "./components/game/gamearea/GameArea";
import { Welcome } from "./components/confirmation/welcome/Welcome";
import { PasswordConfirmation } from "./components/confirmation/passwordConfirmation/PasswordConfirmation";
import { PopNotify } from "./components/layouts/notification/popnotify/PopNotify";

function App() {
  return (
    <div className="App">
      {/* NOTIFICATION COMPONENT */}
      <PopNotify />

      <Switch>
        <Route exact path={pageurl.HOMEPAGE} component={Homepage} />
        <Route exact path={pageurl.REGISTER} component={Registration} />
        <Route exact path={pageurl.LOGIN} component={Login} />
        <Route exact path={pageurl.WELCOME_ONBOARD} component={Welcome} />
        <Route
          exact
          path={pageurl.FORGOT_PASSWORD_CONFIRMATION}
          component={PasswordConfirmation}
        />
        <Route
          exact
          path={pageurl.FORGOT_PASSWORD}
          component={ForgotPassword}
        />
        <Route path={pageurl.DASHBOARD} component={GameArea} />
      </Switch>
    </div>
  );
}

export default App;


<|start_filename|>src/components/confirmation/passwordConfirmation/PasswordConfirmation.js<|end_filename|>
// React
import React from "react";

// Css
import "./../welcome/welcome.css";
import "./passwordConfirmation.css";

// Component
// import wavingHand from "./../../../assets/img/waving-hand.gif";
import { pageurl } from "../../pageurl";
import { Link } from "react-router-dom";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faMailchimp } from "@fortawesome/free-brands-svg-icons";

export const PasswordConfirmation = () => {
  return (
    <React.Fragment>
      <div className="welcome-onboard">
        <div className="welcome-body">
          <section className="welcome-body--heading">
            <h1>Mail Delivered!!!</h1>
            {/* <img src={wavingHand} alt="waving hand" /> */}
            <FontAwesomeIcon icon={faMailchimp} className="mail-icon" />
          </section>
          <section className="welcome-body--message">
            <p>
              A link to reset your password has been sent to your registered{" "}
              <strong>email</strong> address
            </p>

            <p className="redirection">
              Continue to <Link to={pageurl.LOGIN}>Login</Link>
            </p>
          </section>
        </div>
      </div>
    </React.Fragment>
  );
};


<|start_filename|>src/components/homepage/top-players/TopPlayers.js<|end_filename|>
// React
import React, { useEffect, useState } from "react";
// Styles
import "./top-players.css";

// Axios
import axios from "axios";
import {
  BASE_URL,
  LOAD_ALL_PLAYERS,
} from "../../../redux/user/service/root-endpoints";

// Images
import wavingHand from "./../../../assets/img/waving-hand.gif";

// Component
import { TopPlayersCard } from "./TopPlayersCard";
import { SET_SCREEN_MESSAGE } from "../../../redux/types";
import { useDispatch } from "react-redux";
import { faSpinner } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { rankPlayers } from "./rankPlayers";

export const TopPlayers = () => {
  const [showAll, setShowAll] = useState(false);
  const [isLoading, setIsLoading] = useState(true);
  const [topPlayers, setTopPlayers] = useState();
  const dispatch = useDispatch();

  useEffect(() => {
    // Get all players
    const fetchTopPlayers = async () => {
      try {
        // Get players
        const players = await axios.get(BASE_URL + LOAD_ALL_PLAYERS);

        const samplePlayer = [
          {
            player: 2,
            wpm: 8,
            accuracy: 99,
          },
          {
            player: 1,
            wpm: 9,
            accuracy: 100,
          },
          {
            player: 3,
            wpm: 7,
            accuracy: 98,
          },
        ];

        // Extract players array from response
        const extractPlayersArray = players.data[0];
        if (extractPlayersArray) {
          // Sort top players from current lead to least
          const descendingOrderOfPlayers = extractPlayersArray.sort((a, b) => {
            // sort by wpm/code per minute
            return b.wpm - a.wpm;
          });

          // Rank the user in the database
          rankPlayers(descendingOrderOfPlayers);

          // Remove loader
          setIsLoading(false);

          // Store the sorted top players to the state
          setTopPlayers(descendingOrderOfPlayers);
        }
      } catch (error) {
        console.log(error);
        dispatch({
          type: SET_SCREEN_MESSAGE,
          payload: {
            type: "danger",
            message: "Can't Fetch Top players 😪",
          },
        });
      }
    };

    fetchTopPlayers();
  }, [dispatch]);

  // Number of topPlayers to display
  const topPlayerLimit = showAll ? 10 : 5;

  // Handle the show more button
  const handleShowAll = () => {
    return setShowAll(!showAll);
  };

  // Show loader if the players have not been fetched
  if (isLoading) {
    return (
      <div className="rank-section loading">
        <FontAwesomeIcon icon={faSpinner} spin />
      </div>
    );
  }

  return (
    <React.Fragment>
      <section className="rank-section">
        <div className="welcome-user">
          <div className="greeting-text">
            <h2>How is coding today?</h2>
            {/* <h2>Welcome back</h2> when logged in */}
          </div>
          <img src={wavingHand} alt="waving hand" className="waving-hand" />
        </div>
        <div className="rank-board">
          <div className="rank-board--heading">
            <h3>Top 10 Fastest Typist</h3>
          </div>
          {topPlayers
            ?.slice(0, topPlayerLimit)
            .map(({ wpm, accuracy, id, time, userName, twitterHandle }) => {
              return (
                <TopPlayersCard
                  key={id}
                  wpm={wpm}
                  accuracy={accuracy}
                  userName={userName}
                  id={id}
                  gameTime={time}
                  twitterHandle={twitterHandle}
                />
              );
            })}
          <div className="board-toggler">
            <button
              onClick={handleShowAll}
              className="button custom--btn custom--btn-outline-primary"
            >
              {showAll ? "Show less" : "Show more"}
            </button>
          </div>
        </div>
      </section>
    </React.Fragment>
  );
};


<|start_filename|>src/redux/game/reducers/game.reducer.js<|end_filename|>
import { LAST_GAME_RESULT } from "../../types";

// Last Game Record
const INITIAL_STATE = {
  wpm: null,
  accuracy: null,
};

// redux reducer function
const gameReducer = (state = INITIAL_STATE, action) => {
  // Destructure type and payload from action
  const { type, payload } = action;

  switch (type) {
    case LAST_GAME_RESULT:
      return {
        ...state,
        wpm: payload.wpm,
        accuracy: payload.accuracy,
      };

    default:
      // return the state by default else react will shout
      return state;
  }
};

export default gameReducer;


<|start_filename|>src/components/game/typingboard/codeQuotes.js<|end_filename|>
export const codeQuotes = {
  javascript: [
    "console.log('Hello, World');",
    "const name = '<NAME>'; // visitor name",
    "console.log(`welcome $name`); // greet visitor",
    "array.map((arr)=>console.log(arr))",
    "people.filter((person)=>person.role === 'admin')",
    "members.forEach((member)=> console.log(member.position))",
    "for(let x=1; array.length > x; x++)",
    "{if(array[x] === 'darkmode') return darkMode()}",
  ],

  css: ["css"],
};


<|start_filename|>src/components/_helper/clipBoard/copyToClipBoard.js<|end_filename|>
// function that handles the copy oasr
export const copyToClipBoard = (copyText) =>{
    // select the element content
    copyText.select();

    /* For mobile devices support*/
    copyText.setSelectionRange(0, 99999); 

    /* Copy the text inside the text field */
    document.execCommand("copy");

}

<|start_filename|>src/components/homepage/top-players/TopPlayersCard.js<|end_filename|>
// FONT-AWESOME
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faStar, faStarHalfAlt } from "@fortawesome/free-solid-svg-icons";
import { faTwitter } from "@fortawesome/free-brands-svg-icons";

// LAYOUT
import { RegularButton } from "../../layouts/button/Button";

import face from "./../../../assets/img/no-image-avatar.png";
import { useDispatch } from "react-redux";
import { SET_SCREEN_MESSAGE } from "../../../redux/types";
import { timeAgo } from "../../_helper/time/time";

// Players card
export const TopPlayersCard = ({
  userName,
  wpm,
  gameTime,
  accuracy,
  twitterHandle,
}) => {
  const dispatch = useDispatch();

  // Twitter username not available
  const twitterDisable = () => {
    dispatch({
      type: SET_SCREEN_MESSAGE,
      payload: {
        message: "Not available 😴",
        type: "danger",
      },
    });
  };
  return (
    <div className="top-player" data-aos="fade-up">
      <div className="left-info">
        <div className="top-player--image">
          <img src={face} alt="top player avatar" />
        </div>
        <div className="player-information">
          <h3 className="player-name">{userName}</h3>
          <div className="player-details">
            <div className="player-star">
              <FontAwesomeIcon icon={faStar} className="checked-rank" />
              <FontAwesomeIcon icon={faStarHalfAlt} className="checked-rank" />
            </div>
            <p className="score-time">
              {" "}
              {wpm}cpm, {accuracy}% - {timeAgo(gameTime)}
            </p>
          </div>
        </div>
      </div>
      <div className="right-info">
        {twitterHandle ? (
          <RegularButton
            linkUrl={`https://www.twitter.com/intent/follow?screen_name=${twitterHandle}`}
            look="custom--btn-touch link-btn"
            label="Follow"
            icon={faTwitter}
            target="_blank"
          />
        ) : (
          <RegularButton
            func={() => twitterDisable()}
            look="custom--btn-touch link-btn"
            label="Twitter"
            icon={faTwitter}
            target="_blank"
            style={{ opacity: "0" }}
          />
        )}
      </div>
    </div>
  );
};


<|start_filename|>src/components/layouts/notification/flier-notification/Notify.js<|end_filename|>
import React, { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux";
import { Link } from "react-router-dom";
import { CLEAR_NOTIFICATION } from "../../../../redux/types";
import "./notify.css";

export const NotifyPlayer = () => {
  const { notification } = useSelector((state) => state.user);
  const [notificationMessage, setNotificationMessage] = useState(null);
  const { url, urlLabel, message, moreUrl } = notificationMessage || {};
  const { url1, url1Label } = moreUrl || {};
  const dispatch = useDispatch();

  const convertUrl1 = (
    <Link class="black-link" to={url1}>
      {url1Label}
    </Link>
  );

  useEffect(() => {
    if (notification) {
      setNotificationMessage(notification);
    }
  }, [notification]);
  return (
    <React.Fragment>
      {notification && (
        <div className="notify-container">
          <section className="notify-content">
            <p className="">
              <Link to={url}>{urlLabel}</Link> {message}
              {convertUrl1}
            </p>

            <span
              className="close--notify"
              onClick={() => dispatch({ type: CLEAR_NOTIFICATION })}
            >
              No, thanks
            </span>
          </section>
        </div>
      )}
    </React.Fragment>
  );
};


<|start_filename|>src/components/layouts/notification/popnotify/popnotify.css<|end_filename|>
.pop-notifier {
  position: fixed;
  right: 0;
  bottom: 0;
  color: var(--white-color);
  padding: 1rem 1.5rem;
  margin: 2rem;
  border-radius: 0.5rem;
  font-weight: 700;
  font-size: 1rem;
  text-transform: capitalize;
  cursor: pointer;
  white-space: nowrap;
  z-index: 999;
}

.pop-notifier svg {
  margin-right: 1rem;
}

.pop-notifier.success {
  background: var(--green-color);
}

.pop-notifier.danger {
  background: var(--warning-color);
}


<|start_filename|>src/components/authentication/forgot-password/ForgotPassword.js<|end_filename|>
import { ErrorMessage, Field, Form, Formik } from "formik";
import React from "react";
import "./forgotpassword.css";
import searchingAccounct from "./../../../assets/img/searching-someone.svg";
import { forgotPasswordSchema } from "../../_helper/validator/schema";
import { FormNavbar } from "../../layouts/navbar/FormNavbar";

export const ForgotPassword = () => {
  return (
    <React.Fragment>
      <FormNavbar loginPage={false} />
      <section className="forgotpassword">
        <Formik
          initialValues={{
            email: "",
          }}
          // Yup validate form
          validationSchema={forgotPasswordSchema}
          // Handle form submission
          onSubmit={(values) => {
            console.log(values);
          }}
        >
          {({ isSubmitting, handleSubmit }) => (
            <Form onClick={() => handleSubmit()}>
              <div className="form-heading">
                <h1>Let's Find your account</h1>
              </div>
              <div className="input-wrapper">
                <div className="input-heading">
                  <div className="input-label">
                    <label htmlFor="email">Email</label>
                  </div>
                  <ErrorMessage
                    className="error-message"
                    name="email"
                    component="div"
                  />
                </div>
                <Field
                  type="text"
                  name="email"
                  id="email"
                  placeholder="Provide your registered email address"
                />
              </div>
              <div className="input-wrapper">
                <button
                  type="submit"
                  className="custom--btn"
                  disabled={isSubmitting}
                >
                  {isSubmitting ? "Working on it..." : "Reset"}
                </button>
              </div>
            </Form>
          )}
        </Formik>

        <div className="forgotpassword-image">
          <img
            className="type-writer"
            src={searchingAccounct}
            alt="someone searching for accounts"
          />
        </div>
      </section>
    </React.Fragment>
  );
};


<|start_filename|>src/components/layouts/notification/overheadnotify/github-star/github-star.css<|end_filename|>
.github-star-wrapper {
  font-size: 2rem;
}


<|start_filename|>src/axios/index.js<|end_filename|>
// Axios
import axios from "axios";

// Axios instance
const axiosInstance = axios.create({
  baseURL: `${process.env.REACT_APP_BASE_URL}`,
  headers: {
    Accepted: "appication/json",
    "Content-Type": "application/json",
  },
});

// Inject token to the request header
axiosInstance.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem("jwt-token");
    if (token) {
      config.headers.authorization = token;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

export default axiosInstance;
