JSFiddle - React, Tailwind, and code Playground

by suhyunified

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>@import './index.css';</style>
</head>
<body>
  <div class="wrapper">
    <div id="progress-bar">
      <div id="progress-status"></div>
    </div>
    <button id="run-button">Run <b id="times">0</b></button>
  </div>
  <script type="text/javascript" src="./index.js"></script>
</body>
</html>

CSS

body {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

#progress-bar {
  position: relative;
  width: 500px;
  height: 30px;
  overflow: hidden;
  border-radius: 6px;
  background-color: #dedede;
}

#progress-status {
  position: absolute;
  height: 100%;
  width: 0%;
  background-color: violet;
}

button {
  margin-top: 20px;
}

JavaScript

const runButton = document.getElementById('run-button')

runButton.addEventListener('click', () => {
  run()
})

const useQueue = () => {
  const queue = []
  const countElement = document.getElementById('times')

  const addQueue = (v) => {
    queue.push(v)
    countElement.innerHTML = getLength()
  }

  const popQueue = () => {
    queue.shift()
    countElement.innerHTML = getLength()
  }

  const getLength = () => {
    return queue.length
  }

  return {addQueue, popQueue, getLength}
}

const useRunning = () => {
  let isRunning = false

  const setRunning = (v) => {
    isRunning = v
  }

  const getRunning = () => isRunning

  return {
    getRunning,
    setRunning
  }
}

const { addQueue, popQueue, getLength} = useQueue()
const { getRunning, setRunning } = useRunning()

const run = () => {
  addQueue(1)

  if (getRunning()) return

  runProgress()
}

const runProgress = async () => {
  
  setRunning(true)
  await download()
  setRunning(false)
  popQueue()

  if (getLength() > 0){
    runProgress()
  }
}

const download = () => {
  let progress = 0
  const progressStatus = document.getElementById('progress-status')

  return new Promise((resolve) => {
    const id = setInterval(() => {
      progress += 1
      progressStatus.style.width = `${progress}%`
  
      if (progress >= 100) {
        resolve(true)

        progress = 0
        progressStatus.style.width = `${0}%`
        clearInterval(id)
      }
  }, 10)
  })
}