-
Notifications
You must be signed in to change notification settings - Fork 4
Gpa search #1114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gpa search #1114
Changes from all commits
d89a763
f33889a
5f8274c
01f4b6a
f50d80a
abe2422
f7922c5
2e8fcd2
4a71008
1e3a7f7
cba72e3
74e8c18
b01d838
56e65c2
299d08c
456067c
da79d82
9bae276
2894db6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -93,24 +93,62 @@ <h6 class="filter-header"> | |
</div> | ||
</div> | ||
</div> | ||
<!-- Open Section selections --> | ||
<!-- Hidden inputs for min_gpa --> | ||
<input type="hidden" id="min_gpa" name="min_gpa" value="{% if min_gpa %}{{ min_gpa }}{% endif %}"> | ||
<!-- Open Section & Minimum GPA selections mobile --> | ||
<div class="filter-section compact availability-section"> | ||
<h6 class="filter-header"> | ||
Availability | ||
</h6> | ||
<div class="form-check d-inline-flex align-items-center" style="background: white; border: 1px solid #cbd5e0; border-radius: 6px; padding: 0.55rem 0.67rem;"> | ||
<div class="form-check d-inline-flex align-items-center availability-check" style="background: white; border: 1px solid #cbd5e0; border-radius: 6px; padding: 0.55rem 0.67rem;"> | ||
<input | ||
class="form-check-input me-2" | ||
type="checkbox" | ||
id="open-sections" | ||
name="open_sections" | ||
id="open-sections-compact" | ||
{% if request.session.search_filters.open_sections %}checked{% endif %} | ||
> | ||
<label class="form-check-label" for="open-sections"> | ||
Only display courses with open sections | ||
<label class="form-check-label" for="open-sections-compact"> | ||
Show courses with open sections | ||
</label> | ||
</div> | ||
</div> | ||
<div class="filter-section compact availability-section"> | ||
<h6 class="filter-header"> | ||
Minimum GPA | ||
</h6> | ||
<div class="min-gpa-div"> | ||
<input type="text" id="gpa-input-compact" class="min-gpa-input" placeholder="Select GPA" value="{% if min_gpa %}{{ min_gpa }}{% endif %}"> | ||
<input type="range" id="gpa-slider-compact" class="gpa-slider" min="1.0" max="4.0" step="0.1" value="{% if min_gpa %}{{ min_gpa }}{% endif %}"> | ||
</div> | ||
</div> | ||
<!-- Open Section & Minimum GPA selections desktop --> | ||
<div class="filter-grid middle-filter-section"> | ||
<h6 class="filter-header"> | ||
Availability | ||
</h6> | ||
<h6 class="filter-header"> | ||
Minimum GPA | ||
</h6> | ||
<div class="availability-check"> | ||
<input | ||
class="form-check-input me-2" | ||
type="checkbox" | ||
id="open-sections" | ||
name="open_sections" | ||
{% if request.session.search_filters.open_sections %}checked{% endif %} | ||
> | ||
<label class="form-check-label" for="open-sections"> | ||
Show courses with open sections | ||
</label> | ||
</div> | ||
<!-- Min GPA selection --> | ||
<div class="min-gpa-div"> | ||
<div class="gpa-input-container"> | ||
<input type="text" id="gpa-input" class="min-gpa-input" placeholder="Select GPA" value="{% if min_gpa %}{{ min_gpa }}{% endif %}"> | ||
<input type="range" id="gpa-slider" class="gpa-slider" min="1.0" max="4.0" step="0.1" value="{% if min_gpa %}{{ min_gpa }}{% endif %}"> | ||
</div> | ||
</div> | ||
</div> | ||
<!-- List of subjects --> | ||
<div class="filter-grid"> | ||
<div class="filter-section"> | ||
|
@@ -230,7 +268,60 @@ <h6 class="filter-header"> | |
const filterButton = document.getElementById('filter-button'); | ||
const timeFrom = document.getElementById('from_time'); | ||
const timeTo = document.getElementById('to_time'); | ||
const openSections = document.getElementById('open-sections'); | ||
const desktopCheckbox = document.getElementById("open-sections"); | ||
const compactCheckbox = document.getElementById("open-sections-compact"); | ||
|
||
function syncCheckboxes(source, target) { | ||
target.checked = source.checked; | ||
} | ||
|
||
compactCheckbox.addEventListener("change", () => syncCheckboxes(compactCheckbox, desktopCheckbox)); | ||
desktopCheckbox.addEventListener("change", () => syncCheckboxes(desktopCheckbox, compactCheckbox)); | ||
|
||
// Get the GPA input and slider elements for both desktop and mobile and hidden input | ||
const gpaInputDesktop = document.getElementById('gpa-input'); | ||
const gpaSliderDesktop = document.getElementById('gpa-slider'); | ||
const gpaInputMobile = document.getElementById('gpa-input-compact'); | ||
const gpaSliderMobile = document.getElementById('gpa-slider-compact'); | ||
const hiddenGpaInput = document.getElementById('min_gpa'); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should not be this much repeated logic for the desktop and mobile versions. I think it makes more sense to just hide filters on mobile view. |
||
// Function to sync all GPA values | ||
function syncGpaValues(value) { | ||
gpaInputDesktop.value = value; | ||
gpaSliderDesktop.value = value; | ||
gpaInputMobile.value = value; | ||
gpaSliderMobile.value = value; | ||
hiddenGpaInput.value = value; | ||
} | ||
|
||
// Initialize with any existing value | ||
if (hiddenGpaInput.value) { | ||
syncGpaValues(hiddenGpaInput.value); | ||
} | ||
|
||
// Add event listeners to all inputs | ||
gpaInputDesktop.addEventListener('input', function() { | ||
syncGpaValues(this.value); | ||
}); | ||
|
||
gpaSliderDesktop.addEventListener('input', function() { | ||
syncGpaValues(this.value); | ||
}); | ||
|
||
gpaInputMobile.addEventListener('input', function() { | ||
syncGpaValues(this.value); | ||
}); | ||
|
||
gpaSliderMobile.addEventListener('input', function() { | ||
syncGpaValues(this.value); | ||
}); | ||
|
||
// Form submission - ensure the hidden input has the current value | ||
document.querySelector('form').addEventListener('submit', function() { | ||
const currentValue = window.innerWidth < 768 ? | ||
gpaInputMobile.value : gpaInputDesktop.value; | ||
hiddenGpaInput.value = currentValue; | ||
}); | ||
|
||
// Check initial state (in case of page refresh with active filters) | ||
updateButtonState(); | ||
|
@@ -246,7 +337,8 @@ <h6 class="filter-header"> | |
timeFrom.addEventListener('input', updateButtonState); | ||
timeTo.addEventListener('input', updateButtonState); | ||
|
||
openSections.addEventListener('change', updateButtonState); | ||
desktopCheckbox.addEventListener('change', updateButtonState); | ||
hiddenGpaInput.addEventListener('input', updateButtonState); | ||
|
||
// Checks for active filters or inactive day filters to determine button state | ||
function updateButtonState() { | ||
|
@@ -256,6 +348,7 @@ <h6 class="filter-header"> | |
let timeFromChanged = false; | ||
let timeToChanged = false; | ||
let openSectionsChanged = false; | ||
let gpaChanged = false; | ||
|
||
if (timeFrom.value) { | ||
timeFromChanged = timeFrom.value !== ''; | ||
|
@@ -264,11 +357,15 @@ <h6 class="filter-header"> | |
timeToChanged = timeTo.value !== ''; | ||
} | ||
|
||
if (openSections.checked) { | ||
if (desktopCheckbox.checked) { | ||
openSectionsChanged = true; | ||
} | ||
|
||
if (activeFilters.length > 0 || activeDayFilters.length > 0 || timeFromChanged || timeToChanged || openSectionsChanged) { | ||
if (hiddenGpaInput.value) { | ||
gpaChanged = hiddenGpaInput.value !== ''; | ||
} | ||
|
||
if (activeFilters.length > 0 || activeDayFilters.length > 0 || timeFromChanged || timeToChanged || openSectionsChanged || gpaChanged) { | ||
filterButton.classList.add('filter-active'); | ||
filterButton.textContent = 'Filters Active'; | ||
} else { | ||
|
@@ -376,6 +473,12 @@ <h6 class="filter-header"> | |
document.getElementById('from_time').value = ''; | ||
document.getElementById('to_time').value = ''; | ||
|
||
// Clear GPA dropdown | ||
document.getElementById('gpa-input').value = ''; | ||
document.getElementById('gpa-slider').value = ''; | ||
|
||
syncGpaValues(''); // Sync all GPA values to empty | ||
|
||
updateWeekdays(); | ||
updateButtonState(); | ||
|
||
|
@@ -414,6 +517,37 @@ <h6 class="filter-header"> | |
}); | ||
}); | ||
|
||
// Stops invalid inputs from being entered into min GPA input (only numbers and decimal) | ||
brianlogic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
gpaInputDesktop.addEventListener('input', function() { | ||
// Use a more efficient regex that handles all cases | ||
this.value = this.value.replace(/[^0-9.]/g, ''); | ||
const parts = this.value.split('.'); | ||
if (parts.length > 2) { | ||
this.value = parts[0] + '.' + parts.slice(1).join(''); | ||
} | ||
}); | ||
|
||
gpaInputMobile.addEventListener('input', function() { | ||
// Use a more efficient regex that handles all cases | ||
this.value = this.value.replace(/[^0-9.]/g, ''); | ||
const parts = this.value.split('.'); | ||
if (parts.length > 2) { | ||
this.value = parts[0] + '.' + parts.slice(1).join(''); | ||
} | ||
}); | ||
|
||
// Input validation for GPA field desktop and mobile | ||
gpaInputMobile.addEventListener('input', function() { | ||
// Use a more efficient regex that handles all cases | ||
this.value = this.value.replace(/[^0-9.]/g, ''); | ||
|
||
// More efficient way to handle multiple decimals | ||
const parts = this.value.split('.'); | ||
if (parts.length > 2) { | ||
this.value = parts[0] + '.' + parts.slice(1).join(''); | ||
} | ||
}); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are there 3 of the same thing |
||
// Initialize weekdays | ||
updateWeekdays(); | ||
|
||
|
@@ -485,7 +619,7 @@ <h6 class="filter-header"> | |
.filter-grid { | ||
display: grid; | ||
grid-template-columns: repeat(2, 1fr); | ||
gap: 1.5rem; | ||
gap: 0.3rem 1.5rem; | ||
align-items: start; | ||
} | ||
|
||
|
@@ -744,4 +878,83 @@ <h6 class="filter-header"> | |
opacity: 0; | ||
visibility: hidden; | ||
} | ||
|
||
.min-gpa-div { | ||
display: inline-flex; | ||
gap: 0; | ||
} | ||
|
||
.gpa-slider { | ||
width: 80%; | ||
background: #d75626; | ||
border-radius: 5px; | ||
outline: none; | ||
height: 0.5rem; | ||
margin: 5% 0; | ||
} | ||
|
||
.availability-check { | ||
display: inline-flex; | ||
justify-content: left; | ||
border-radius: 4px; | ||
padding: 0.375rem 0.75rem; | ||
border: 1px solid #ccc; | ||
height: 100%; | ||
} | ||
|
||
.availability-section { | ||
display: none; | ||
} | ||
|
||
/* Show it only on mobile devices (screen width less than 768px) */ | ||
@media (max-width: 768px) { | ||
.availability-section { | ||
display: block; | ||
} | ||
|
||
.middle-filter-section { | ||
display: none !important; | ||
} | ||
|
||
.availability-check { | ||
display: flex; | ||
align-items: center; | ||
justify-content: flex-start; | ||
border-radius: 4px; | ||
padding: 0.375rem 0.75rem; | ||
border: 1px solid #ccc; | ||
height: fit-content; | ||
width: fit-content; | ||
gap: 0.5rem; | ||
} | ||
|
||
.availability-check .form-check-input { | ||
margin: 0; | ||
} | ||
|
||
.availability-check .form-check-label { | ||
margin-left: 1.2rem; | ||
white-space: normal; | ||
} | ||
} | ||
|
||
.min-gpa-input{ | ||
padding: 8px 12px; | ||
box-sizing: border-box; | ||
border: 1px solid #ccc; | ||
border-radius: 4px; | ||
width: 35%; | ||
margin-right: 0.5rem; | ||
} | ||
|
||
.gpa-input-container { | ||
position: relative; | ||
display: flex; | ||
width: 100%; | ||
} | ||
|
||
.button:focus { | ||
outline: none; | ||
|
||
} | ||
</style> |
Uh oh!
There was an error while loading. Please reload this page.