Skip to content

Commit

Permalink
Implemented new workflow for no results
Browse files Browse the repository at this point in the history
  • Loading branch information
mjaydenkim committed Jan 15, 2025
1 parent bb9dd64 commit 8fc1372
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 110 deletions.
23 changes: 14 additions & 9 deletions client/src/modules/Results/Components/PreviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const PreviewCard = ({ course }: PreviewCardProps) => {
const [topReview, setTopReview] = useState<ReviewType | {}>();
const [numReviews, setNumReviews] = useState(0);
const [topReviewLikes, setTopReviewLikes] = useState(0);
const [offered, setOffered] = useState('');

useEffect(() => {
if (course) {
Expand All @@ -29,16 +30,18 @@ export const PreviewCard = ({ course }: PreviewCardProps) => {
}, [course]);

const updateGauges = () => {
setId(course._id);
setRating(course.classRating ? String(course.classRating) : '-');
setDiff(course.classDifficulty ? String(course.classDifficulty) : '-');
setWorkload(course.classWorkload ? String(course.classWorkload) : '-');
updateTopReview();
if (course) {
setId(course._id);
setRating(course.classRating ? String(course.classRating) : '-');
setDiff(course.classDifficulty ? String(course.classDifficulty) : '-');
setWorkload(course.classWorkload ? String(course.classWorkload) : '-');
updateTopReview();
}
};

const updateTopReview = () => {
axios
.post(`/api/courses/get-reviews`, { courseId: course._id })
.post(`/api/courses/get-reviews`, { courseId: course ? course._id : id })
.then((response) => {
const reviews = response.data.result;
if (reviews && reviews.length > 0) {
Expand All @@ -48,6 +51,7 @@ export const PreviewCard = ({ course }: PreviewCardProps) => {
setTopReview(reviews[0]);
setTopReviewLikes(reviews[0].likes || 0);
setNumReviews(reviews.length);
setOffered(lastOfferedSems(course));
} else {
setTopReview({});
setNumReviews(0);
Expand All @@ -57,10 +61,11 @@ export const PreviewCard = ({ course }: PreviewCardProps) => {

if (!course) {
// Return fallback if course is undefined
return <></>;
return (
<></>
);
}

const offered = lastOfferedSems(course);
return (
<div className={styles.container}>
<div>
Expand Down Expand Up @@ -108,7 +113,7 @@ export const PreviewCard = ({ course }: PreviewCardProps) => {
</a>
)}

{numReviews === 0 && (
{numReviews === 0 && topReview !== undefined && (
<>
<img src={Bear} alt="Bear Icon" className={styles.bearicon} />
<div className={styles.noreviews}>
Expand Down
4 changes: 2 additions & 2 deletions client/src/modules/Results/Components/Results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export const Results = ({match, history}: ResultsProps) => {
const response = await axios.post(`/api/search/get-courses`, {
query: match.params.input.toLowerCase()
});
const courseList = response.data.result.courses;
setCourseList(!courseList.error && courseList.length > 0 ? courseList : []);
const list = response.data.result.courses;
setCourseList(!list.error && list.length > 0 ? list : []);
setLoading(false);
}

Expand Down
215 changes: 125 additions & 90 deletions client/src/modules/Results/Components/ResultsDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import FilterIcon from '../../../assets/icons/filtericon.svg';

import styles from '../Styles/Results.module.css';
import { Class } from 'common';
import Bear from '/surprised_bear.svg';

/*
ResultsDisplay Component.a
Expand Down Expand Up @@ -101,6 +102,7 @@ export const ResultsDisplay = ({
fieldDefault: number,
increasing: boolean
) => {
if (courseList.length === 0) return;
const sorted = [...courseList].sort((a, b) => {
const first = Number(b[sortByField]) || fieldDefault;
const second = Number(a[sortByField]) || fieldDefault;
Expand Down Expand Up @@ -215,25 +217,27 @@ export const ResultsDisplay = ({
* The original list as FilteredResult components otherwise
*/
const renderResults = () => {
const items = filteredItems.length ? filteredItems : courseList;

return items.map((result, index) => (
<div
className={styles.filteredresults}
data-cy={`results-display-${result.classSub.toLowerCase()}-${
result.classNum
}`}
>
<FilteredResult
key={index}
index={index}
selected={index === activeCard}
course={result}
previewHandler={previewHandler}
sortBy={selected}
/>
</div>
));
if (filteredItems.length === 0) {
return <></>
} else {
return filteredItems.map((result, index) => (
<div
className={styles.filteredresults}
data-cy={`results-display-${result.classSub.toLowerCase()}-${
result.classNum
}`}
>
<FilteredResult
key={index}
index={index}
selected={index === activeCard}
course={result}
previewHandler={previewHandler}
sortBy={selected}
/>
</div>
));
}
};

const renderCheckboxes = (group: string) => {
Expand All @@ -259,23 +263,16 @@ export const ResultsDisplay = ({

return (
<div className={styles.container}>
{(loading || courseList.length === 0) && <h1> Search Results </h1>}
{/* Case where results are still being loaded */}
{loading && <Loading />}
{/* Case where no results returned */}
{courseList.length === 0 && !loading && (
<div>
<img
src="/noResults.svg"
className={styles.noresultimg}
alt="No class found"
/>
<div>Sorry! No classes match your search.</div>
</div>
{loading && (
<>
<h1> Search Results </h1>
<Loading />
</>
)}
{/* Case where results are returned (non-empty) */}
{courseList.length !== 0 && !loading && (
{/* Case where results are returned, even if zero */}
{!loading && (
<div className={styles.layout} data-cy="results-display">
{/* Case where no results returned */}
<div className={styles.leftbar}>
<h1> Search Results </h1>
{/*<button*/}
Expand All @@ -297,72 +294,110 @@ export const ResultsDisplay = ({
</div>
</div>

<div className={styles.columns}>
{searchListViewEnabled && (
<>
<div>
We found{' '}
<b>
{filteredItems.length === 0
? courseList.length
: filteredItems.length}
</b>{' '}
courses for &quot;{userInput}
&quot;
</div>
<div className={styles.filtersortbuttons}>
<div className={styles.bar}>
<div>
<label>Sort By: </label>
<select
value={selected}
className={styles.sortselector}
onChange={(e) => handleSelect(e)}
{filteredItems.length !== 0 && (
<div className={styles.columns}>
{searchListViewEnabled && (
<>
<div>
We found <b>{filteredItems.length}</b> courses for &quot;
{userInput}
&quot;
</div>
<div className={styles.filtersortbuttons}>
<div className={styles.bar}>
<div>
<label>Sort By: </label>
<select
value={selected}
className={styles.sortselector}
onChange={(e) => handleSelect(e)}
>
<option value="relevance">Relevance</option>
<option value="rating">Overall Rating</option>
<option value="diff">Difficulty</option>
<option value="work">Workload</option>
</select>
</div>

<button
className={styles.filterbutton}
onClick={() => setShowFilterPopup(!showFilterPopup)}
>
<option value="relevance">Relevance</option>
<option value="rating">Overall Rating</option>
<option value="diff">Difficulty</option>
<option value="work">Workload</option>
</select>
Filter <img src={FilterIcon} alt="filter-icon" />
</button>
</div>

<button
className={styles.filterbutton}
onClick={() => setShowFilterPopup(!showFilterPopup)}
>
Filter <img src={FilterIcon} alt="filter-icon" />
</button>
{showFilterPopup && (
<FilterPopup
renderCheckboxes={renderCheckboxes}
setShowFilterPopup={() =>
setShowFilterPopup(!showFilterPopup)
}
/>
)}
</div>
{showFilterPopup && (
<FilterPopup
renderCheckboxes={renderCheckboxes}
setShowFilterPopup={() =>
setShowFilterPopup(!showFilterPopup)
}
/>
)}
</div>
<div className={styles.layout}>
<div className={styles.list}>
<div className={styles.resultslist}>
<ul>{renderResults()}</ul>
<div className={styles.layout}>
<div className={styles.list}>
<div className={styles.resultslist}>
<ul>{renderResults()}</ul>
</div>
</div>
</div>
</div>
</>
)}
</>
)}
</div>
)}
{filteredItems.length === 0 && (
<div className={styles.columns}>
{searchListViewEnabled && (
<>
<div className={styles.filtersortbuttons}>
<div className={styles.bar}>
<button
className={styles.filterbutton}
onClick={() => setShowFilterPopup(!showFilterPopup)}
>
Filter <img src={FilterIcon} alt="filter-icon" />
</button>
</div>
{showFilterPopup && (
<FilterPopup
renderCheckboxes={renderCheckboxes}
setShowFilterPopup={() =>
setShowFilterPopup(!showFilterPopup)
}
/>
)}
</div>
</>
)}
</div>
)}
</div>
</div>

<div className={styles.preview}>
<div className={styles.previewcard}>
<PreviewCard
course={cardCourse}
// transformGauges={transformGauges}
/>
{filteredItems.length === 0 && (
<div className={styles.noitems}>
<img src={Bear} alt="Bear Icon" className={styles.bearicon}/>
<div>No classes found. Try searching something else or switching up the filters!</div>
{/* <img*/}
{/* src="/noResults.svg"*/}
{/* className={styles.noresultimg}*/}
{/* alt="No class found"*/}
{/* />*/}
{/* <div>Sorry! No classes match your search.</div>*/}
</div>
</div>
)}

{filteredItems.length !== 0 && (
<div className={styles.preview}>
<div className={styles.previewcard}>
<PreviewCard
course={cardCourse}
// transformGauges={transformGauges}
/>
</div>
</div>
)}
</div>
)}
</div>
Expand Down
17 changes: 17 additions & 0 deletions client/src/modules/Results/Styles/CoursePreview.module.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
.container {
padding: 16px;
border: 1px solid var(--clr-gray-300);
background-color: color-mix(in srgb, var(--clr-blue-100) 90%, var(--clr-gray-300));
border-radius: 8px;
}

.columns {
display: flex;
flex-flow: column;
Expand Down Expand Up @@ -70,6 +77,16 @@
height: 50px;
}

.nocourse {
display: flex;
font-size: 1.75em;
justify-content: center;
align-items: center;
width: 100%;
height: 50px;
padding: 30px;
}

.bearicon {
display: flex;
justify-content: center;
Expand Down
Loading

0 comments on commit 8fc1372

Please sign in to comment.