Skip to content

Commit a2c9d7e

Browse files
Responsive filtering solid (#142)
* applied filters into the search function using flags in the model, will have to refine more in the filters, but this is great for the demo * wrote departments filter option * added check to make sure to not recommend courses the client has taken before * initial state good * departments go to model * trying to add filtering out courses with NULL fields as an implementable filter option, merging with main start as per teams request * merging into brain? * some ?. properties check, because skill issue * more course?. things * finished the noNull feature, essentially fixed typos * null course checkbox * null check linked * Null field toggle works * nice and beutiful * removed the explicit null string checks, hopefully doesnt break, also wrote logic for Period filtering * period filter * a bit polishing, touching on the period presenter since i thought its broken, but it was the database dropping all course.period data >:( * fixed some filters logic (level filter, period filter), added descriptions to most filters tooltips, fixed About us button, touched Tab title to current working title, fixed some other things * visually persistent filters * now fixed * once again * unlocking departments and locations * wip * filters enabled by clicking on them * My side merge with Dean's side * departments half functional * rebase to main * rebase to main * Refactoring transcript scraper (#126) * Reworked UploadTranscriptPresenter into a source file, now SidebarPresenter calls it, allows us to upgrade it so that the transcript scraper function has access to a flattened out model (course list with only id, and name fields needed) * reworked LocalStorage so that it stores object array instead of strings, object structure is {id (str),name(str),is_in_DB(bool)} * fixed couple errors relating to the new LocaleStorage finished courses, also touched on the departments so that its trucated by tailwind instead of just 25 characters * fixed a lot of typos (deparmen != department) * trying to add hover over tooltips such that it displayes name of course * inbetween * removing the console.logs because theyre dumb and we should remove them before committing to main especially, added some comments, will add more * department percistency done only SU and Education Office broken * even more documentation, added descriptions and cleared up toolTips on the sidebar * departments should be working * nothing really * work on upload bahaviour * fix of animated gif * fixed upload * merge main --------- Co-authored-by: benedekboldizsar <bb.boldizsarbenedek@gmail.com>
1 parent 7acc78b commit a2c9d7e

File tree

11 files changed

+1810
-172
lines changed

11 files changed

+1810
-172
lines changed

my-app/package-lock.json

Lines changed: 1751 additions & 115 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

my-app/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"firebase": "^11.5.0",
2020
"fuse.js": "^7.1.0",
2121
"ldrs": "^1.1.6",
22+
"lint": "^0.8.19",
2223
"lodash.debounce": "^4.0.8",
2324
"lodash.throttle": "^4.1.1",
2425
"mobx": "^6.13.7",

my-app/src/presenters/FilterPresenter.jsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ const FilterPresenter = observer(({ model }) => {
5050
model.filteredCourses = filteredCourses;
5151
}, [filteredCourses]);
5252

53-
54-
5553
/* functions declared here are generally things the main function of this observer takes and runs if the given filters are enabled,
5654
* this is determined through model.filterOptions.apply*Insert filter name* flags.
5755
* This presenter should be changed such that it uses side-effects instead model.filtersChange flag, since
@@ -414,7 +412,6 @@ const FilterPresenter = observer(({ model }) => {
414412
}
415413

416414
/* function that should run every single time the model changes (see note below) */
417-
418415
/* the problem is that unless using sideeffects, the run() not being async and/or it setting the filterschange = false very early can mean
419416
* that 0 courses will get put into the model.filtered courses (which is the list of courses getting passed to search, and then listview)
420417
* therefore TODO: rework it to stop using this dumb flags we started before learning anything about react,observers,js

my-app/src/presenters/SidebarPresenter.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const SidebarPresenter = observer(({ model }) => {
1616

1717
useEffect(() => {
1818
model.setFiltersChange();
19-
},[]);
19+
},[model]);
2020

2121
function handleLanguageFilterChange(param) {
2222
if (param === "English") {
@@ -219,9 +219,9 @@ const SidebarPresenter = observer(({ model }) => {
219219
const handleFileChange = (event) => {
220220
const truncatedCourses = model.courses.map(({ id, name }) => ({ id, name }));
221221
const file = event.target.files[0];
222-
//document.getElementById('PDF-Scraper-Error').style.visibility = "visible";
222+
document.getElementById('PDF-Scraper-Error').style.visibility = "visible";
223223
transcriptScraperFunction(file, setErrorMessage, setErrorVisibility, reApplyFilter, truncatedCourses);
224-
//document.getElementById('PDF-Scraper-Input').value = '';
224+
document.getElementById('PDF-Scraper-Input').value = '';
225225
setFileInputValue('');
226226

227227

my-app/src/views/Components/SideBarComponents/ButtonGroupField.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export default function ButtonGroupField(props) {
3131
};
3232
return (
3333
<div className="my-1">
34-
<div className="flex flex-col sm:inline-flex sm:flex-row rounded-lg shadow-2xs
34+
<div className="flex sm:inline-flex rounded-lg shadow-2xs
3535
w-full items-center font-medium text-white bg-[#aba8e0]">
3636
{props.items.map((item, index) => (
3737
<button

my-app/src/views/Components/SideBarComponents/CollapsibleCheckboxes.jsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import FilterEnableCheckbox from "./FilterEnableCheckbox";
33
import Tooltip from "./ToolTip";
44

55
const CollapsibleCheckboxes = (props) => {
6-
const [expandedLabel, setExpandedLabel] = useState(props?.initialValues?.map(i => i?.label));
76
const [expanded, setExpanded] = useState([]);
87
const [filterEnabled, setFilterEnabled] = useState(props.filterEnable);
98
const [checkedSubItems, setCheckedSubItems] = useState({});
@@ -83,7 +82,7 @@ const CollapsibleCheckboxes = (props) => {
8382
setInitalLoad(false);
8483
setExpanded(tempExpanded);
8584
}
86-
}, [rows]);
85+
}, [rows, initalLoad, props?.initialValues]);
8786

8887

8988

my-app/src/views/Components/SideBarComponents/CourseTranscriptList.jsx

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { useState, useRef, forwardRef } from "react";
2-
import Tooltip from "./ToolTip";
1+
import { useState, forwardRef } from "react";
32

4-
export default function CourseTranscriptList(props) {
3+
const CourseTranscriptList = forwardRef((props,ref) => {
54
let local = [];
65
if (localStorage.getItem("completedCourses"))
76
local = JSON.parse(localStorage.getItem("completedCourses"));
@@ -31,14 +30,11 @@ export default function CourseTranscriptList(props) {
3130
localStorage.setItem("completedCourses", JSON.stringify(newitems));
3231
window.dispatchEvent(new Event("completedCourses changed"));
3332
props.reApplyFilter();
34-
if (props.checkboxRef && props.checkboxRef.current) {
35-
props.checkboxRef.current.click();
36-
}
33+
ref.current.click();
3734
};
3835

3936

4037
//=====================================
41-
const tooltipRef = useRef(null);
4238

4339
const tooltipClasses = [
4440
"absolute",
@@ -80,25 +76,25 @@ export default function CourseTranscriptList(props) {
8076
<div
8177
className="absolute inset-0 mt-30 pointer-events-none bg-gradient-to-b from-transparent to-[#553d65] z-100"
8278
></div>
83-
<div className="grid grid-cols-3 w-full max-[1200px]:grid-cols-2 max-[700px]:grid-cols-1 gap-1 sm:gap-2 overflow-y-auto overflow-x-hidden max-h-[180px] pb-10" style={{
79+
<div className="grid grid-cols-3 w-full max-[1200px]:grid-cols-2 gap-1 sm:gap-2 overflow-y-auto overflow-x-hidden max-h-[180px] pb-10" style={{
8480
scrollbarWidth: "thin",
8581
scrollbarColor: "#888 #f1f1f1",
8682
}}>
8783
{items.map((item, index) => (
8884
<div
8985
key={index}
90-
className="flex items-center bg-[#aba8e0] px-3 py-1 rounded-md shadow-md text-sm min-w-18 relative"
86+
className="flex items-center bg-[#aba8e0] px-3 py-1 rounded-md shadow-md text-sm min-w-18"
9187
>
9288
<div className="relative">
9389
<span className="flex-auto mr-2 peer">{item?.id}</span>
9490

9591
<div className={tooltipClasses}>
96-
{item?.name + (item?.is_in_DB ? "" : " (Course discontinued)")}
92+
{item?.name}
9793
</div>
9894
</div>
9995
<button
10096
onClick={() => removeItem(index)}
101-
className="text-violet-600 hover:text-red-700 font-bold text-sm hover:bg-red-300 rounded-md absolute right-2 top-1/2 -translate-y-1/2"
97+
className="text-violet-600 hover:text-red-700 font-bold text-sm hover:bg-red-300 rounded-md"
10298
>
10399
<svg
104100
xmlns="http://www.w3.org/2000/svg"
@@ -120,4 +116,6 @@ export default function CourseTranscriptList(props) {
120116
</div>
121117
</div>
122118
);
123-
}
119+
});
120+
121+
export default CourseTranscriptList;

my-app/src/views/Components/SideBarComponents/MultipleChoiceButtons.jsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default function MultipleChoiceButtons(props) {
1111

1212
useEffect(() => {
1313
setFilterEnabled(props.filterEnable);
14-
})
14+
},[props.filterEnable])
1515

1616
const handleClick = (index) => {
1717
setSelectedItems((prev) => {
@@ -36,17 +36,18 @@ export default function MultipleChoiceButtons(props) {
3636
return "default-button-class"; // Fallback class for invalid index
3737
}
3838

39-
const baseClasses = `flex-auto py-1 px-4 inline-flex items-center gap-x-2 text-sm
40-
font-medium focus:z-10 border border-gray-200 shadow-2xs hover:bg-[#8785ac]
41-
focus:outline-hidden disabled:opacity-50 disabled:pointer-events-none pl-8`;
39+
const baseClasses = `flex-auto py-1 px-4 inline-flex items-center text-sm
40+
font-medium focus:z-10 border border-gray-200 shadow-2xs hover:bg-[#8785ac]
41+
focus:outline-hidden sm:pl-7 pl-4 text-center`;
4242
const activeClass = selectedItems[index] ? "bg-violet-500" : "bg-transparent";
4343
const roundedClasses =
4444
index === 0
45-
? "rounded-l-lg"
46-
: index === props.items.length - 1
47-
? "rounded-r-lg"
48-
: "border-l-0";
49-
return `${baseClasses} ${activeClass} ${roundedClasses}`;
45+
? "rounded-l-lg"
46+
: index === props.items.length - 1
47+
? "rounded-r-lg"
48+
: "border-l-0 ";
49+
const mobileClasses = "w-full sm:w-auto"; // Adjust for mobile
50+
return `${baseClasses} ${activeClass} ${roundedClasses} ${mobileClasses}`;
5051
};
5152

5253
return (
@@ -74,7 +75,7 @@ export default function MultipleChoiceButtons(props) {
7475
}}>
7576

7677
<div className="my-1">
77-
<div className="flex flex-col sm:inline-flex sm:flex-row rounded-lg shadow-2xs
78+
<div className="flex sm:inline-flex rounded-lg shadow-2xs
7879
w-full items-center font-medium text-white bg-[#aba8e0]">
7980
{props.items.map((item, index) => (
8081
<button

my-app/src/views/Components/SideBarComponents/SliderField.jsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import React, { useState, useRef, useEffect } from "react";
1+
import React, { useState, useRef, useEffect, useMemo } from "react";
22
import FilterEnableCheckbox from "./FilterEnableCheckbox";
33
import Tooltip from "./ToolTip";
44

55
export default function UploadField(props) {
66
let paramFieldType = "slider";
77

8-
const values = [
8+
9+
const values = useMemo(() => [
910
1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5,
1011
6, 7, 7.5, 8, 8.5, 9, 10, 11, 12, 13.5,
1112
14, 15, 20, 22.5, 30, 45
12-
];
13+
], []);
1314

1415
const [minIndex, setMinIndex] = useState(0);
1516
const [maxIndex, setMaxIndex] = useState(values.length - 1);
@@ -19,14 +20,15 @@ export default function UploadField(props) {
1920

2021
useEffect(() => {
2122
for (let i = 0; i < values.length; i++) {
22-
if (values[i] === props.initialValues[0]) {
23+
if (values[i] === props?.initialValues[0]) {
2324
setMinIndex(i);
2425
}
25-
if (values[i] === props.initialValues[1]) {
26+
if (values[i] === props?.initialValues[1]) {
2627
setMaxIndex(i);
2728
}
2829
}
29-
}, []); // Empty dependency array ensures this runs only once
30+
}, [props?.initialValues, values]); // Empty dependency array ensures this runs only once
31+
3032

3133

3234
const handleDrag = (e, thumbType) => {
@@ -110,7 +112,7 @@ export default function UploadField(props) {
110112
window.addEventListener("mousemove", move);
111113
window.addEventListener("mouseup", up);
112114
}}
113-
onTouchStart={(e) => {
115+
onTouchStart={() => {
114116
const move = (ev) => handleDrag(ev, "min");
115117
const end = () => {
116118
window.removeEventListener("touchmove", move);
@@ -139,7 +141,7 @@ export default function UploadField(props) {
139141
window.addEventListener("mousemove", move);
140142
window.addEventListener("mouseup", up);
141143
}}
142-
onTouchStart={(e) => {
144+
onTouchStart={() => {
143145
const move = (ev) => handleDrag(ev, "max");
144146
const end = () => {
145147
window.removeEventListener("touchmove", move);

my-app/src/views/Components/SideBarComponents/ToggleField.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ export default function ToggleField(props) {
77
let paramFieldType = "toggle";
88

99
const [filterEnabled, setFilterEnabled] = useState(props.filterEnable);
10-
const [prop1Set, setprop1Set] = useState((props.initialValues=="both") || (props.initialValues==String(props.fields[0]).charAt(0).toLowerCase() + String(props.fields[0]).slice(1)));
10+
//eslint-disable-next-line @typescript-eslint/no-unused-vars
11+
const [prop1Set, setprop1Set] = useState((props.initialValues == "both") || (props.initialValues == String(props.fields[0]).charAt(0).toLowerCase() + String(props.fields[0]).slice(1)));
12+
//eslint-disable-next-line @typescript-eslint/no-unused-vars
1113
const [prop2Set, setprop2Set] = useState((props.initialValues=="both") || (props.initialValues==String(props.fields[1]).charAt(0).toLowerCase() + String(props.fields[1]).slice(1)));
1214

1315
const checkboxRef = useRef(null);
@@ -36,7 +38,7 @@ export default function ToggleField(props) {
3638
checkboxRef.current.click();
3739
}
3840
}}>
39-
<div className="flex flex-col sm:flex-row md:flex-row rounded-lg shadow-2xs w-full items-center
41+
<div className="flex sm:flex-row rounded-lg shadow-2xs w-full items-center
4042
font-medium text-white bg-[#aba8e0] ">
4143
<label className="flex-auto py-3 px-4 inline-flex gap-x-2 -mt-px -ms-px
4244
first:rounded-t-md last:rounded-b-md sm:first:rounded-s-md sm:mt-0 sm:first:ms-0 s

0 commit comments

Comments
 (0)