<div id="app"></div>
.container {
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
}

.wrapper {
  height: 80%;
  width: 80%;
  display: flex;
  flex-flow: column wrap;
  justify-content: center;
  align-items: center;
  border: 1px solid transparent;
  border-radius: 15px;
  background-color: #FFD5D4;
}

.wrapper > * {
  margin-bottom: 1rem;
}

.timer {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.clock {
  margin-bottom: 1rem;
}

.clock > input {
  padding: 1rem;
  margin: 0 5px;
  width: 3rem;
  text-align: center;
}

.time {
  text-align: center;
}

.buttons {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-around;
  align-items: center;
  width: 70%;
}

button {
  background-color: white;
  padding: 16px 24px;
  cursor: pointer;
  border-radius: 5px;
  border: 1px solid transparent;
  font-weight: 600;
  color: #FAF9F6;
}

button:hover {
  opacity: 0.9;
}

.green {
  background-color: #77DD76;
}

.blue {
  background-color: #A7C7E7;
}

.red {
  background-color: #FF6962;
}
/*
* https://frontendeval.com/questions/countdown-timer
*
* Create a countdown timer that notifies the user
*/

const Button = ({ color, text, onClick }) => {
  return <button class={ color } onClick={ (e) => onClick(e, text) }>{ text }</button>
}

const App = () => {
  const [hours, setHours] = React.useState(null);
  const [minutes, setMinutes] = React.useState(null);
  const [seconds, setSeconds] = React.useState(null);
  const [totalTime, setTotalTime] = React.useState(0);
  const [counting, setCounting] = React.useState(false);
  
  let timerId;
  
  React.useEffect(() => {
    if (totalTime == 0 && counting) {
      resetTimer();
      alertUser();
    }
  }, [totalTime])
  
  startTimer = () => {
    if (!hours && !minutes && !seconds) {
      alertUser();
      return;
    }
    setCounting(true);
    setTotalTime(calculateTime());
    this.interval = setInterval(() => {
      decrementByOneSecond();
    }, 1000)
  }
  
  pauseTimer = () => {
    clearInterval(this.interval);
    setCounting(false);
  }
  
  resetTimer = () => {
    clearInterval(this.interval);
    setHours('');
    setMinutes('');
    setSeconds('');
    setCounting(false);
    setTotalTime(0);
  }
  
  decrementByOneSecond = () => {
    const newTime = totalTime - 1;
    const newHours = Math.floor(newTime / 3600);
    const newMinutes = Math.floor((newTime - (newHours * 3600)) / 60);
    const newSeconds = newTime - (newHours * 3600) - (newMinutes * 60);
    
    setHours((''+newHours).padStart(2, '0'));
    setMinutes((''+newMinutes).padStart(2, '0'));
    setSeconds((''+newSeconds).padStart(2, '0'));
    setTotalTime(time => newTime)
  }
  
  alertUser = () => {
    alert('Timer finished');
  }
  
  calculateTime = () => {
    const time = (+hours) * 60 * 60 + (+minutes) * 60 + (+seconds)
    return time;
  }
  
  return (
    <div class='container'>
      <div class='wrapper'>
        <div class='timer'>
          <h1>Countdown Timer</h1>
          <div class='clock'>
            <input 
              type='number' 
              class='timer__hours' 
              placeholder='HH'
              maxLength={2}
              onChange={(e) => setHours(e.target.value)}
              value={ hours }
              aria-label="Hours"
             ></input>
            <span>:</span>
            <input 
              type='number' 
              class='timer__minutes'
              placeholder='MM'
              maxLength={2}
              onChange={(e) => setMinutes(e.target.value)}  
              value={ minutes }
              aria-label="Minutes"
            ></input>
            <span>:</span>
            <input 
              type='number' 
              class='timer__seconds' 
              placeholder='SS'
              maxLength={2}
              onChange={(e) => setSeconds(e.target.value)}
              value={ seconds }
              aria-label="Seconds"
            ></input>
          </div>
          <div class='buttons'>
            { !counting && <Button color='green' text='Start' onClick={ startTimer }/> }
            { counting && (
              <>
                <Button color='blue' text='Pause' onClick={ pauseTimer }/>
                <Button color='red' text='Reset' onClick={ resetTimer }/>
              </>
            )}
          </div>
        </div>
        <div class='time'><b>{totalTime}</b> seconds left</div>
      </div>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('app'));
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js