Skip to content

Commit

Permalink
added a search bar filter (#95)
Browse files Browse the repository at this point in the history
* added a search bar that filters the projects by name, description, lang and topic

* added placeholder to searchbar, changed some styling elements
  • Loading branch information
ColbertX authored Apr 12, 2022
1 parent 1004db9 commit 175169c
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 8 deletions.
79 changes: 79 additions & 0 deletions components/SearchFilter/SearchFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { ChangeEvent, useState, useEffect } from 'react';
import { Project } from '../../util';
import Searchbar from './Searchbar';

interface SearchFilterProps {
projects: Project[];
setFilteredProjects: (projectList: Project[]) => void;
}

function lowercaseRemove(s: string) {
// takes a string, makes it all lowercase, and removes all - and _ characters, and
// also removes whitespace

let newString = s.toLowerCase();
newString = newString.replace(/-|_|\s/g, '');
return newString;
}

function SearchFilter({projects, setFilteredProjects}: SearchFilterProps): JSX.Element {

const [searchbarText, setSearchbarText] = useState('');

const handleSearchInput = (e: ChangeEvent<HTMLInputElement>) => {
setSearchbarText(e.target.value);
};

const filterProjectsBySearchText = (project: Project) => {
// helper function for filtering the projects

// remove - and _ and white spaces from search, and make it lowercase to make it easier for the user to
// search things without typing the exact name
// e.g. if the user searches "devpathways" or "dev pathways" they should still be able to see "Dev-Pathways"
const search = lowercaseRemove(searchbarText);

const {
name,
description,
lang,
topics,
} = project;

// can search by name, description, or language
const lowercaseName = lowercaseRemove(name);
const lowercaseDescription = lowercaseRemove(description);
const lowercaseLang = lowercaseRemove(lang);

if (lowercaseName.includes(search) || lowercaseDescription.includes(search) || lowercaseLang.includes(search)) {
return true;
}

// can also search by topic
for (let i = 0; i < topics.length; i++) {
const lowercaseTopic = lowercaseRemove(topics[i]);

if (lowercaseTopic.includes(search)) {
return true;
}
}

return false;
};

// run the filter projects function every time the searchbar text changes
useEffect(() => {
const tempProjects = projects.filter(filterProjectsBySearchText);
setFilteredProjects(tempProjects);
}, [searchbarText]);

return (
<div>
<Searchbar
value={searchbarText}
onChange={(e: ChangeEvent<HTMLInputElement>) => handleSearchInput(e)}
/>
</div>
);
}

export default SearchFilter;
22 changes: 22 additions & 0 deletions components/SearchFilter/Searchbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { ChangeEvent } from 'react';

interface SearchbarProps {
value: string;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
}

function Searchbar({value, onChange}: SearchbarProps): JSX.Element {

return (
<div className="searchbar">
<input
placeholder="search"
type="search"
value={value}
onChange={onChange}
/>
</div>
);
}

export default Searchbar;
30 changes: 22 additions & 8 deletions pages/projects.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { GetStaticProps } from 'next';
import { NextSeo } from 'next-seo';
import React from 'react';
import React, { useState } from 'react';
import Layout from '../components/Layout';
import ProjectCard from '../components/ProjectCard';
import SearchFilter from '../components/SearchFilter/SearchFilter';
import { getProjects, Project, GitHubColors, getGithubColors } from '../util';


Expand All @@ -12,6 +13,11 @@ interface ProjectsProps {
}

function Projects({ projects, githubColors }: ProjectsProps): JSX.Element {

// projects is a master list of all the projects that we fetched, filteredProjects is the one that we render
// to the user
const [filteredProjects, setFilteredProjects] = useState(projects);

return (
<Layout>
<div className="container">
Expand All @@ -35,14 +41,22 @@ function Projects({ projects, githubColors }: ProjectsProps): JSX.Element {
a (work-in-progress) heads-up overview of the projects that power ACM at UCLA.
</p>
<hr />
<SearchFilter
projects={projects}
setFilteredProjects={setFilteredProjects}
/>
<hr/>
<div className="row same-height-grid">
{projects.map((project, i) => {
return (
<div className="col-4" key={project.name}>
<ProjectCard project={project} vertical preload={i < 3} githubColors={githubColors} />
</div>
);
})}
{filteredProjects.length > 0
? filteredProjects.map((project, i) => {
return (
<div className="col-4" key={project.name}>
<ProjectCard project={project} vertical preload={i < 3} githubColors={githubColors} />
</div>
);
})
: <h2>No results found</h2>
}
</div>
</div>
</Layout>
Expand Down

0 comments on commit 175169c

Please sign in to comment.