Untitled

 avatar
unknown
plain_text
4 years ago
4.9 kB
8
Indexable
// ARQUIVO
// pages/trivia.jsx


import React from 'react';
import Header from '../components/Header';

class Trivia extends React.Component {
  constructor() {
    super();
    this.state = {
      respondido: false,
      perguntas: [],
      indice: 0,
      timer: 30,
    };
    this.chamaApi = this.chamaApi.bind(this);
    this.sortArray = this.sortArray.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.computeAnswer = this.computeAnswer.bind(this);
  }

  componentDidMount() {
    const { timer } = this.state;
    const ONE_SECOND = 1000;
    const SECONDS_TO_MILLISECONDS = 1000;
    this.chamaApi();
    this.timerInterval = setInterval(() => {
      this.setState((prevState) => ({ timer: prevState.timer - 1 }));
    }, ONE_SECOND);
    setTimeout(() => (this.computeAnswer()), timer * SECONDS_TO_MILLISECONDS);
  }

  computeAnswer() { // Function called after an answer is clicked OR, a timeout happens
    this.setState({ respondido: true });
    clearInterval(this.timerInterval);
  }

  sortArray() {
    const { perguntas, indice } = this.state;
    const {
      correct_answer: correct,
      incorrect_answers: incorrect } = perguntas[indice];
    return [...incorrect, correct].sort();
  }

  async chamaApi() { // Makes the API call to fetch the current questions
    const TOKEN = JSON.parse(localStorage.token);
    const URL = `https://opentdb.com/api.php?amount=5&encode=url3986&token=${TOKEN}`;
    const response = await fetch(URL);
    const result = await response.json();
    this.setState({
      perguntas: result.results,
    });
  }

  handleClick() {
    this.computeAnswer();
  }

  render() {
    const { perguntas, indice, respondido, timer } = this.state;
    return (
      <div>
        <Header />
        <p>
          Time Left!!:
        </p>
        <span>{ timer }</span>
        {perguntas.length > 0
        && (
          <>
            <p data-testid="question-category">
              { decodeURIComponent(perguntas[indice].category) }
            </p>
            <p data-testid="question-text">
              { decodeURIComponent(perguntas[indice].question) }
            </p>
            {this.sortArray().map((atual, i) => (
              <button
                onClick={ this.handleClick }
                type="submit"
                key={ i }
                data-testid={
                  atual === perguntas[indice].correct_answer
                    ? 'correct-answer'
                    : `wrong-answer-${i}`
                }
                className={ respondido && (atual === perguntas[indice].correct_answer
                  ? 'correct'
                  : 'incorrect') }
              >
                {decodeURIComponent(atual)}
              </button>
            ))}
          </>)}
      </div>
    );
  }
}

export default Trivia;

_______________________________________________________________

// ARQUIVO
// components/Header.jsx

import React from 'react';
import md5 from 'crypto-js/md5';

class Header extends React.Component {
  constructor() {
    super();
    this.state = {
      player: {},
      hashInfo: '',
    };
  }

  componentDidMount() {
    this.playerInfoStart();
  }

  playerInfoStart() {
    const player = JSON.parse(localStorage.getItem('state'));
    const hashInfo = md5(player.gravatarEmail).toString();
    this.setState({
      player,
      hashInfo,
    });
  }

  render() {
    const { player, hashInfo } = this.state;
    return (
      <header>
        <img
          alt="Profile"
          data-testid="header-profile-picture"
          src={ `https://www.gravatar.com/avatar/${hashInfo}` }
        />
        <span data-testid="header-player-name">{ player.name }</span>
        <span data-testid="header-score">{ player.score }</span>
      </header>
    );
  }
}

export default (Header);


__________________________________________________________________

// ARQUIVO
// App.css

.App {
  text-align: center;
}

.App-logo {
  height: 40vmin;
  pointer-events: none;
}

.red-border {
  border: 1px solid red;
}

.green-border {
  border: 1px solid green;
}

@media ( prefers-reduced-motion : no-preference ) {

  .App-logo {
    animation: shake infinite 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
  }
}

.App-header {
  align-items: center;
  background-color: #282c34;
  color: white;
  display: flex;
  flex-direction: column;
  font-size: calc(10px + 2vmin);
  justify-content: center;
  min-height: 100vh;
}

.App-link {
  color: #61dafb;
}

@keyframes shake {

  10%, 90% {
    transform: translate3d(-1px, 0, 0);
  }

  20%, 80% {
    transform: translate3d(2px, 0, 0);
  }

  30%, 50%, 70% {
    transform: translate3d(-4px, 0, 0);
  }

  40%, 60% {
    transform: translate3d(4px, 0, 0);
  }
}

.correct {
  border: 3px solid rgb(6, 240, 15);
}

.incorrect {
  border: 3px solid rgb(255, 0, 0);
}
Editor is loading...