diff --git a/js/app.js b/js/app.js
index 5dc8d87..6f739ce 100644
--- a/js/app.js
+++ b/js/app.js
@@ -1,5 +1,5 @@
const STORAGE_SAVE_KEY = "launchdesk-v1-items";
-const STORAGE_LOAD_KEY = "launchdesk-items-v1"; // Intentional bug: this key should match STORAGE_SAVE_KEY.
+// Fixed:Intentional bug: this key should match STORAGE_SAVE_KEY.
const demoChecks = [
{
@@ -91,7 +91,7 @@ const activityLog = document.getElementById("activityLog");
let checks = loadChecks();
let currentView = checks;
-form.addEventListener("submit", (event) => handleAddChek(event)); // Intentional bug: misspelled function name.
+form.addEventListener("submit", (event) => handleAddCheck(event)); // Fixed:Intentional bug: misspelled function name.
searchInput.addEventListener("input", applyFilters);
statusFilter.addEventListener("change", applyFilters);
priorityFilter.addEventListener("change", applyFilters);
@@ -104,7 +104,7 @@ renderApp();
logActivity("Demo data loaded. Start by testing the checklist workflows.");
function loadChecks() {
- const saved = localStorage.getItem(STORAGE_LOAD_KEY);
+ const saved = localStorage.getItem(STORAGE_SAVE_KEY);
if (!saved) {
return [...demoChecks];
@@ -132,8 +132,8 @@ function handleAddCheck(event) {
const owner = ownerInput.value.trim() || "Unassigned";
const dueDate = dueDateInput.value || new Date().toISOString().slice(0, 10);
- if (!title && !category) {
- // Intentional bug: validation should stop when either required field is missing.
+ if (!title || !category) {
+ // Fixed:Intentional bug: validation should stop when either required field is missing.
formMessage.textContent =
"Please enter a check title and choose a category.";
return;
@@ -164,12 +164,16 @@ function applyFilters() {
const selectedPriority = priorityFilter.value;
let filtered = checks.filter((check) =>
- check.owner.toLowerCase().includes(searchTerm),
- ); // Intentional bug: search should include title, category, priority, status, and owner.
+ check.title.toLowerCase().includes(searchTerm) ||
+ check.category.toLowerCase().includes(searchTerm) ||
+ check.priority.toLowerCase().includes(searchTerm) ||
+ check.status.toLowerCase().includes(searchTerm) ||
+ check.owner.toLowerCase().includes(searchTerm)
+ );
if (selectedStatus !== "All") {
- filtered = filtered.filter((check) => check.priority === selectedStatus);
- } // Intentional bug: status filter compares against priority.
+ filtered = filtered.filter((check) => check.status === selectedStatus);
+ } // Fixed:Intentional bug: status filter compares against priority.
if (selectedPriority !== "All") {
filtered = filtered.filter((check) => check.priority === selectedPriority);
@@ -191,7 +195,7 @@ function renderRows(list) {
const rows = list.map((check) => {
const priorityClass = `priority-${check.priority.toLowerCase()}`;
- const statusClass = `status-${check.status.toLowerCase()}`; // Intentional bug: "In Progress" needs a slug class.
+ const statusClass = `status-${check.status.toLowerCase().replace(" ", "-")}`; // Fixed:Intentional bug: "In Progress" needs a slug class.
return `
@@ -231,11 +235,15 @@ function renderRows(list) {
function updateMetrics() {
const total = checks.length;
- const fixed = checks.filter((check) => check.status === "Complete").length; // Intentional bug: valid fixed status is "Fixed".
+ const fixed = checks.filter((check) => check.status === "Fixed").length; // Fixed:Intentional bug: valid fixed status is "Fixed".
const criticalOpen = checks.filter(
(check) => check.priority === "Critical" && check.status !== "Fixed",
).length;
- const dueSoon = checks.filter((check) => daysUntil(check.dueDate) > 7).length; // Intentional bug: this should count items due within 7 days.
+ const dueSoon = checks.filter((check) => {
+ const days = daysUntil(check.dueDate);
+ return days >= 0 && days <= 7;
+ }).length; // Fixed:Intentional bug: this should count items due within 7 days.
+
const score = total === 0 ? 0 : Math.round((fixed / total) * 100);
totalCount.textContent = total;
@@ -247,13 +255,13 @@ function updateMetrics() {
}
function handleTableClick(event) {
- const deleteButton = event.target.closest("[data-delete-id]"); // Intentional bug: button uses data-remove-id.
+ const deleteButton = event.target.closest("[data-remove-id]"); // Fixed:Intentional bug: button uses data-remove-id.
if (!deleteButton) {
return;
}
- const id = Number(deleteButton.dataset.deleteId);
+ const id = Number(deleteButton.dataset.removeId);
const removed = checks.find((check) => check.id === id);
checks = checks.filter((check) => check.id !== id);
saveChecks();
@@ -278,14 +286,17 @@ function handleStatusChange(event) {
check.status = statusSelect.value;
renderRows(currentView);
logActivity(`Changed "${check.title}" to ${check.status}.`);
- // Intentional bug: status changes should save, update filters, and refresh metrics.
+ saveChecks();
+ applyFilters();
+ updateMetrics();
+ // Fixed:Intentional bug: status changes should save, update filters, and refresh metrics.
}
async function resetDemoData() {
formMessage.textContent = "";
try {
- const response = await fetch("data/launch-seed.json"); // Intentional bug: real file is data/launch-checks.json.
+ const response = await fetch("data/launch-checks.json"); // Fixed:Intentional bug: real file is data/launch-checks.json.
if (!response.ok) {
throw new Error(`Demo data request failed with ${response.status}`);
@@ -312,7 +323,7 @@ function exportCsv() {
"Due Date",
];
const rows = currentView.map((check) => [
- check.name, // Intentional bug: property should be check.title.
+ check.title, // Fixed:Intentional bug: property should be check.title.
check.category,
check.priority,
check.status,
@@ -349,8 +360,12 @@ function logActivity(message) {
function daysUntil(dateValue) {
const today = new Date();
+ today.setHours(0, 0, 0, 0);
+
const target = new Date(dateValue);
- const difference = target.getTime() - today.getTime();
+ target.setHours(0, 0, 0, 0);
+
+ const difference = target - today;
return Math.ceil(difference / 86400000);
}
diff --git a/launchdesk-checks (1).csv b/launchdesk-checks (1).csv
new file mode 100644
index 0000000..f4f47d7
--- /dev/null
+++ b/launchdesk-checks (1).csv
@@ -0,0 +1,7 @@
+"Title","Category","Priority","Status","Owner","Due Date"
+"Contact form tested","Frontend","Critical","Pending","Naveen","2026-05-04"
+"Homepage meta title added","SEO","High","Fixed","Amani","2026-05-02"
+"Mobile navigation checked","QA","High","In Progress","Dilan","2026-05-03"
+"SSL certificate verified","Security","Critical","Blocked","Mira","2026-05-01"
+"Image compression pass complete","Performance","Medium","Pending","Raveen","2026-05-05"
+"Privacy policy linked in footer","Content","Low","Fixed","Ishara","2026-05-06"
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..6a2d5d9
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,12 @@
+{
+ "name": "launchdesk-debugging-lab",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "launchdesk-debugging-lab",
+ "version": "1.0.0"
+ }
+ }
+}