Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/instructor-solution-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ logActivity(`Changed "${check.title}" to ${check.status}.`);
- Broken constants:

```js
const STORAGE_SAVE_KEY = "launchdesk-v1-items";
const STORAGE_LOAD_KEY = "launchdesk-items-v1";
const STORAGE_KEY = "launchdesk-v1-items";
const STORAGE_KEY = "launchdesk-items-v1";
```

- Fix:
Expand Down
46 changes: 26 additions & 20 deletions js/app.js
Original file line number Diff line number Diff line change
@@ -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.
const STORAGE_KEY = "launchdesk-v1-items";
// Intentional bug: this key should match STORAGE_KEY.

const demoChecks = [
{
Expand Down Expand Up @@ -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)); // Intentional bug: misspelled function name.
searchInput.addEventListener("input", applyFilters);
statusFilter.addEventListener("change", applyFilters);
priorityFilter.addEventListener("change", applyFilters);
Expand All @@ -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_KEY);

if (!saved) {
return [...demoChecks];
Expand All @@ -119,7 +119,7 @@ function loadChecks() {
}

function saveChecks() {
localStorage.setItem(STORAGE_SAVE_KEY, JSON.stringify(checks));
localStorage.setItem(STORAGE_KEY, JSON.stringify(checks));
}

function handleAddCheck(event) {
Expand All @@ -132,7 +132,7 @@ function handleAddCheck(event) {
const owner = ownerInput.value.trim() || "Unassigned";
const dueDate = dueDateInput.value || new Date().toISOString().slice(0, 10);

if (!title && !category) {
if (!title || !category) {
// Intentional bug: validation should stop when either required field is missing.
formMessage.textContent =
"Please enter a check title and choose a category.";
Expand Down Expand Up @@ -164,11 +164,15 @@ function applyFilters() {
const selectedPriority = priorityFilter.value;

let filtered = checks.filter((check) =>
check.owner.toLowerCase().includes(searchTerm),
check.owner.toLowerCase().includes(searchTerm) ||
check.title.toLowerCase().includes(searchTerm) ||
check.category.toLowerCase().includes(searchTerm) ||
check.priority.toLowerCase().includes(searchTerm) ||
check.status.toLowerCase().includes(searchTerm),
); // Intentional bug: search should include title, category, priority, status, and owner.

if (selectedStatus !== "All") {
filtered = filtered.filter((check) => check.priority === selectedStatus);
filtered = filtered.filter((check) => check.status === selectedStatus);
} // Intentional bug: status filter compares against priority.

if (selectedPriority !== "All") {
Expand All @@ -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().replaceAll(" ", "-")}`; // Intentional bug: "In Progress" needs a slug class.

return `
<tr>
Expand All @@ -210,12 +214,12 @@ function renderRows(list) {
<span class="row-actions">
<select data-status-id="${check.id}" aria-label="Update status for ${escapeHtml(check.title)}">
${["Pending", "In Progress", "Fixed", "Blocked"]
.map(
(status) => `
.map(
(status) => `
<option value="${status}" ${status === check.status ? "selected" : ""}>${status}</option>
`,
)
.join("")}
)
.join("")}
</select>
<button class="icon-button" type="button" data-remove-id="${check.id}" title="Delete check">
x
Expand All @@ -231,11 +235,11 @@ 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; // 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) => daysUntil(check.dueDate) <= 7).length; // Intentional bug: this should count items due within 7 days.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix incomplete: "Due soon" metric includes overdue items.

The current logic daysUntil(check.dueDate) <= 7 will incorrectly count items with negative days (overdue items). According to the instructor guide (lines 181-184), the fix should also verify that days are non-negative.

🐛 Complete the fix
-  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;

This ensures only items due in the future within 7 days are counted, excluding overdue items.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@js/app.js` at line 242, The dueSoon calculation currently counts overdue
items because it only checks daysUntil(check.dueDate) <= 7; update the filter in
the dueSoon computation (the checks.filter callback where daysUntil is called)
to ensure the returned days are non-negative and at most 7 (e.g., compute days =
daysUntil(check.dueDate) and require days >= 0 && days <= 7) so only items due
within the next 7 days are counted and overdue items are excluded.

const score = total === 0 ? 0 : Math.round((fixed / total) * 100);

totalCount.textContent = total;
Expand All @@ -247,13 +251,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]"); // 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();
Expand All @@ -276,7 +280,9 @@ function handleStatusChange(event) {
}

check.status = statusSelect.value;
renderRows(currentView);
saveChecks();
applyFilters();

logActivity(`Changed "${check.title}" to ${check.status}.`);
// Intentional bug: status changes should save, update filters, and refresh metrics.
}
Expand All @@ -285,7 +291,7 @@ 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"); // Intentional bug: real file is data/launch-checks.json.

if (!response.ok) {
throw new Error(`Demo data request failed with ${response.status}`);
Expand All @@ -312,7 +318,7 @@ function exportCsv() {
"Due Date",
];
const rows = currentView.map((check) => [
check.name, // Intentional bug: property should be check.title.
check.title, // Intentional bug: property should be check.title.
check.category,
check.priority,
check.status,
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"description": "A polished but intentionally broken website launch readiness checker for debugging practice.",
"scripts": {
"dev": "python3 -m http.server 5173",
"dev": "python -m http.server 5173",
"start": "python3 -m http.server 5173"
Comment on lines +7 to 8
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent Python command between dev and start scripts.

The dev script uses python while start uses python3. On systems where python points to Python 2.x, the dev script will fail. For consistency and compatibility, both should use the same command.

🔧 Proposed fix
-    "dev": "python -m http.server 5173",
+    "dev": "python3 -m http.server 5173",
     "start": "python3 -m http.server 5173"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"dev": "python -m http.server 5173",
"start": "python3 -m http.server 5173"
"dev": "python3 -m http.server 5173",
"start": "python3 -m http.server 5173"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 7 - 8, The npm scripts are inconsistent: "dev"
uses python while "start" uses python3; update the package.json scripts so both
"dev" and "start" use the same Python executable (prefer python3 for modern
environments) to avoid Python2 fallback; edit the "dev" entry to match "start"
(or vice versa) so both scripts run "python3 -m http.server 5173" and save the
file.

}
}
}