Skip to content

Commit fa8a832

Browse files
Merge pull request #823 from nancysangani/fix/skills-input-not-functioning
fix: hoist window.addSkill and remove duplicate broken submit listener
2 parents c8fecdf + 1d2c358 commit fa8a832

1 file changed

Lines changed: 85 additions & 149 deletions

File tree

static/script.js

Lines changed: 85 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,48 @@ function recordSearch() {
194194

195195
function normalizeSkill(skill) { return skill.trim().toLowerCase(); }
196196

197-
function isSkillSelected(skill) {
198-
var normalizedSkill = normalizeSkill(skill);
199-
return selectedSkills.some(function (s) { return normalizeSkill(s) === normalizedSkill; });
197+
loadProgressState();
198+
updateProfileWidgets();
199+
200+
(function initIndexPage() {
201+
var form = document.getElementById("recommend-form");
202+
if (!form) return;
203+
204+
var submitBtn = document.getElementById("submit-btn");
205+
var btnLabel = document.getElementById("btn-label");
206+
var btnLoading = document.getElementById("btn-loading");
207+
var resultsSection = document.getElementById("results-section");
208+
var resultsGrid = document.getElementById("results-grid");
209+
var resultsLoadingEl = document.getElementById("results-loading");
210+
var resultsEmptyEl = document.getElementById("results-empty");
211+
var emptyMessageEl = document.getElementById("empty-message");
212+
var skillsHidden = document.getElementById("skills");
213+
var skillsInput = document.getElementById("skills-input");
214+
var selectedChips = document.getElementById("skill-chips-selected");
215+
var suggestions = document.getElementById("skills-suggestions");
216+
var skillWrap = document.getElementById("skill-input-wrap");
217+
var quickPickChips = Array.prototype.slice.call(document.querySelectorAll(".skill-chip"));
218+
var selectedSkills = [];
219+
var availableSkills = (typeof skills !== "undefined" && Array.isArray(skills))
220+
? skills.map(function (item) { return item.label; }).filter(Boolean)
221+
: quickPickChips.map(function (chip) { return chip.getAttribute("data-skill"); });
222+
var activeSuggestionIndex = -1;
223+
var visibleSuggestions = [];
224+
var SAVED_PROJECTS_KEY = "devpathSavedProjects";
225+
226+
window.addSkill = function addSkill(rawSkill) {
227+
var skill = canonicalSkill(rawSkill);
228+
if (!skill || isSelected(skill)) return;
229+
selectedSkills.push(skill);
230+
renderSelectedChips();
231+
syncSkillsHiddenInput();
232+
updateQuickPickState();
233+
clearFieldError("skills-error");
234+
if (skillsInput) skillsInput.focus();
235+
};
236+
237+
function normalize(value) {
238+
return String(value || "").trim().toLowerCase();
200239
}
201240

202241
function getCanonicalSkill(rawSkill) {
@@ -327,20 +366,6 @@ function recordSearch() {
327366
if (skillWrap && !skillWrap.contains(evt.target)) hideSuggestions();
328367
});
329368

330-
//add a skill to the list if it's not empty or a duplicate
331-
function addSkill(rawSkill) {
332-
var skill = getCanonicalSkill(rawSkill);
333-
if (!skill) return;
334-
if (isSkillSelected(skill)) return;
335-
selectedSkills.push(skill);
336-
renderSelectedChips();
337-
syncSkillsHiddenInput();
338-
updateQuickPickState();
339-
// Once a skill is added, remove the "please add a skill" error if it was showing
340-
clearFieldError("skills-error");
341-
}
342-
343-
// remove a skill from the list and update the UI accordingly
344369
function removeSkill(skill) {
345370
// Rebuild the array without the skill that was just removed
346371
selectedSkills = selectedSkills.filter(function (s) { return normalizeSkill(s) !== normalizeSkill(skill); });
@@ -690,138 +715,7 @@ function recordSearch() {
690715
// Form submission and API call
691716
// ----------------------------------------------------------
692717

693-
form.addEventListener("submit", function (evt) {
694-
evt.preventDefault(); //stop the browser from reloading the page on form submit
695-
clearAllErrors()
696-
697-
clearAllErrors();
698-
699-
if (skillsInput.value.trim()) {
700-
addSkill(skillsInput.value);
701-
skillsInput.value = "";
702-
hideSuggestions();
703-
}
704-
705-
if (!validateForm()) return; //stop - anything missing/invalid
706-
707-
setLoadingState(true);
708-
709-
// Allow browser to paint spinner before request starts
710-
requestAnimationFrame(function () {
711-
712-
var payload = {
713-
//combine form values into an object to send to server/api
714-
var payload = {
715-
skills: skillsHidden.value.trim() || skillsTextInput.value.trim(),
716-
level: document.getElementById("level").value,
717-
interest: document.getElementById("interest").value,
718-
time: document.getElementById("time").value
719-
};
720-
721-
fetch("/api/recommend", {
722-
method: "POST",
723-
headers: { "Content-Type": "application/json" },
724-
body: JSON.stringify(payload)
725-
})
726-
.then(function (res) {
727-
return res.json();
728-
})
729-
.then(function (data) {
730-
console.log("API Response:", data);
731-
setLoadingState(false);
732-
evt.preventDefault();
733-
734-
clearAllErrors();
735-
736-
if (skillsTextInput.value.trim()) {
737-
addSkill(skillsTextInput.value);
738-
skillsTextInput.value = "";
739-
hideSuggestions();
740-
}
741-
742-
if (!validateForm()) return;
743-
744-
setLoadingState(true);
745-
746-
renderResults(data.projects || [], data.message);
747-
renderResults(Array.isArray(data.projects) ? data.projects : [], data.message);
748-
})
749-
.catch(function (err) {
750-
setLoadingState(false);
751-
var generalErr = document.getElementById("form-error-general");
752-
if (generalErr) {
753-
generalErr.textContent = "Something went wrong. Please try again.";
754-
}
755-
});
756-
})
757-
758-
});
759-
760-
};
761-
762-
requestAnimationFrame(function () {
763-
764-
var payload = {
765-
skills: skillsHidden.value.trim() || skillsTextInput.value.trim(),
766-
level: document.getElementById("level").value,
767-
interest: document.getElementById("interest").value,
768-
time: document.getElementById("time").value
769-
};
770-
771-
fetch("/api/recommend", {
772-
method: "POST",
773-
headers: {
774-
"Content-Type": "application/json"
775-
},
776-
body: JSON.stringify(payload)
777-
})
778-
.then(function (res) {
779-
return res.json();
780-
})
781-
.then(function (data) {
782-
783-
setLoadingState(false);
784-
785-
if (data.error) {
786-
var generalErr = document.getElementById("form-error-general");
787-
if (generalErr) {
788-
generalErr.textContent = "Network error. Please try again.";
789-
}
790-
});
791-
});
792-
});
793-
generalErr.textContent = "An unexpected error occurred. Please try again.";
794-
}
795-
console.error("API request failed:", err);
796-
});
797-
});
798-
});
799-
//post the data to backend api as JSON, then handle the response
800-
fetch("/api/recommend", {
801-
method: "POST",
802-
headers: { "Content-Type": "application/json" },
803-
body: JSON.stringify(payload)
804-
})
805-
.then(function (res) { return res.json(); })
806-
.then(function (data) {
807-
setLoadingState(false);
808-
if (data.error) {
809-
var generalErr = document.getElementById("form-error-general");
810-
if (generalErr) generalErr.textContent = data.error;
811-
return;
812-
}
813-
renderResults(data.projects || [], data.message);
814-
})
815-
.catch(function (err) {
816-
setLoadingState(false);
817-
var generalErr = document.getElementById("form-error-general");
818-
if (generalErr) generalErr.textContent = "Something went wrong. Please try again.";
819-
console.error(err);
820-
});
821-
});
822-
});
823-
824-
718+
// Manages the loading state of the form and results section(whats visible or not)
825719
function setLoadingState(isLoading) {
826720
// Disable the button so the user can't accidentally submit twice
827721
submitBtn.disabled = isLoading;
@@ -887,6 +781,48 @@ function recordSearch() {
887781
return span;
888782
}
889783

784+
//takes the array of projects from the api and draws them on the page as cards
785+
//if array is empty it shows the "no results" message instead
786+
function renderResults(projects, message) {
787+
console.log("Rendering results with projects:", projects);
788+
console.log("Message:", message);
789+
790+
resultsSection.style.display = "block";
791+
resultsLoadingEl.style.display = "none";
792+
// Clear out any cards from a previous search before showing new ones
793+
resultsGrid.innerHTML = "";
794+
recordSearch();
795+
796+
if (!projects || projects.length === 0) {
797+
resultsGrid.style.display = "none";
798+
resultsEmptyEl.style.display = "block";
799+
800+
// Show a friendly custom message when the user selected an interest
801+
var selectedInterest = document.getElementById("interest")?.value;
802+
if (selectedInterest) {
803+
emptyMessageEl.textContent = "No projects are currently available for this interest. Please check back later or try a different area.";
804+
} else if (message) {
805+
emptyMessageEl.textContent = message;
806+
} else {
807+
emptyMessageEl.textContent = "Try adjusting your skills or choosing a different interest area.";
808+
}
809+
810+
// Clear out previous results before rendering new ones
811+
resultsGrid.innerHTML = "";
812+
813+
// If no projects are returned, show the empty state message
814+
if (!projects || projects.length === 0) {
815+
resultsGrid.style.display = "none";
816+
resultsEmptyEl.style.display = "block";
817+
818+
projects.forEach(function (project) {
819+
resultsGrid.appendChild(buildProjectCard(project));
820+
});
821+
822+
recordSearch();
823+
resultsSection.scrollIntoView({ behavior: "smooth" });
824+
}
825+
890826
function buildProjectCard(project) {
891827

892828
var card = document.createElement("div");

0 commit comments

Comments
 (0)