counter

by Soya Natsuki

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment-with-locales.min.js"></script>
<!DOCTYPE HTML>
<html>

  <head>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap" rel="stylesheet">
  </head>

  <body>
    <div class="content">
      <div class="row">
        <div class="col-12">
          <div class="card image-card">
            <img src="http://soya.moe:463/CDN/SOYA_Stamp.png" class="card-img-top" alt="soyanyan stamp">
            <div class="card-body">
              <h5 class="fw-bold text-muted">
                소야냥은 얼마나 기다려야 될까요?
              </h5>
              <p class="card-text text-muted">혀니가 일하는동안 소야냥은 졸음을 참으면서 기다리고 있습니다. 오늘은 언제까지 기다려야 될까요?</p>
              
              <div class="form-group">
                <label for="end-time fw-bold text-muted">종료시간</label>
                <input type="datetime-local" class="form-control" id="end-time" />
              </div>
              
              <div class="text-center mt-3 text-muted counter">
                00시간 00분 00초
              </div>
            </div>
            <div class="card-footer bg-white d-flex">
              <button type="button" class="btn btn-outline-success flex-fill me-1 set-timer">
                타이머 설정
              </button>
              <button type="button" class="btn btn-outline-danger flex-fill reset-timer">
                타이머 리셋
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>

</html>

CSS

body {
  height: 100vh;
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: 'Noto Sans KR', sans-serif;
  background-color: #ccc;
}

.content {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 5rem;
}

.image-card {
  width: 25rem;
}

.card-footer {
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}

label {
  margin-bottom: 0.25rem;
}

.counter {
  border-radius: 5px;
  border: 1px rgba(0, 0, 0, 0.175) solid;
  padding: 1rem 0;
  font-size: 2rem;
}

JavaScript

let timer, timerFlag

// on document ready
$(function() {
  // set timer
  $('.set-timer').on('click', function() {
  	// if timer already executed
    if(timerFlag) return
  
    // get input
    const end = $('#end-time').val().replace('T', ' ')

    // check input
    if (end === '') return

    // loop
    timerFlag = true
    timer = setInterval(() => {
      // format input
      const today = moment()
      const to = moment(`${end}:00`)

      // format output
      const hours = moment.duration(to.diff(today)).hours()
      const minutes = moment.duration(to.diff(today)).minutes()
      const seconds = moment.duration(to.diff(today)).seconds()

      // check end condition
      if (hours === 0 && minutes === 0 && seconds === 0) {
        // reset timer
        clearInterval(timer)
        timerFlag = false
        
        // reset input & output
				reset()
        
        // show message
        alert('혀니가 돌아올 시간이에요!')
      }

      // render result
      $('.counter').html(`${hours}시간 ${minutes}분 ${seconds}초`)
    }, 1000)
  })

  // reset timer
  $('.reset-timer').on('click', function() {
    // reset timer
    clearInterval(timer)
    timerFlag = false

		// reset input & output
		reset()
  })
})

// reset input and output
function reset() {
  // reset input
  $('#end-time').val('')

  // reset counter
  $('.counter').html('00시간 00분 00초')
}