diff --git a/assets/pipe.mp3 b/assets/pipe.mp3 new file mode 100644 index 0000000..56f6001 Binary files /dev/null and b/assets/pipe.mp3 differ diff --git a/countdown/index.html b/countdown/index.html new file mode 100644 index 0000000..2fc9189 --- /dev/null +++ b/countdown/index.html @@ -0,0 +1,28 @@ + + + + + + + + + zy's Countdown + + + +
+ Stopwatch + + + + 00:00:00:00 + + + +
+ + + + + + \ No newline at end of file diff --git a/countdown/index.js b/countdown/index.js new file mode 100644 index 0000000..520323e --- /dev/null +++ b/countdown/index.js @@ -0,0 +1,71 @@ +const time = document.getElementById('time'); +const start = document.getElementById('start'); +const reset = document.getElementById('reset'); +const hoursInput = document.getElementById('hours-input'); +const minutesInput = document.getElementById('minutes-input'); +const secondsInput = document.getElementById('seconds-input'); +const sound = new Audio('/assets/pipe.mp3'); + +let timer = null; +let isActive = false; +let remainingTime = 0; + +function formatTime(duration) { + const milliseconds = Math.floor((duration % 1000) / 10); + const seconds = Math.floor((duration / 1000) % 60); + const minutes = Math.floor((duration / 1000 / 60) % 60); + const hours = Math.floor(duration / 1000 / 60 / 60); + return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}:${String(milliseconds).padStart(2, '0')}`; +} + +start.addEventListener('click', () => { + if (!isActive) { + const hours = parseInt(hoursInput.value, 10) || 0; + const minutes = parseInt(minutesInput.value, 10) || 0; + const seconds = parseInt(secondsInput.value, 10) || 0; + + if (hours < 0 || minutes < 0 || minutes > 59 || seconds < 0 || seconds > 59) { + alert("Please enter valid time values."); + return; + } + + remainingTime = (hours * 3600 + minutes * 60 + seconds) * 1000; + + if (remainingTime <= 0) { + alert("Please enter a valid time duration."); + return; + } + + isActive = true; + start.innerHTML = "Stop"; + + timer = setInterval(() => { + remainingTime -= 10; + if (remainingTime <= 0) { + clearInterval(timer); + sound.play(); + time.textContent = "00:00:00:00"; + isActive = false; + start.innerHTML = "Start"; + } else { + time.textContent = formatTime(remainingTime); + } + }, 10); + } else { + isActive = false; + clearInterval(timer); + start.innerHTML = "Start"; + } +}); + +reset.addEventListener('click', () => { + isActive = false; + clearInterval(timer); + timer = null; + remainingTime = 0; + time.textContent = "00:00:00:00"; + start.innerHTML = "Start"; + hoursInput.value = ""; + minutesInput.value = ""; + secondsInput.value = ""; +}); diff --git a/countdown/style.css b/countdown/style.css new file mode 100644 index 0000000..a23ee08 --- /dev/null +++ b/countdown/style.css @@ -0,0 +1,76 @@ +@import url(/global.css); + +input { + width: 70px; + padding: 12px; + margin: 10px 5px; + border: 2px solid #5a5a5a; + border-radius: 6px; + background-color: #2a2a2a; + color: #ffffff; + font-size: 16px; + text-align: center; + transition: border-color 0.3s ease, box-shadow 0.3s ease; +} + +input:focus { + border-color: #4caf50; + box-shadow: 0 0 5px #4caf50; + outline: none; +} + +button { + padding: 12px 20px; + border: none; + border-radius: 6px; + background-color: #4caf50; + color: #ffffff; + font-size: 16px; + cursor: pointer; + margin: 10px 5px; + font-weight: bold; + transition: background-color 0.3s ease, transform 0.2s ease; +} + +button:hover { + background-color: #45a049; + transform: translateY(-2px); +} + +button:active { + background-color: #3e8e41; + transform: translateY(0); +} + +div.main { + padding: 50px; + background-color: #3a3a3a; + border-radius: 10px; + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); + text-align: center; + max-width: 600px; + margin: 50px auto; +} + +span#time { + font-size: 36px; + font-weight: bold; + display: block; + margin: 25px 0; + color: #f5f5f5; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +a { + bottom: 20px; + left: 20px; + position: absolute; + color: #b3b3b3; + text-decoration: none; + font-size: 14px; + transition: color 0.3s ease; +} + +a:hover { + color: #ffffff; +} diff --git a/global.css b/global.css index 0841991..29c5c72 100644 --- a/global.css +++ b/global.css @@ -19,6 +19,9 @@ body { background-color: #2a2a2a; color: #f0f0f0; overflow-x: hidden; +} + +* { font-family: 'Hack', 'JetBrainsMono', monospace; } diff --git a/timer/index.html b/timer/index.html new file mode 100644 index 0000000..5804d1b --- /dev/null +++ b/timer/index.html @@ -0,0 +1,25 @@ + + + + + + + + zy's Timer + + +
+ 00:00:00:00 +
+ + + +
+ Countdown + +
+ + + + + \ No newline at end of file diff --git a/timer/index.js b/timer/index.js new file mode 100644 index 0000000..ecfff0d --- /dev/null +++ b/timer/index.js @@ -0,0 +1,54 @@ +const time = document.getElementById('time'); +const start = document.getElementById('start'); +const reset = document.getElementById('reset'); +const lap = document.getElementById('lap'); +const lapList = document.getElementById('lap-list'); + +let isActive = false; +let timer = null; +let startTime = null; +let elapsedTime = 0; + +function formatTime(duration) { + const milliseconds = Math.floor((duration % 1000) / 10); + const seconds = Math.floor((duration / 1000) % 60); + const minutes = Math.floor((duration / 1000) / 60); + const hours = Math.floor((duration / 1000) / 60 / 60); + return ` + ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}:${String(milliseconds).padStart(2, '0')}`; +} + +start.addEventListener('click', () => { + if (! isActive) { + isActive = true; + start.innerHTML = "Stop"; + startTime = Date.now() - elapsedTime; + timer = setInterval(() => { + elapsedTime = Date.now() - startTime; + time.textContent = formatTime(elapsedTime); + }, 10); + } else { + isActive = false; + clearInterval(timer); + start.innerHTML = "Start"; + } +}); + +reset.addEventListener('click', () => { + isActive = false; + clearInterval(timer); + timer = null; + startTime = null; + elapsedTime = 0; + time.textContent = "00:00:00:00"; + start.innerHTML = "Start"; + lapList.innerHTML = ""; +}); + +lap.addEventListener('click', () => { + if (isActive) { + const lapTime = document.createElement('li'); + lapTime.textContent = formatTime(elapsedTime); + lapList.appendChild(lapTime); + } +}); diff --git a/timer/style.css b/timer/style.css new file mode 100644 index 0000000..5e00b8d --- /dev/null +++ b/timer/style.css @@ -0,0 +1,82 @@ +@import url(/global.css); + +div.main { + padding: 60px; + display: grid; + justify-content: center; + background-color: #3a3a3a; + border-radius: 10px; + margin: 50px auto; + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); + max-width: 600px; + text-align: center; +} + +div.main button { + margin: 0 10px; + cursor: pointer; + color: #fff; + border: none; + padding: 15px 25px; + font-size: 16px; + font-weight: bold; + transition: background-color 0.3s ease, transform 0.1s ease; + border-radius: 8px; +} + +#time { + margin-bottom: 30px; + font-size: 36px; + font-weight: 700; + color: #f5f5f5; +} + +.buttons { + display: flex; + justify-content: center; + gap: 10px; +} + +#start { + background-color: #4caf50; + border: 2px solid #4caf50; +} + +#lap { + background-color: #3b5998; + border: 2px solid #3b5998; +} + +#reset { + background-color: #f44336; + border: 2px solid #f44336; +} + +#start:hover { + background-color: #45a049; + transform: scale(1.01); +} + +#lap:hover { + background-color: #2e486f; + transform: scale(1.01); +} + +#reset:hover { + background-color: #e53935; + transform: scale(1.01); +} + +a { + position: fixed; + bottom: 20px; + left: 20px; + color: #b3b3b3; + text-decoration: none; + font-size: 14px; + transition: color 0.2s ease; +} + +a:hover { + color: #fff; +}