2020.06.19

  • Style and layout updates! Using grid and font-size: x-vw to have responsive font sizes. Also using a monospaced custom font for the time display and the buttons.
  • There could be a second pass for additional support for smaller screen sizes. It's interesting to think about unit ratios for the screen and what to anchor the ratios from: ie. the content, the screen height/width; other elements on the page. It affects how elements are grouped.
  • I also removed the 15 minute preset, since I was primarily using the 5 and 45 minute settings.
  • Up next: toggle buttons displayed based on the mode that it's in; additional animation transitions when starting and stopping the timer.
body{
  background: #FBFAFF;
  color: #22006A;
  font-size: 2em;
  font-family: 'Roboto Mono', monospace;
}
#root {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
  height: 100vh;
}
.App{
  display: grid;
  grid-template-rows: 1fr auto 1fr;
  grid-template-columns: 1fr auto 1fr;
}
.App, button {
  font-family: 'Roboto Mono', monospace;
  text-align: center;
}
.time-container{
  display: grid;
  grid-template-rows: 3fr 1fr;
  grid-row: 2;
  grid-column: 2;
  align-items: center;
}

#timer {
  transition: color 1.5s ease-out;
  font-size: 28vw;
  grid-row: 1;
}
.button-row{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-row: 2;
  grid-gap: .5em;
}
button{
  font-size: .5em;
  color: #FBFAFF;
  padding: 1.5em 2em;
  background: #6628EA;
  box-shadow: 0px 0px 1px #000000, 0px 4px 6px rgba(50, 50, 93, 0.14);
  border-radius: 4px;
  border: none;
  grid-column: 1fr;
}
button:hover{
  background: #5522BF;
  cursor: pointer;
  position: relative;
  top: -1px;
}
button:active{
  background: #401991;
  top: 0px;
}
.footer{
  font-size: .35em;
  grid-row: 3;
  grid-column: 2;
  display: grid;
  align-items: end;
  grid-template-rows: auto 20px auto;
}
.footer p{
  margin: .15em;
  text-transform: uppercase;
  font-weight: lighter;
}
.footer p:first-child{
  font-weight: bold;
}
import React from "react";
import "./index.css";

export default function App() {
  let timeInterval;
  let flashInterval;
  let timeRemaining;

  function startTimer(initialTime) {
    timeRemaining = (initialTime - 1) * 60;
    timeInterval = setInterval(function() {
      decreaseTime();
    }, 1000);
  }

  function decreaseTime() {
    if (timeRemaining <= 0) {
      stopTimer();
    } else {
      timeRemaining -= 1;
      displayTime(timeRemaining)
      // console.log("Time Remaining " + timeRemaining);
    }
  }

  function displayTime(timeRemaining){
    const minutesRemaining = Math.round(timeRemaining / 60);
    const secondsRemaining = timeRemaining % 60;
    const timeRemainingReadable = minutesRemaining + ":" + secondsRemaining
    const timeElement = document.getElementById('timer');
    timeElement.innerHTML = timeRemainingReadable;
    console.log(timeRemainingReadable);
  }

  function displayMessage(message){
    const messageElement = document.getElementById('timer');
    messageElement.innerHTML = message;
  }

  function stopTimer() {
    clearInterval(timeInterval);
    flashInterval = setInterval(flash, 1500);
    displayMessage("00:00")
    console.log("Time's up");
  }

  function flash() {
    const flashElement = document.getElementById("timer");
    flashElement.style.color =
      flashElement.style.color === "plum"
        ? "rosybrown"
        : "plum";
  }

  function setColor(color){
    const elementBackground = document.getElementById('timer');
    elementBackground.style.color = color;
  }

  function resetTimer() {
    displayMessage("00:00");
    setColor("rosybrown");
    clearInterval(timeInterval);
    clearInterval(flashInterval);
  }

  return (
    <div className="App">
      <div className="time-container">
        <div id="timer">00:00</div>
        <div className="button-row">
          <button onClick={() => startTimer(5)}>5 min</button>
          <button onClick={() => startTimer(45)}>45 min</button>
          <button onClick={resetTimer}>RESET</button>
        </div>
      </div>
      <Footer/>
    </div>
  );
}
function Footer(){
  return(
    <div className="footer">
      <p>Click Click Timer</p>
      <p>Made by Francisco</p>
    </div>
  )
}

2020.06.15

  • Used JavaScript to update the remaining time on the page.
  • Used division and remainder operator % to convert seconds into minutes. I also had to subtract the initial minute so that at 15 minute timer starts with 14:59 vs. 15:59. And I had to use Math.round() to round minutes to the closest interger.
  • I also added a few functions to update the text on the page to when the timer stops and when it's reset. Used innerHTML to replace the text on each interval.
  • The color schemes could use another iteration. Flashing the background when the timer ends catches your eye, but it's also hard on the eyes. Currently using some more subtle colors to not burn the eyes when it flashes. Used transition: color 1.5s ease-out to fade the colors.
  • At this stage, it's more usable. But there's another pass at the type, button sizes color scheme, and spacing.
  • It's functional, and I'm not sure how much React was really necessary for this app.
  • Could be useful to also show/hide the buttons based on the current state of the app.
import React from "react";
import "./index.css";

export default function App() {
  let timeInterval;
  let flashInterval;
  let timeRemaining;

  function startTimer(initialTime) {
    timeRemaining = (initialTime - 1) * 60;
    timeInterval = setInterval(function() {
      decreaseTime();
    }, 1000);
  }

  function decreaseTime() {
    if (timeRemaining <= 0) {
      stopTimer();
    } else {
      timeRemaining -= 1;
      displayTime(timeRemaining)
      // console.log("Time Remaining " + timeRemaining);
    }
  }

  function displayTime(timeRemaining){
    const minutesRemaining = Math.round(timeRemaining / 60);
    const secondsRemaining = timeRemaining % 60;
    const timeRemainingReadable = minutesRemaining + ":" + secondsRemaining
    const timeElement = document.getElementById('timer');
    timeElement.innerHTML = timeRemainingReadable;
    console.log(timeRemainingReadable);
  }

  function displayMessage(message){
    const messageElement = document.getElementById('timer');
    messageElement.innerHTML = message;
  }

  function stopTimer() {
    clearInterval(timeInterval);
    flashInterval = setInterval(flash, 1500);
    displayMessage("00:00")
    console.log("Time's up");
  }

  function flash() {
    const flashElement = document.getElementById("timer");
    flashElement.style.color =
      flashElement.style.color === "plum"
        ? "rosybrown"
        : "plum";
  }

  function setColor(color){
    const elementBackground = document.getElementById('timer');
    elementBackground.style.color = color;
  }

  function resetTimer() {
    displayMessage("00:00");
    setColor("rosybrown");
    clearInterval(flashInterval);
  }

  return (
    <div className="App">
      <h3 id="timer">Pick a timer</h3>
      <button onClick={() => startTimer(5)}>5 minutes</button>
      <button onClick={() => startTimer(15)}>15 minutes</button>
      <button onClick={() => startTimer(45)}>45 minutes</button>
      <button onClick={stopTimer}>Stop</button>
      <button onClick={resetTimer}>Reset</button>
    </div>
  );
}

2020.06.14

https://2bt0h.csb.app
  • Reverted to a functional app without a lot of visual feedback
  • I can manually start the timer and stop the timer. And also manually stop the flashing.
  • Nice to haves would be smoother transitions between the flashes. Indicating remaining time. And manually setting the time. Add styling to buttons. Make the entire page responsive so that it can be a component within another page
  • Included pre-sets, but there's a bug of starting mutliple timers. multiple flashes when the buttons are pressed multiple times.
  • The lack of visual confirmation is the worst part.
import React from "react";
import "./styles.css";

export default function App() {
  let timeInterval;
  let flashInterval;
  let timeRemaining;

  function startTimer(initialTime) {
    timeRemaining = initialTime * 60;
    timeInterval = setInterval(function() {
      decreaseTime();
    }, 1000);
  }
  function decreaseTime() {
    if (timeRemaining <= 0) {
      stopTimer();
    } else {
      timeRemaining -= 1;
      console.log("Time Remaining " + timeRemaining);
    }
  }
  function stopTimer() {
    clearInterval(timeInterval);
    flashInterval = setInterval(flash, 2000);
    console.log("Timer Done!");
  }
  function stopFlash() {
    clearInterval(flashInterval);
  }
  function flash() {
    const flashElement = document.getElementById("timer");
    flashElement.style.background =
      // flashElement.style.background === "#2B8EF1" ? "#ACC9E6" : "#2B8EF1";
      flashElement.style.background === "lightcyan"
        ? "lightskyblue"
        : "lightcyan";
  }
  return (
    <div className="App">
      <h3 id="timer">Timer</h3>
      <button onClick={() => startTimer(5)}>5 minutes</button>
      <button onClick={() => startTimer(15)}>15 minutes</button>
      <button onClick={() => startTimer(45)}>45 minutes</button>
      <button onClick={stopTimer}>Stop</button>
      <button onClick={stopFlash}>Reset</button>
    </div>
  );
}
.App {
  font-family: sans-serif;
  text-align: center;
  color: #002347;
}
#timer {
  height: 50vh;
  line-height: 50vh;
  background: lightcyan;
  font-size: 3em;
}
import React, { useState } from "react";
import "./styles.css";

export default function App() {
  // const [language, setLanguage] = useState("javascript");
  const [timeRemaining, setTimeRemaining] = useState(0);
  const [intervalID, setIntervalID] = useState(0);
  // const [today, setToday] = useState({
  //   date: new Date()
  // });
  
  // function tick() {
  //   setToday({
  //     date: new Date()
  //   });
  // }

  // function countDown() {
  //   setTimeRemaining(timeRemaining - 1);
  //   console.log("decreased time: " + timeRemaining);
  // }

  // function countDown(timeRemaining) {
  //   setTimeRemaining(timeRemaining - 1);
  //   console.log("decreased time: " + timeRemaining);
  //   return timeRemaining;
  // }

  function startTimer(initialTime) {
    console.log("time remaining " + timeRemaining);
    // console.log("interval: " + intervalID);
    // setIntervalID(setInterval(countDown, 5000))

    // setIntervalID(
    //   setInterval( function() { 
    //     countDown(timeRemaining); 
    //   }, 2000 )
    // )

    // setIntervalID(
    //   setInterval( function() { 
    //     tick(); 
    //   }, 2000 )
    // )

    setIntervalID(
      setInterval( function() { 
        countDown(); 
      }, 1000 )
    )

  }

  function countDown() {
    if (timeRemaining <= 0) {
      stopTimer();
    } else {
      setTimeRemaining(timeRemaining - 1);
      console.log(intervalID);
      console.log("Time Remaining " + timeRemaining);
    }
  }

  function stopTimer() {
    console.log(intervalID);
    console.log("Timer Done!");
    clearInterval(intervalID);
  }

  return (
    <div className="App">
      <h3>Timer</h3>
      <p>{timeRemaining}</p>
      {/* <p>{today.date.toLocaleTimeString()}</p> */}
      <button onClick={() => startTimer()}>Start</button>
      {/* <button onClick={() => startTimer(timeRemaining)}>Start</button> */}
      <button onClick={() => setTimeRemaining(10)}>Reset</button>
      <button onClick={() => countDown()}>Count Down</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}

// update time on page
// time remaining is updating. but I'm losing track of setInterval

// create a sound or flash when the timer is done

2020.06.13

  • Creating a timer app
  • Exploring the Date() function, but realizing that implementing it in relatively time works better to support pausing and resuming the timer.
  • The current solution displays a decremented time each second inside the console.
  • Learned how to pass parameters to setInterval, then I realized that I could also update the global variable.
export default function App() {

  let interval;
  let timeRemaining; 

  function startTimer(initialTime) {
    timeRemaining = initialTime * 60
    interval = setInterval( function() { decreaseTime(); }, 1000 );
  }
  function decreaseTime() {
    if (timeRemaining <= 0){
      stopTimer();
    } else {
      timeRemaining -= 1;
      console.log("Time Remaining " + timeRemaining);
    }
  }
  function stopTimer() {
    clearInterval(interval);
    console.log("Timer Done!");
  }

  return (
    <div className="App">
      <h3>Timer</h3>
      <button onClick={() => startTimer(3)}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}

Other Attempts

  • Referenced other snippets to understand how to trigger setInterval
  • There's an example to change the colors on the page. Then I modified it to trigger "hello" every second. This is where I realied that setInterval wasn't working because I was passing a parameter to the function. But the console didn't throw any errors! or it would call it once and stop.
  • Figuring out how to pass parameters into setInterval with an anonymous function. via Stack Overflow


export default function App() {
  var nIntervId;

  function changeColor() {
    nIntervId = setInterval(flashText, 1000);
  }

  function flashText() {
    var oElem = document.getElementById("root");
    oElem.style.color = oElem.style.color == "red" ? "blue" : "red";
    // oElem.style.color == 'red' ? 'blue' : 'red' is a ternary operator.
    console.log(nIntervId);
  }

  function stopTextColor() {
    clearInterval(nIntervId);
    console.log(nIntervId);
  }

  let interval;
    
  function startGreetings() {
    interval = setInterval(sayGreetings, 1000);
  }
  function sayGreetings() {
    console.log("hello");
    console.log(interval);
  }
  function stopGreetings() {
    clearInterval(interval);
    console.log(interval);
  }

  return (
    <div className="App">
      <h3>Timer</h3>
      <h1>5m 00s</h1>
      <button onClick={() => startGreetings()}>Start Greeting</button>
      <button onClick={() => stopGreetings()}>Stop Greeting</button>
      {/* <button onClick={() => changeColor()}>Change Color</button>
      <button onClick={() => stopTextColor()}>Stop Color</button> */}
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}
c
import React from "react";
import "./styles.css";

// startTimer
// calculate total seconds
// update every second
// check

export default function App() {

  var intervalId;

  function decrementTimer(time) {
    time -= 1;
    console.log(time);
  }

  function updateTimer(time) {
    if (time === 0) {
      stopTimer();
    } else {
      // intervalId = setInterval(decrementTimer(time), 1000);
      console.log(time);
      console.log(intervalId);
    }
  }

  function startTimer(time) {
    time = time * 10;
    console.log("start time: " + time);
    // updateTimer(time)
    intervalId = setInterval(decrementTimer(time), 1000);
  }

  function stopTimer() {
    clearInterval(intervalId);
    console.log(intervalId);
  }

return (
    <div className="App">
      <h3>Timer</h3>
      <h1>5m 00s</h1>
      <button onClick={() => startTimer("2")}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}

// start timer
// > type in type to set it
// after timer reaches 0, stop, trigger flash and sound
// start and pause
// reset to set a new time
// have pre-sets

// const currentDate = new Date();
// const currentTime = currentDate.getDay();

// function updateTime(time){
//     if (time = 0) { //syntax error with assignment vs. evaluation
//       stopTimer();
//     } else {
//       time -= 1;
//       // updateTime(time);
//     }
//     return totalTime;
// }

// function testNum(a) {
//   let result;
//   if (a > 0) {
//     result = 'positive';
//   } else {
//     result = 'NOT positive';
//   }
//   console.log(result)
//   return result;
// }

//   {/* <button onClick={startTimer('60')}>Start</button> */}
// {/* <button onClick={() => testNum('-1')}>Test</button> */}