diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6f3a291 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} \ No newline at end of file diff --git a/theme-clock.zip b/theme-clock.zip new file mode 100644 index 0000000..9225117 Binary files /dev/null and b/theme-clock.zip differ diff --git a/theme-clock/index.html b/theme-clock/index.html index 8b50d24..bce2015 100644 --- a/theme-clock/index.html +++ b/theme-clock/index.html @@ -18,6 +18,16 @@
+
+ + +
+
+ +
+

Time's up! Alarm triggered!

+
+
diff --git a/theme-clock/mixkit-digital-clock-digital-alarm-buzzer-992.wav b/theme-clock/mixkit-digital-clock-digital-alarm-buzzer-992.wav new file mode 100644 index 0000000..9b0b32b Binary files /dev/null and b/theme-clock/mixkit-digital-clock-digital-alarm-buzzer-992.wav differ diff --git a/theme-clock/script.js b/theme-clock/script.js index 5f1126d..4b0889d 100644 --- a/theme-clock/script.js +++ b/theme-clock/script.js @@ -1,48 +1,98 @@ -const hourEl = document.querySelector('.hour') -const minuteEl = document.querySelector('.minute') -const secondEl = document.querySelector('.second') -const timeEl = document.querySelector('.time') -const dateEl = document.querySelector('.date') -const toggle = document.querySelector('.toggle') +const hourEl = document.querySelector('.hour'); +const minuteEl = document.querySelector('.minute'); +const secondEl = document.querySelector('.second'); +const timeEl = document.querySelector('.time'); +const dateEl = document.querySelector('.date'); +const toggle = document.querySelector('.toggle'); +const alarmTimeEl = document.querySelector('#alarm-time'); +const setAlarmButton = document.querySelector('.set-alarm'); +const alarmStatusEl = document.querySelector('.alarm-status'); +const alarmNotification = document.querySelector('#alarm-notification'); +const weatherLocationEl = document.querySelector('.weather-location'); +const weatherDescriptionEl = document.querySelector('.weather-description'); +const weatherTempEl = document.querySelector('.weather-temp'); const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; +let alarmTime = null; + +// Load the alarm sound +const alarmSound = new Audio('./mixkit-digital-clock-digital-alarm-buzzer-992.wav'); + toggle.addEventListener('click', (e) => { - const html = document.querySelector('html') + const html = document.querySelector('html'); if (html.classList.contains('dark')) { - html.classList.remove('dark') - e.target.innerHTML = 'Dark mode' + html.classList.remove('dark'); + e.target.innerHTML = 'Dark mode'; + } else { + html.classList.add('dark'); + e.target.innerHTML = 'Light mode'; + } +}); + +setAlarmButton.addEventListener('click', () => { + alarmTime = alarmTimeEl.value; + if (alarmTime) { + alarmStatusEl.textContent = `Alarm set for ${alarmTime}`; } else { - html.classList.add('dark') - e.target.innerHTML = 'Light mode' + alarmStatusEl.textContent = 'Please set a valid time for the alarm'; } -}) +}); function setTime() { const time = new Date(); - const month = time.getMonth() - const day = time.getDay() - const date = time.getDate() - const hours = time.getHours() - const hoursForClock = hours >= 13 ? hours % 12 : hours; - const minutes = time.getMinutes() - const seconds = time.getSeconds() - const ampm = hours >= 12 ? 'PM' : 'AM' - - hourEl.style.transform = `translate(-50%, -100%) rotate(${scale(hoursForClock, 0, 12, 0, 360)}deg)` - minuteEl.style.transform = `translate(-50%, -100%) rotate(${scale(minutes, 0, 60, 0, 360)}deg)` - secondEl.style.transform = `translate(-50%, -100%) rotate(${scale(seconds, 0, 60, 0, 360)}deg)` - - timeEl.innerHTML = `${hoursForClock}:${minutes < 10 ? `0${minutes}` : minutes} ${ampm}` - dateEl.innerHTML = `${days[day]}, ${months[month]} ${date}` + const month = time.getMonth(); + const day = time.getDay(); + const date = time.getDate(); + const hours = time.getHours(); + const hoursForClock = hours % 12 || 12; // Adjust for 12-hour format + const minutes = time.getMinutes(); + const seconds = time.getSeconds(); + const ampm = hours >= 12 ? 'PM' : 'AM'; + + hourEl.style.transform = `translate(-50%, -100%) rotate(${scale(hoursForClock, 0, 12, 0, 360)}deg)`; + minuteEl.style.transform = `translate(-50%, -100%) rotate(${scale(minutes, 0, 60, 0, 360)}deg)`; + secondEl.style.transform = `translate(-50%, -100%) rotate(${scale(seconds, 0, 60, 0, 360)}deg)`; + + timeEl.innerHTML = `${hoursForClock}:${minutes.toString().padStart(2, '0')} ${ampm}`; + dateEl.innerHTML = `${days[day]}, ${months[month]} ${date}`; } -// StackOverflow https://stackoverflow.com/questions/10756313/javascript-jquery-map-a-range-of-numbers-to-another-range-of-numbers -const scale = (num, in_min, in_max, out_min, out_max) => { - return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +function checkAlarm() { + const time = new Date(); + const hours = time.getHours(); + const minutes = time.getMinutes(); + const currentTime = `${hours}:${minutes.toString().padStart(2, '0')}`; + + if (alarmTime && currentTime === alarmTime) { + alarmSound.play(); // Play alarm sound + showAlarmNotification(); // Show the notification + alarmTime = null; // Reset alarm after triggering + alarmStatusEl.textContent = 'No alarm set'; + } +} + +// Show the alarm notification on the webpage +function showAlarmNotification() { + alarmNotification.classList.add('show'); // Show the notification + setTimeout(() => { + alarmNotification.classList.remove('show'); // Hide the notification after 5 seconds + }, 5000); // Notification disappears after 5 seconds } -setTime() -setInterval(setTime, 1000) +// Scale function for time rotation +const scale = (num, in_min, in_max, out_min, out_max) => { + return ((num - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min; +}; + +// Set the clock and weather widget +setTime(); +setInterval(() => { + setTime(); + checkAlarm(); // Check if the alarm time is reached +}, 1000); + +// Initialize weather widget +getLocation(); diff --git a/theme-clock/style.css b/theme-clock/style.css index aa33562..2d17118 100644 --- a/theme-clock/style.css +++ b/theme-clock/style.css @@ -1,4 +1,4 @@ -@import url('https://fonts.googleapis.com/css?family=Heebo:300&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Heebo:wght@300;400&display=swap'); * { box-sizing: border-box; @@ -7,58 +7,71 @@ :root { --primary-color: #000; --secondary-color: #fff; + --accent-color: #4caf50; + --danger-color: #e74c3c; + --background-color: #f9f9f9; + --shadow-color: rgba(0, 0, 0, 0.2); } html { - transition: all 0.5s ease-in; + transition: all 0.5s ease-in-out; } html.dark { --primary-color: #fff; --secondary-color: #333; -} - -html.dark { - background-color: #111; - color: var(--primary-color); + --background-color: #111; + --shadow-color: rgba(255, 255, 255, 0.2); } body { font-family: 'Heebo', sans-serif; + background-color: var(--background-color); + color: var(--primary-color); display: flex; align-items: center; justify-content: center; height: 100vh; - overflow: hidden; margin: 0; + overflow: hidden; } .toggle { cursor: pointer; - background-color: var(--primary-color); + background-color: var(--accent-color); color: var(--secondary-color); border: 0; - border-radius: 4px; - padding: 8px 12px; + border-radius: 50px; + padding: 10px 20px; position: absolute; - top: 100px; + top: 20px; + right: 20px; + font-size: 16px; + font-weight: 400; + box-shadow: 0 4px 6px var(--shadow-color); + transition: all 0.3s ease-in-out; } -.toggle:focus { - outline: none; +.toggle:hover { + background-color: var(--primary-color); + color: var(--accent-color); + transform: scale(1.05); } .clock-container { display: flex; flex-direction: column; - justify-content: space-between; align-items: center; + gap: 20px; } .clock { position: relative; - width: 200px; - height: 200px; + width: 250px; + height: 250px; + background: linear-gradient(145deg, #05b54e, #ffffff); + border-radius: 50%; + box-shadow: inset 0 4px 6px var(--shadow-color), 0 6px 10px var(--shadow-color); } .needle { @@ -66,58 +79,50 @@ body { position: absolute; top: 50%; left: 50%; - height: 65px; - width: 3px; + width: 4px; + border-radius: 2px; transform-origin: bottom center; - transition: all 0.5s ease-in linear; + transition: all 0.5s ease-in-out; } .needle.hour { + height: 70px; transform: translate(-50%, -100%) rotate(0deg); } .needle.minute { - transform: translate(-50%, -100%) rotate(0deg); height: 100px; + transform: translate(-50%, -100%) rotate(0deg); } .needle.second { + height: 110px; + background-color: var(--danger-color); transform: translate(-50%, -100%) rotate(0deg); - height: 100px; - background-color: #e74c3c; } .center-point { - background-color: #e74c3c; - width: 10px; - height: 10px; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - border-radius: 50%; -} - -.center-point::after { - content: ''; - background-color: var(--primary-color); - width: 5px; - height: 5px; + background-color: var(--danger-color); + width: 12px; + height: 12px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border-radius: 50%; + box-shadow: 0 2px 4px var(--shadow-color); } .time { - font-size: 60px; + font-size: 50px; + font-weight: 400; + letter-spacing: 1px; } .date { - color: #aaa; - font-size: 14px; - letter-spacing: 0.3px; + color: var(--accent-color); + font-size: 16px; + letter-spacing: 0.5px; text-transform: uppercase; } @@ -125,12 +130,65 @@ body { background-color: var(--primary-color); color: var(--secondary-color); border-radius: 50%; - height: 18px; - width: 18px; + height: 20px; + width: 20px; display: inline-flex; align-items: center; justify-content: center; - line-height: 18px; - transition: all 0.5s ease-in; + line-height: 20px; font-size: 12px; -} \ No newline at end of file + transition: all 0.5s ease-in-out; + box-shadow: 0 2px 4px var(--shadow-color); +} + +.alarm-container { + margin-top: 20px; + text-align: center; +} + +.set-alarm { + cursor: pointer; + background-color: var(--accent-color); + color: var(--secondary-color); + border: 0; + border-radius: 50px; + padding: 10px 20px; + font-size: 16px; + font-weight: 400; + margin-top: 10px; + transition: all 0.3s ease-in-out; +} + +.set-alarm:hover { + background-color: var(--primary-color); + color: var(--accent-color); + transform: scale(1.05); +} + +.alarm-status { + margin-top: 10px; + font-size: 16px; + color: var(--danger-color); +} +.alarm-notification { + position: fixed; + top: 20px; + left: 50%; + transform: translateX(-50%); + background-color: var(--danger-color); + color: var(--secondary-color); + padding: 15px; + border-radius: 8px; + font-size: 16px; + font-weight: bold; + opacity: 0; + visibility: hidden; + transition: opacity 0.5s ease, visibility 0.5s ease; + box-shadow: 0 4px 6px var(--shadow-color); +} + +.alarm-notification.show { + opacity: 1; + visibility: visible; +} +