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
Binary file added static/Back-to-top.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
139 changes: 41 additions & 98 deletions static/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,35 @@ var githubInput = document.getElementById('github-username');
var errorMsg = document.getElementById('github-modal-error');


/* ---- Scroll-to-top button ---- */

var scrollBtn = document.querySelector(".back-to-top");

if (scrollBtn) {

// Show the button after scrolling down 300px
window.addEventListener("scroll", function () {

if (window.scrollY > 300) {
scrollBtn.style.display = "block";
} else {
scrollBtn.style.display = "none";
}

});

scrollBtn.addEventListener("click", function () {

window.scrollTo({
top: 0,
behavior: "smooth"
});

});

}


// ============================================================
// Mobile navigation toggle (runs on all pages)
// ============================================================
Expand Down Expand Up @@ -705,53 +734,23 @@ if (isIndexPage) {

setLoadingState(true);

requestAnimationFrame(function () {
renderResults(data.projects || [], data.message);
})
.catch(function () {

var payload = {
skills: skillsHidden.value.trim() || skillsTextInput.value.trim(),
level: document.getElementById("level").value,
interest: document.getElementById("interest").value,
time: document.getElementById("time").value
};
setLoadingState(false);

fetch("/api/recommend", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
})
.then(function (res) {
return res.json();
})
.then(function (data) {

setLoadingState(false);

if (data.error) {
var generalErr = document.getElementById("form-error-general");

if (generalErr) {
generalErr.textContent = data.error;
generalErr.textContent =
"Something went wrong. Please try again.";
}

return;
}

renderResults(data.projects || [], data.message);
})
.catch(function (err) {

setLoadingState(false);

var generalErr = document.getElementById("form-error-general");
});

if (generalErr) {
generalErr.textContent =
"Something went wrong. Please try again.";
}
});

console.error("API request failed:", err);
});
});
});

Expand Down Expand Up @@ -802,8 +801,9 @@ if (isIndexPage) {
// Clear out any cards from a previous search before showing new ones
resultsGrid.innerHTML = "";

if (!projects || projects.length === 0) {
resultsGrid.style.display = "none";

if (!projects || projects.length === 0) { //if no projects returned from api, show the "no results" message and hide the grid
resultsGrid.style.display = "none";
resultsEmptyEl.style.display = "block";

// Show a friendly custom message when the user selected an interest
Expand Down Expand Up @@ -1396,60 +1396,3 @@ updateRoadmapProgress();
});
} // end github modal handlers


// ============================================================
// SCROLL NAVIGATION BUTTON (runs on all pages)
// ============================================================
(function () {
var SCROLL_THRESHOLD = 200;
var scrollTopBtn = document.getElementById('scroll-top-btn');
var scrollBtnIcon = document.getElementById('scroll-btn-icon');
var atBottom = false;

var ARROW_UP = '<polyline points="18 15 12 9 6 15"/>';
var ARROW_DOWN = '<polyline points="6 9 12 15 18 9"/>';

function isNearBottom() {
return (window.innerHeight + window.pageYOffset) >= document.body.scrollHeight - 40;
}

function handleScroll() {
if (!scrollTopBtn) return;
if (window.pageYOffset > SCROLL_THRESHOLD) {
scrollTopBtn.classList.add('visible');
} else {
scrollTopBtn.classList.remove('visible');
}
if (isNearBottom()) {
atBottom = true;
scrollTopBtn.setAttribute('aria-label', 'Scroll to top');
scrollTopBtn.title = 'Scroll to top';
if (scrollBtnIcon) scrollBtnIcon.innerHTML = ARROW_UP;
} else {
atBottom = false;
scrollTopBtn.setAttribute('aria-label', 'Scroll to bottom');
scrollTopBtn.title = 'Scroll to bottom';
if (scrollBtnIcon) scrollBtnIcon.innerHTML = ARROW_DOWN;
}
}

main
if (scrollTopBtn) {
window.addEventListener('scroll', handleScroll, { passive: true });
scrollTopBtn.addEventListener('click', function () {
if (atBottom) {
window.scrollTo({ top: 0, behavior: 'smooth' });
} else {
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
}
});
handleScroll();
}
}());

/* Only wire up listeners if the button exists on this page */
if (scrollTopBtn) {
window.addEventListener('scroll', handleScroll);
scrollTopBtn.addEventListener('click', scrollToTop);
}
main
46 changes: 18 additions & 28 deletions static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -3529,37 +3529,27 @@ html[data-theme="dark"] .btn-view-code-sm {
white-space: pre;
color: #e6edf3;
}

@media (prefers-reduced-motion: reduce) {
html:focus-within {
scroll-behavior: auto;
}

*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
.back-to-top {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 100;
display: none; /* Hidden by default */
}

.theme-toggle {
width: 42px;
height: 42px;
border-radius: 12px;
border: 1px solid rgba(255,255,255,0.15);
background: rgba(255,255,255,0.08);
color: white;
cursor: pointer;
font-size: 1rem;
transition: all 0.25s ease;
.back-to-top img {
width: 50px;
height: 50px;
opacity: 0.7;
transition: opacity 0.3s ease;
}

.theme-toggle:hover {
background: rgba(255,255,255,0.18);
transform: translateY(-2px);
.back-to-top img:hover {
opacity: 1;
}

/* ============================================================
WORKING DARK MODE
.back-to-top button {
background: transparent;
border: none;
cursor: pointer;
}
12 changes: 12 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@ <h2 class="section-title">Find Your Next Project</h2>
<button type="button" class="skill-chip" data-skill="pytest">pytest</button>
<button type="button" class="skill-chip" data-skill="Webpack">Webpack</button>
</div>


<!-- Level + Interest in a row -->
<div class="form-row">
<div class="form-group">
Expand Down Expand Up @@ -684,6 +686,15 @@ <h3>What it leads to</h3>
</div>
</div>
</section>
<!-- Back to top button (appears after scrolling) -->
<div class="back-to-top">
<button id="scrollBtn">
<img
src="{{ url_for('static', filename='Back-to-top.png') }}"
alt="Back to Top"
>
</button>
</div>

<!-- ============================================================
Footer
Expand Down Expand Up @@ -783,6 +794,7 @@ <h4 class="footer-col-title">About Us</h4>
.btn-clear:hover {
background-color: #e5e7eb;
}

</style>

<button id="scroll-top-btn" aria-label="Scroll to top" title="Scroll to top">
Expand Down
Loading