Countdown click in JavaScript I did a small countdown clock challenge in JavaScript. Please review it, thanks.


const timeControls = document.querySelector('.timer__controls');
const timeLeft = document.querySelector('.display__time-left');
const endTime = document.querySelector('.display__end-time');
let interval;

function secondsToHourMinSec(seconds) {
  const date = new Date(0);
  date.setSeconds(seconds);
  return date.toISOString().substr(11, 8);
}

function advanceCurrentTime(seconds) {
  const date = new Date(0);
  date.setSeconds(Math.floor(Date.now() / 1000) + seconds);
  return date.toLocaleTimeString().substr(0, 7);
}

function displayRemainingTime(seconds) {
  timeLeft.textContent = secondsToHourMinSec(seconds);
}

function displayEndTime(seconds) {
  endTime.textContent = `Be back at ${advanceCurrentTime(seconds)}`;
}

function displayTime(seconds) {
  displayRemainingTime(seconds);
  displayEndTime(seconds);

  interval = setInterval(function() {
    seconds--;
    if (seconds &lt; 0) {
      clearInterval(interval);
      return;
    }
    displayRemainingTime(seconds);
  }, 1000);
}

function startTimer(seconds) {
  clearInterval(interval);
  displayTime(seconds);
}

timeControls.addEventListener('click', e =&gt; {
  const button = e.target.closest('button');
  if (button)
    startTimer(parseInt(button.dataset.time));
});

document.customForm.addEventListener('submit', function(e) {
  e.preventDefault();
  const value = this.minutes.value;
  if (value.length !== 0)
    startTimer(parseInt(value) * 60);
  this.reset();
});
html {
  box-sizing: border-box;
  font-size: 10px;
  background: #8e24aa;
  background: linear-gradient(45deg, #42a5f5 0%, #478ed1 50%, #0d47a1 100%);
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin: 0;
  text-align: center;
  font-family: "Inconsolata", monospace;
}

.display__time-left {
  font-weight: 100;
  font-size: 20rem;
  margin: 0;
  color: white;
  text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.05);
}

.timer {
  display: flex;
  min-height: 100vh;
  flex-direction: column;
}

.timer__controls {
  display: flex;
}

.timer__controls&gt;* {
  flex: 1;
}

.timer__controls form {
  flex: 1;
  display: flex;
}

.timer__controls input {
  flex: 1;
  border: 0;
  padding: 2rem;
}

.timer__button {
  background: none;
  border: 0;
  cursor: pointer;
  color: white;
  font-size: 2rem;
  text-transform: uppercase;
  background: rgba(0, 0, 0, 0.1);
  border-bottom: 3px solid rgba(0, 0, 0, 0.2);
  border-right: 1px solid rgba(0, 0, 0, 0.2);
  padding: 1rem;
  font-family: "Inconsolata", monospace;
}

.timer__button:hover,
.timer__button:focus {
  background: rgba(0, 0, 0, 0.2);
  outline: 0;
}

.display {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.display__end-time {
  font-size: 4rem;
  color: white;
}
&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;

&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;title&gt;Countdown Timer&lt;/title&gt;
  &lt;link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet" type="text/css"&gt;
  &lt;link rel="stylesheet" href="style.css"&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;div class="timer"&gt;
    &lt;div class="timer__controls"&gt;
      &lt;button data-time="20" class="timer__button"&gt;20 Secs&lt;/button&gt;
      &lt;button data-time="300" class="timer__button"&gt;Work 5&lt;/button&gt;
      &lt;button data-time="900" class="timer__button"&gt;Quick 15&lt;/button&gt;
      &lt;button data-time="1200" class="timer__button"&gt;Snack 20&lt;/button&gt;
      &lt;button data-time="3600" class="timer__button"&gt;Lunch Break&lt;/button&gt;
      &lt;form name="customForm" id="custom"&gt;
        &lt;input type="text" name="minutes" placeholder="Enter Minutes"&gt;
      &lt;/form&gt;
    &lt;/div&gt;
    &lt;div class="display"&gt;
      &lt;h1 class="display__time-left"&gt;&lt;/h1&gt;
      &lt;p class="display__end-time"&gt;&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;script src="scripts.js"&gt;&lt;/script&gt;
&lt;/body&gt;

&lt;/html&gt;
I have the following ideas for improvement of your code:

Separate different concepts like timers and UI rendering to make them easy to understand and change.
Use milliseconds for consistency with browser API.
Separate formatting and calculation for dates and durations.
Incapsulate mutable state in objects so it won't leak in your main application logic (let interval).
Don't use the substr function to format time because this solution is not robust. Write custom formatter or use a library like momentjs instead.

Here is my solution:
class Timer {
    constructor(duration, delay = 1000) {
        this._remaining = duration;
        this._delay = delay;
        this._callbacks = [];
    }

    start() {
        this._intervalId = setInterval(this._tick.bind(this), this._delay);
    }

    stop() {
        clearInterval(this._intervalId);
    }

    onTick(callback) {
        this._callbacks.push(callback);
    }

    _tick() {
        this._remaining -= this._delay;
        if (this._remaining &lt;= 0) this.stop();
        this._callbacks.forEach((cb) =&gt; cb(this._remaining));
    }
}

class Timers {
    makeActive(timer) {
        this._activeTimer = timer;
    }

    stopActive() {
        if (this._activeTimer) this._activeTimer.stop();
    }
}

// I didn't change formatting implementation here because I am lazy
const formatHMS = (date) =&gt; date.toISOString().substr(11, 8);
const formatLocaleHMS = (date) =&gt; date.toLocaleTimeString().substr(0, 8);

const dateIn = (duration) =&gt; {
    const date = new Date(0);
    date.setMilliseconds(Date.now() + duration);
    return date;
}

const durationToDate = (duration) =&gt; {
    const date = new Date(0);
    date.setMilliseconds(duration);
    return date;
}

const timeControls = document.querySelector('.timer__controls');
const timeLeft = document.querySelector('.display__time-left');
const endTime = document.querySelector('.display__end-time');

const displayRemaining = (duration) =&gt; {
    timeLeft.textContent = formatHMS(durationToDate(duration));
}

const displayEnd = (duration) =&gt; {
    endTime.textContent = `Be back at ${formatLocaleHMS(dateIn(duration))}`;
}

const timers = new Timers();

const startAndUpdate = (duration) =&gt; {
    displayRemaining(duration);
    displayEnd(duration);

    const timer = new Timer(duration);
    timer.start();
    timer.onTick(displayRemaining);

    timers.stopActive();
    timers.makeActive(timer);
};

const secondsToMs = (seconds) =&gt; seconds * 1000;
timeControls.addEventListener('click', (e) =&gt; {
    const button = e.target.closest('button');
    if (button) startAndUpdate(secondsToMs(parseInt(button.dataset.time)));
});

const minutesToMs = (minutes) =&gt; secondsToMs(minutes * 60);
document.customForm.addEventListener('submit', function (e) {
    e.preventDefault();
    const value = this.minutes.value;
    if (value !== '') startAndUpdate(minutesToMs(parseInt(value)));
});