Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
be2bb98
fix filters not working on mobile
mirmirmirr Nov 14, 2025
6681b31
hide results on mobile if filter is open
mirmirmirr Nov 14, 2025
3dc9a1c
wrap filter section on mobile
mirmirmirr Nov 14, 2025
fb8ab3f
adjust chosen tag location
mirmirmirr Nov 17, 2025
44dbdf0
truncate filter section
mirmirmirr Nov 18, 2025
2db667b
add scrollbar to filter panel
mirmirmirr Nov 18, 2025
56492f9
add setShowFilter dependency
mirmirmirr Nov 18, 2025
245bb2a
add TAG_THRESHOLD variable
mirmirmirr Nov 18, 2025
f4ed85f
added aria tags
mirmirmirr Nov 18, 2025
574d16f
rename searchbar
mirmirmirr Nov 18, 2025
004988c
adjust filter panels styling and colors
mirmirmirr Nov 20, 2025
34ef944
standardize filterSections to singular
mirmirmirr Nov 20, 2025
27f83d6
adjust the courses panel to grow with the container
mirmirmirr Nov 20, 2025
d633758
convert regular list to FilterData list and add tooltip
mirmirmirr Nov 21, 2025
d5158fe
add filter panel color palette
mirmirmirr Nov 21, 2025
c3ee4b6
define names for colors
mirmirmirr Nov 21, 2025
b7f083a
update tag colors
mirmirmirr Nov 21, 2025
bc16583
new colors!
mirmirmirr Nov 21, 2025
0a6717a
change popup background color
mirmirmirr Nov 23, 2025
acebe2f
condense into one global Tag component
mirmirmirr Nov 23, 2025
43206bf
remove double remove filter
mirmirmirr Nov 23, 2025
35d7c6c
update department filter tags
mirmirmirr Nov 23, 2025
686130d
update for mobile styling
mirmirmirr Nov 23, 2025
402c7f5
change scrollbar color
mirmirmirr Nov 23, 2025
ec18bc2
add spacer
mirmirmirr Nov 23, 2025
0196fee
Merge branch 'main-preview' into 60-mobile-filters-dont-work
mirmirmirr Nov 24, 2025
f574d2f
Merge branch 'main-preview' into 60-mobile-filters-dont-work
mirmirmirr Nov 24, 2025
5c41221
update colors
mirmirmirr Nov 29, 2025
50e282b
fix colors
mirmirmirr Nov 29, 2025
e04397a
add back steelblue
mirmirmirr Nov 29, 2025
e3dfb94
prettier
mirmirmirr Nov 29, 2025
90b7156
Merge branch 'main-preview' into 60-mobile-filters-dont-work
mirmirmirr Nov 29, 2025
d3a32d8
add more bottom filter spacing
mirmirmirr Dec 2, 2025
56f6186
adjust toolbar visibility
mirmirmirr Dec 2, 2025
ab4bd04
prettier check
mirmirmirr Dec 2, 2025
d7e28bb
add nav button border
mirmirmirr Dec 2, 2025
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
42 changes: 21 additions & 21 deletions src/components/Course/CatalogCourse.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
import React, { useState } from "react";
import Tag from "./CatalogCourse/Tag";
import AddButton from "./CatalogCourse/AddButton";
import { motion } from "framer-motion";
import { APICourse } from "../../types/interfaces/Course.interface";
import { useCourseWorkspace } from "../../hooks/useCourseWorkspace";
import { useFilterData } from "../../hooks/useFilters";
import { FilterData } from "../../types/interfaces/Filters.interface";
import Tag from "../Tag";

const findFiltersForCourse = (
api_list: string[],
filterDataType: FilterData[],
) => {
console.log("API List:", api_list);
return filterDataType.filter((attr) => api_list.includes(attr.code));
};

interface CourseProps {
course: APICourse;
}

const Course: React.FC<CourseProps> = ({ course }) => {
const { toolboxCourses, setToolboxCourses } = useCourseWorkspace();
const { attributes, semesters } = useFilterData();

const attrFilters = findFiltersForCourse(course.attr_list || [], attributes);
const semFilters = findFiltersForCourse(course.sem_list || [], semesters);

const [isOpen, setIsOpen] = useState(false);
const toggleOpen = (e: React.MouseEvent<HTMLDivElement>) => {
Expand Down Expand Up @@ -58,7 +72,7 @@ const Course: React.FC<CourseProps> = ({ course }) => {
<div
className={`${
courseCount === undefined ? "hidden" : ""
} absolute right-[-10px] top-[-10px] rounded-full bg-[#78A1BB] w-8 h-8 flex justify-center items-center text-white`}
} absolute right-[-10px] top-[-10px] rounded-full bg-steelblue w-8 h-8 flex justify-center items-center text-carpipink`}
>
<p>{courseCount}</p>
</div>
Expand All @@ -71,26 +85,12 @@ const Course: React.FC<CourseProps> = ({ course }) => {
</b>
<p>{toTitleCase(course.title)}</p>
</div>
<div className={`flex flex-wrap mt-1`}>
{course.attr_list?.map((attr, index) => {
return (
<Tag
key={index}
name={attr}
bgcolor={"#99C1B9"}
color={"#283044"}
/>
);
<div className={`flex flex-wrap mt-1 gap-1`}>
{attrFilters.map((attr, index) => {
return <Tag key={index} filter={attr} />;
})}
{course.sem_list?.map((semester, index) => {
return (
<Tag
key={index}
name={semester}
bgcolor={"#565E87"}
color={"#F5CECE"}
/>
);
{semFilters?.map((semester, index) => {
return <Tag key={index} filter={semester} />;
})}
</div>
</div>
Expand Down
19 changes: 0 additions & 19 deletions src/components/Course/CatalogCourse/Tag.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/Course/ToolboxCourse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const ToolboxCourse: React.FC<ToolboxCourseProps> = ({
className={`relative bg-carpipink text-nowrap rounded-md w-fit px-3 py-1`}
>
<div
className={`absolute -top-2 -right-2 rounded-full bg-[#78A1BB] w-6 h-6 flex justify-center items-center text-white text-sm ${
className={`absolute -top-2 -right-2 rounded-full bg-steelblue w-6 h-6 flex justify-center items-center text-white text-sm ${
count === 1 ? "hidden" : ""
}`}
>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Department-Filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ const DepartmentFilters: React.FC = () => {
const { toggleFilter, subjects } = useFilterData();

return (
<div className="md:h-full md:w-full md:overflow-y-auto flex flex-wrap justify-center gap-2">
<div className="md:h-full md:w-full md:overflow-y-auto flex flex-wrap justify-center gap-1">
{subjects.map((subject) => (
<button
key={subject.code}
className={`
px-3
py-2
rounded-xl
rounded-full
border
border-darkblue
text-xs
transition-colors
hover:bg-darkblue hover:text-carpipink
hover:bg-darkblue hover:text-carpipink hover:cursor-pointer
h-fit
`}
onClick={() => toggleFilter(subject)}
Expand All @@ -29,7 +29,7 @@ const DepartmentFilters: React.FC = () => {
</button>
))}

<div className="h-15" />
<div className="h-40" />
</div>
);
};
Expand Down
29 changes: 0 additions & 29 deletions src/components/SearchBar/ChosenTag.tsx

This file was deleted.

20 changes: 10 additions & 10 deletions src/components/SearchBar/FilterPanel/FilterPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
import { useFilterData } from "../../../hooks/useFilters";
import FilterSection from "./FilterSection";
// import FilterSectionChild from "./FilterSectionChild";

const FilterPanel: React.FC = () => {
const { selectedFilters, toggleFilter, subjects, attributes, semesters } =
useFilterData();
const { selectedFilters, subjects, attributes, semesters } = useFilterData();

const selectedSubjects = selectedFilters
.filter((f) => f.type === "Subject")
.map((f) => f.code);
const selectedAttributes = selectedFilters
.filter((f) => f.type === "Attributes")
.filter((f) => f.type === "Attribute")
.map((f) => f.code);
const selectedSemesters = selectedFilters
.filter((f) => f.type === "Semesters")
.filter((f) => f.type === "Semester")
.map((f) => f.code);

return (
<div className="w-full">
<div className="md:max-h-80 md:overflow-y-auto scrollbar-thin scrollbar-thumb-carpipink scrollbar-track-darkblue/50">
<h1 className="font-bold">Filter By</h1>
<FilterSection
sectionName="Subject"
tags={subjects}
selected={selectedSubjects}
toggleFilter={toggleFilter}
showCode
/>
<FilterSection
sectionName="Attributes"
sectionName="Attribute"
tags={attributes}
selected={selectedAttributes}
toggleFilter={toggleFilter}
/>
<FilterSection
sectionName="Semesters"
sectionName="Semester"
tags={semesters}
selected={selectedSemesters}
toggleFilter={toggleFilter}
/>
<div className="h-20 md:h-5" />
</div>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/SearchBar/FilterPanel/FilterPanelPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import FilterPanel from "./FilterPanel";

const FilterPanelPopup: React.FC = () => {
return (
<div className="absolute right-4 top-20 z-10 mt-2 w-full max-w-sm rounded-lg bg-carpipink p-4 shadow-lg border border-darkblue">
<div className="absolute right-0 top-16 z-10 mt-2 w-full max-w-sm rounded-lg bg-darkblue text-carpipink p-4 shadow-lg ">
<FilterPanel />
</div>
);
Expand Down
82 changes: 65 additions & 17 deletions src/components/SearchBar/FilterPanel/FilterSection.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,82 @@
import React from "react";
import { FilterData } from "../../../types/interfaces/Filters.interface";
import React, { useState } from "react";
import { motion } from "framer-motion";
import {
FilterCategory,
FilterData,
} from "../../../types/interfaces/Filters.interface";
import useIsDesktop from "../../../hooks/useIsDesktop";
import Tag from "../../Tag";

interface FilterSectionProps {
sectionName: "Subject" | "Attributes" | "Semesters";
sectionName: FilterCategory;
tags: FilterData[];
selected: string[];
toggleFilter: (filter: FilterData) => void;
showCode?: boolean;
}

const FilterSection: React.FC<FilterSectionProps> = ({
sectionName,
tags,
selected,
toggleFilter,
showCode = false,
}) => {
const isDesktop = useIsDesktop();
const [isExpanded, setIsExpanded] = useState(false);

const COLLAPSED_HEIGHT = "6rem";
const TAG_THRESHOLD = 6;
const shouldTruncate = tags.length > TAG_THRESHOLD;

return (
<div className="mt-2">
<h3 className="font-semibold mb-1">{sectionName}</h3>
<div className="flex overflow-x-auto scrollbar-none">
{tags.map((tag) => (
<button
key={tag.id}
className={`hover:bg-darkblue/10 hover:cursor-pointer rounded-2xl px-3 py-1 text-sm mr-1 mb-1 flex-none
${selected.includes(tag.code) ? "bg-darkblue text-carpipink hover:bg-darkblue/70 border border-darkblue" : "border border-darkblue text-darkblue"}`}
onClick={() => toggleFilter(tag)}
>
{tag.value}
</button>
))}
<h3 className="font-medium mb-1">{sectionName}</h3>

<div className="relative">
<motion.div
initial={false}
animate={{
height:
isExpanded || !shouldTruncate || !isDesktop
? "auto"
: COLLAPSED_HEIGHT,
}}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="flex flex-wrap overflow-hidden gap-1"
>
{tags.map((tag) => (
<Tag
key={tag.id}
filter={tag}
isSelectable={true}
isSelected={selected.includes(tag.code)}
showCode={showCode}
/>
))}
</motion.div>

{isDesktop && !isExpanded && shouldTruncate && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
aria-hidden="true"
className="absolute bottom-0 left-0 w-full h-12 bg-gradient-to-t from-darkblue to-transparent pointer-events-none"
/>
)}
</div>

{/* Toggle Button */}
{shouldTruncate && (
<button
onClick={() => setIsExpanded(!isExpanded)}
aria-expanded={isExpanded}
aria-controls={`${sectionName}-tags`}
className="text-xs text-carpipink mt-1 hover:underline focus:outline-none"
>
{isExpanded ? "Show Less" : "Show All"}
</button>
Comment thread
mirmirmirr marked this conversation as resolved.
)}
</div>
);
};
Expand Down
54 changes: 54 additions & 0 deletions src/components/SearchBar/FilterPanel/FilterSectionChild.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { useState } from "react";
import {
FilterCategory,
FilterData,
} from "../../../types/interfaces/Filters.interface";

interface FilterSectionProps {
sectionName: FilterCategory;
tags: FilterData[];
selected: string[];
toggleFilter: (filter: FilterData) => void;
}

const FilterSectionChild: React.FC<FilterSectionProps> = ({
sectionName,
tags,
selected,
toggleFilter,
}) => {
const [isExpanded, setIsExpanded] = useState(false);

return (
<div className="relative">
<h3
className="font-semibold mb-1 hover:cursor-pointer hover:bg-carpipink/10 rounded-full px-4"
onMouseEnter={() => setIsExpanded(true)}
onMouseLeave={() => setIsExpanded(false)}
>
{sectionName}
</h3>

{isExpanded && (
<div className="absolute left-full top-0 z-10 p-2 ml-2 bg-darkblue text-carpipink shadow-lg border rounded-2xl border-darkblue flex flex-wrap w-xl">
{tags.map((tag) => (
<button
key={tag.id}
className={`hover:bg-darkblue/10 hover:cursor-pointer rounded-2xl px-3 py-1 text-sm mr-1 mb-1 flex-none transition-colors
${
selected.includes(tag.code)
? "bg-darkblue text-carpipink hover:bg-darkblue/70 border border-carpipink"
: "border border-carpipink"
}`}
onClick={() => toggleFilter(tag)}
>
{tag.value}
</button>
))}
</div>
)}
</div>
);
};

export default FilterSectionChild;
Loading