Tutorial React – Como criar uma aplicação Pomorodo
Parte 2/3

|Thalles Bastos

Seguimos nosso tutorial de como criar um Pomodoro Timer em React. Para quem chegou direto nesse post aqui está o primeiro onde criamos a estrutura inicial dando uma identidade para nossa aplicação:

Parte 1 - Tutorial React Pomodoro - Criando a estrutura inicial

Abaixo teremos os dois principais arquivos do nosso app, um deles é o App.js onde ficarão nossas funções e o outro é o pomodoro.js, o componente que monta a estrutura.

Usaremos dois áudios nessa aplicação, um é o DingDong.mp3 para sinalizar quando o timer acabar e o outro o Click.mp3 para o início da contagem. Clique nos links para baixar os arquivos e coloque na pasta /public do projeto.

Código dos arquivos

Abaixo temos os dois principais arquivos do app com as linhas comentadas. Após ler e entender o que acontece no código você pode copiar e colar nos arquivos do seu projeto. Eles estão com a versão final do timer.

App.js

import React, { useState, useRef, useEffect, useMemo } from 'react'
import Pomodoro from './components/pomodoro';

function App() {
  
  // Definição dos estados que usaremos e useRef() para os áudios
  const Ref = useRef(null);
  const [timer, setTimer] = useState('25:00');
  const [timerActive, setTimerActive] = useState(false);
  const [timerEnd, setTimerEnd] = useState();
  const [textIniciar, setTextIniciar] = useState('Iniciar');
  const [textMinutes, setTextMinutes] = useState('25');
  
  // criando os arquivos de áudio que usaremos
  const audioClick = useMemo(() => new Audio('/click.mp3'), []);
  const audioDingDong = useMemo(() => new Audio('/ding-dong.mp3'), []);
  
  // calculo do tempo restante para o final do timer
  const getTimeRemaining = (e) => {
    const total = Date.parse(e) - Date.parse(new Date());
    const seconds = Math.floor((total / 1000) % 60);
    const minutes = Math.floor((total / 1000 / 60) % 60);
    return {
        total, minutes, seconds
    };
  }

  // define o valor do timer em minutos, exemplo: 25:00
  const startTimer = (e) => {
    let { total, minutes, seconds } = getTimeRemaining(e);
    if (total >= 0) {
      setTimer((minutes > 9 ? minutes : '0' + minutes) + ':' + (seconds > 9 ? seconds : '0' + seconds))
    }
  }

  // ao clicar em iniciar/retomar rodamos esta função
  const initTimer = (e) => {
    audioClick.play();
    // caso seja para iniciar/retomar seta o timer como ativo e chama
    // a função clearTimer() para limpar e criar o contador do timer
    if(textIniciar === 'Iniciar' || textIniciar === 'Retomar'){
      setTextIniciar('Parar');
      setTimerActive(true);
      clearTimer(getDeadTime());
    } else {
      // caso seja para parar a contagem gravamos o tempo que falta para
      // acabar o timer e encerramos/limpamos o contador com clearInterval()
      setTextIniciar('Retomar')
      setTimerActive(false)
      const diferenca = Date.parse(timerEnd) - Date.parse(new Date())
      const seconds = Math.floor((diferenca / 1000) % 60)
      const minutes = Math.floor((diferenca / 1000 / 60) % 60)
      setTimer((minutes > 9 ? minutes : '0' + minutes) + ':' + (seconds > 9 ? seconds : '0' + seconds))
      if (Ref.current) clearInterval(Ref.current)
    }
  }

  // função que limpa timers existentes e cria o contador
  const clearTimer = (e) => {
    if(textIniciar === 'Iniciar'){
      if (Ref.current) clearInterval(Ref.current)
    }
    const id = setInterval(() => {
        setTimerEnd(e)
        startTimer(e)
        const diferenca = Date.parse(e) - Date.parse(new Date())
        const seconds = Math.floor((diferenca / 1000) % 60)
        const minutes = Math.floor((diferenca / 1000 / 60) % 60)
        document.title = minutes+':'+seconds+' Pomodoro Timer - Otimize seu tempo';
        // caso o timer tenha chegado no final, limpamos o contador
        // e damos play no áudio que sinaliza que finalizou
        if(Date.parse(new Date()) === Date.parse(e)){
          if (Ref.current) clearInterval(Ref.current)
          setTimer((textMinutes > 9 ? textMinutes : '0' + textMinutes) + ':00')
          setTimerActive(false)
          setTextIniciar('Iniciar')
          audioDingDong.play()
        }
    }, 1000)
    Ref.current = id
  }

  // verifica quando tempo já se passou no timer
  const getDeadTime = () => {
    let deadline = new Date()
    deadline.setMinutes(deadline.getMinutes() + parseInt(textMinutes))
    deadline.setSeconds(deadline.getSeconds() + 0)
    return deadline
  }

  // caso o usuário mude o tempo do timer, seta o novo tempo e reinicia
  useEffect(() => {
    setTimer((textMinutes > 9 ? textMinutes : '0' + textMinutes) + ':00')
  }, [textMinutes]);

  // ao clicar em resetar, limpamos o contador e setamos o valor do timer
  const resetTimer = () => {
    setTimerActive(false)
    setTimer((textMinutes > 9 ? textMinutes : '0' + textMinutes) + ':00')
    setTextIniciar('Iniciar')
    document.title = 'Pomodoro Timer - Otimize seu tempo'
    if (Ref.current) clearInterval(Ref.current)
  }

  // chama nosso componente que monta o template do timer passando as propriedades necessárias
  return (
    <div className="App">
      <Pomodoro
        timer={timer} 
        initTimer={initTimer}
        resetTimer={resetTimer}
        timerActive={timerActive}
        textIniciar={textIniciar}
        textMinutes={textMinutes}
        setTextMinutes={setTextMinutes}
      />
    </div>
  );
}

export default App;

/components/pomodoro.js

import React from 'react'

function Pomodoro(props) {

  const { timer, initTimer, resetTimer, timerActive, textIniciar, textMinutes, setTextMinutes } = props;

  const handleChange = event => {
    resetTimer()
    const min = 1
    const max = 60
    const value = Math.max(min, Math.min(max, Number(event.target.value)))
    setTextMinutes(value)
  };

  return (
    <div>
      <div className='container'>
        <h1>Pomodoro Timer</h1>
        <div className="top">
          <p>Vou focar durante </p>
          <input 
            type="number"
            maxLength="60" 
            value={textMinutes} 
            onChange={handleChange}
          />
          <p>minutos</p>
        </div>
        <div className='timerPomo'>{timer}</div>
        <div className='flexButtons'>
          <button className={timerActive ? "buttonActive" : ""} onClick={initTimer}>{textIniciar}</button>
          <button onClick={resetTimer}>Resetar</button>
        </div>
      </div>
      <div className="shape-divider shape-divider-bottom">
        <svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 2000 245" preserveAspectRatio="xMinYMin">
          <path fill="#FFF" opacity="0.5" d="M2028.47,246.15v-39.09C1945.6,199.68,1869.96,195.8,1803,194c-71.99-1.93-137.53-4.37-225,1 c-88.04,5.4-120.19,13.36-233,19c-55.14,2.76-102.19,5-165,3c-37.5-1.2-102.55-4.6-200-19c-89.42-13.21-145.61-26.73-276-57 C520.19,98.33,428.29,76.99,402,72C243.75,41.93,118.41,28.67,37,22c-26.77-2.19-49.49-3.73-66.33-4.77v229.03h2057.82 C2028.48,246.22,2028.47,246.19,2028.47,246.15z"></path>
          <path fill="#FFF" d="M1816,212c-58.78-4.11-116.63-8.07-195-9c-43.43-0.51-105.81-1.13-187,4c-33.73,2.13-29.27,2.64-127,10 c-86.52,6.52-110.13,7.64-137,8c-11.31,0.15-53.81,0.58-110-3c-54.49-3.47-108.08-9.83-185-23c-69.21-11.85-114.89-21.96-202-41 c-262.93-57.46-291.75-62.62-318-67C229.24,70,155.97,65.58,121,64C60.05,61.24,8.67,62.27-28.77,63.95v187.41H2028V232 C1943.49,221.98,1871.42,215.88,1816,212z"></path>
        </svg>
      </div>
    </div>
  )
}

export default Pomodoro

Após adicionar o novo código nos arquivos existentes, rode a aplicação para ver as funções do timer em ação, dentro da pasta do projeto execute no terminal: $ npm start

Seguimos para a próxima etapa de como criar uma aplicação em React onde iremos publicar a aplicação no Heroku, salvar o projeto no Github e LinkedIn. Próxima parte:

-

Parte 3 - Tutorial React Pomodoro - Github e LinkedIn

-

DiversificaDev - Oferecendo mentoria gratuita para iniciantes em tecnologia e programação para estimular a diversidade na área além de soluções digitais como criação de sites, gestão mídias sociais, estratégias de marketing e otimização de sites SEO.



Nenhum comentário

Comentar

Clique no Captcha para enviar

Inscreva-se na nossa Newsletter