From 57ab58cdb4b94e2b806eaa31b375c1a5a699029c Mon Sep 17 00:00:00 2001 From: Mahmoud Shaabo Date: Tue, 31 Mar 2026 23:51:37 +0100 Subject: [PATCH 1/3] feat: implement alarm clock functionality --- Sprint-3/alarmclock/alarmclock.js | 50 ++++++++++++++++++++++++++++++- Sprint-3/alarmclock/index.html | 2 +- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/Sprint-3/alarmclock/alarmclock.js b/Sprint-3/alarmclock/alarmclock.js index 6ca81cd3b..56624fbaf 100644 --- a/Sprint-3/alarmclock/alarmclock.js +++ b/Sprint-3/alarmclock/alarmclock.js @@ -1,4 +1,52 @@ -function setAlarm() {} +// Stores the interval ID so we can clear it later +let interval = null; + +function setAlarm() { + // Clear any previously running countdown + clearInterval(interval); + + // Reset background to default + document.body.style.backgroundColor = ""; + + // Read the input value and convert it to a plain integer (total seconds) + let totalSeconds = parseInt(document.getElementById("alarmSet").value); + + // --- Format and display the initial time --- + // Math.floor(119 / 60) = 1 --> minutes + // 119 % 60 = 59 --> leftover seconds + // padStart(2, "0") ensures single digits become "01", "09", etc. + const mins = String(Math.floor(totalSeconds / 60)).padStart(2, "0"); + const secs = String(totalSeconds % 60).padStart(2, "0"); + document.getElementById("timeRemaining").innerText = + "Time Remaining: " + mins + ":" + secs; + + // --- Start the countdown --- + // setInterval calls the callback every 1000 ms (1 second) and returns an ID + interval = setInterval(function () { + totalSeconds--; // subtract 1 second + + if (totalSeconds <= 0) { + // Stop the interval when time runs out + clearInterval(interval); + + document.getElementById("timeRemaining").innerText = + "Time Remaining: 00:00"; + + // Change background color to signal the alarm + document.body.style.backgroundColor = "red"; + + // Trigger the alarm sound (defined below the DO NOT EDIT line) + playAlarm(); + return; + } + + // Recalculate mm:ss for the new totalSeconds and update the display + const m = String(Math.floor(totalSeconds / 60)).padStart(2, "0"); + const s = String(totalSeconds % 60).padStart(2, "0"); + document.getElementById("timeRemaining").innerText = + "Time Remaining: " + m + ":" + s; + }, 1000); +} // DO NOT EDIT BELOW HERE diff --git a/Sprint-3/alarmclock/index.html b/Sprint-3/alarmclock/index.html index 48e2e80d9..ff2d3b453 100644 --- a/Sprint-3/alarmclock/index.html +++ b/Sprint-3/alarmclock/index.html @@ -4,7 +4,7 @@ - Title here + Alarm clock app
From 04f825499b132031cf4e2d050ec7c31d1816886a Mon Sep 17 00:00:00 2001 From: Mahmoud Shaabo Date: Sun, 5 Apr 2026 17:37:06 +0100 Subject: [PATCH 2/3] fix: address PR review feedback and implement DRY principle --- Sprint-3/alarmclock/alarmclock.js | 65 ++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/Sprint-3/alarmclock/alarmclock.js b/Sprint-3/alarmclock/alarmclock.js index 56624fbaf..7cae0a40d 100644 --- a/Sprint-3/alarmclock/alarmclock.js +++ b/Sprint-3/alarmclock/alarmclock.js @@ -1,6 +1,15 @@ // Stores the interval ID so we can clear it later let interval = null; +// Helper function: format seconds as mm:ss and update the display +// This keeps the time-display logic in ONE place (CJ feedback: avoid repetition) +function updateTimeDisplay(totalSeconds) { + const mins = String(Math.floor(totalSeconds / 60)).padStart(2, "0"); + const secs = String(totalSeconds % 60).padStart(2, "0"); + document.getElementById("timeRemaining").innerText = + "Time Remaining: " + mins + ":" + secs; +} + function setAlarm() { // Clear any previously running countdown clearInterval(interval); @@ -8,20 +17,32 @@ function setAlarm() { // Reset background to default document.body.style.backgroundColor = ""; + // Stop any currently playing alarm sound before starting a new countdown + // (the user may not click "Stop" first before setting a new alarm) + pauseAlarm(); + // Read the input value and convert it to a plain integer (total seconds) let totalSeconds = parseInt(document.getElementById("alarmSet").value); - // --- Format and display the initial time --- - // Math.floor(119 / 60) = 1 --> minutes - // 119 % 60 = 59 --> leftover seconds - // padStart(2, "0") ensures single digits become "01", "09", etc. - const mins = String(Math.floor(totalSeconds / 60)).padStart(2, "0"); - const secs = String(totalSeconds % 60).padStart(2, "0"); - document.getElementById("timeRemaining").innerText = - "Time Remaining: " + mins + ":" + secs; - - // --- Start the countdown --- - // setInterval calls the callback every 1000 ms (1 second) and returns an ID + // Validate input: reject NaN, negative numbers, or empty field + if (isNaN(totalSeconds) || totalSeconds < 0) { + document.getElementById("timeRemaining").innerText = + "Please enter a valid number of seconds (0 or above)."; + return; + } + + // If input is 0, trigger the alarm immediately instead of waiting 1 second + if (totalSeconds === 0) { + updateTimeDisplay(0); + document.body.style.backgroundColor = "red"; + playAlarm(); + return; + } + + // Display the initial time using the helper function + updateTimeDisplay(totalSeconds); + + // Start the countdown: setInterval calls the callback every 1000 ms (1 second) interval = setInterval(function () { totalSeconds--; // subtract 1 second @@ -29,10 +50,9 @@ function setAlarm() { // Stop the interval when time runs out clearInterval(interval); - document.getElementById("timeRemaining").innerText = - "Time Remaining: 00:00"; + updateTimeDisplay(0); - // Change background color to signal the alarm + // Change background colour to signal the alarm document.body.style.backgroundColor = "red"; // Trigger the alarm sound (defined below the DO NOT EDIT line) @@ -40,14 +60,21 @@ function setAlarm() { return; } - // Recalculate mm:ss for the new totalSeconds and update the display - const m = String(Math.floor(totalSeconds / 60)).padStart(2, "0"); - const s = String(totalSeconds % 60).padStart(2, "0"); - document.getElementById("timeRemaining").innerText = - "Time Remaining: " + m + ":" + s; + // Update the display with the new remaining time + updateTimeDisplay(totalSeconds); }, 1000); } +// Make the Stop button also stop the countdown (not just the sound) +// Uses DOMContentLoaded so the button element exists before we attach the listener +// This adds a SECOND listener without modifying the original code below +document.addEventListener("DOMContentLoaded", function () { + document.getElementById("stop").addEventListener("click", function () { + clearInterval(interval); + document.body.style.backgroundColor = ""; + }); +}); + // DO NOT EDIT BELOW HERE var audio = new Audio("alarmsound.mp3"); From 3da5c594f87a76fc83af86d5c114fcc4a6985098 Mon Sep 17 00:00:00 2001 From: Mahmoud Shaabo Date: Tue, 7 Apr 2026 11:33:05 +0100 Subject: [PATCH 3/3] refactor: apply CJ's final feedback for feedback element and classList toggle --- Sprint-3/alarmclock/alarmclock.js | 21 +++++++++++++-------- Sprint-3/alarmclock/index.html | 3 ++- Sprint-3/alarmclock/style.css | 10 ++++++++++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Sprint-3/alarmclock/alarmclock.js b/Sprint-3/alarmclock/alarmclock.js index 7cae0a40d..06dea09dd 100644 --- a/Sprint-3/alarmclock/alarmclock.js +++ b/Sprint-3/alarmclock/alarmclock.js @@ -10,12 +10,18 @@ function updateTimeDisplay(totalSeconds) { "Time Remaining: " + mins + ":" + secs; } +// Helper function: show or clear the feedback message in a separate element +function showFeedback(message) { + document.getElementById("feedback").innerText = message; +} + function setAlarm() { // Clear any previously running countdown clearInterval(interval); - // Reset background to default - document.body.style.backgroundColor = ""; + // Remove alarm style and clear feedback message + document.body.classList.toggle("alarm-activated", false); + showFeedback(""); // Stop any currently playing alarm sound before starting a new countdown // (the user may not click "Stop" first before setting a new alarm) @@ -26,15 +32,14 @@ function setAlarm() { // Validate input: reject NaN, negative numbers, or empty field if (isNaN(totalSeconds) || totalSeconds < 0) { - document.getElementById("timeRemaining").innerText = - "Please enter a valid number of seconds (0 or above)."; + showFeedback("Please enter a valid number of seconds (0 or above)."); return; } // If input is 0, trigger the alarm immediately instead of waiting 1 second if (totalSeconds === 0) { updateTimeDisplay(0); - document.body.style.backgroundColor = "red"; + document.body.classList.toggle("alarm-activated", true); playAlarm(); return; } @@ -52,8 +57,8 @@ function setAlarm() { updateTimeDisplay(0); - // Change background colour to signal the alarm - document.body.style.backgroundColor = "red"; + // Apply alarm style using a CSS class (separates presentation from logic) + document.body.classList.toggle("alarm-activated", true); // Trigger the alarm sound (defined below the DO NOT EDIT line) playAlarm(); @@ -71,7 +76,7 @@ function setAlarm() { document.addEventListener("DOMContentLoaded", function () { document.getElementById("stop").addEventListener("click", function () { clearInterval(interval); - document.body.style.backgroundColor = ""; + document.body.classList.toggle("alarm-activated", false); }); }); diff --git a/Sprint-3/alarmclock/index.html b/Sprint-3/alarmclock/index.html index ff2d3b453..d2b886e5f 100644 --- a/Sprint-3/alarmclock/index.html +++ b/Sprint-3/alarmclock/index.html @@ -1,4 +1,4 @@ - + @@ -9,6 +9,7 @@

Time Remaining: 00:00

+ diff --git a/Sprint-3/alarmclock/style.css b/Sprint-3/alarmclock/style.css index 0c72de38b..351cd8e7c 100644 --- a/Sprint-3/alarmclock/style.css +++ b/Sprint-3/alarmclock/style.css @@ -13,3 +13,13 @@ h1 { text-align: center; } + +#feedback { + text-align: center; + color: red; + font-weight: bold; +} + +.alarm-activated { + background-color: red; +}