Skip to content

Commit 0cfbf2a

Browse files
Merge pull request topcoder-archive#626 from cagdas001/develop
feat: add auto suggestion for achievement filter
2 parents 80f9bcf + c34ac76 commit 0cfbf2a

File tree

6 files changed

+100
-79
lines changed

6 files changed

+100
-79
lines changed

client/src/components/FiltersSideMenu/filters.js

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import PT from "prop-types";
33
import Button from "../Button";
44
import WideButton from "../wideButton";
55
import Collapsible from "../collapsible";
6-
import SearchBox from "../searchBox";
76
import Availability from "../availability";
8-
import TagList from "../tagList";
97
import EditFiltersPopup from "../editFiltersPopup";
108
import SuggestionBox from "../SuggestionBox";
119
import Pill from "../Pill";
@@ -20,9 +18,8 @@ import utilityStyles from "../../styles/utility.module.css";
2018
* SearchTabFilters - component containing all the filters on the search tab page
2119
* achievements: the values for the achievements filter options
2220
*/
23-
export default function SearchTabFilters({ achievements }) {
21+
export default function SearchTabFilters() {
2422
const search = useSearch();
25-
const [achievementsData, setAchievementsData] = useState(achievements);
2623

2724
/**
2825
* Component unmount trigger
@@ -46,21 +43,6 @@ export default function SearchTabFilters({ achievements }) {
4643
search.changePageNumber(1);
4744
};
4845

49-
useEffect(() => {
50-
setAchievementsData(achievements);
51-
}, [achievements]);
52-
53-
const filterData = (query, initialValues, property, setState) => {
54-
const q = query.toLowerCase();
55-
if (q.length >= 3) {
56-
setState(
57-
initialValues.filter((g) => g[property].toLowerCase().includes(q))
58-
);
59-
} else if (query.length === 0) {
60-
setState(initialValues);
61-
}
62-
};
63-
6446
const [numberOfFiltersApplied, setNumberOfFiltersApplied] = useState();
6547
const modal = useModal();
6648

@@ -180,6 +162,32 @@ export default function SearchTabFilters({ achievements }) {
180162
search["selectSkills"](skillFilters);
181163
};
182164

165+
const addAchievementToFilter = (achievement) => {
166+
const achievementFilters = JSON.parse(
167+
JSON.stringify(search.selectedAchievements)
168+
);
169+
170+
if (achievementFilters.findIndex((s) => s.id === achievement.id) !== -1) {
171+
return;
172+
}
173+
achievementFilters.push(achievement);
174+
search["selectAchievements"](achievementFilters);
175+
};
176+
177+
const removeAchievementFromFilter = (achievement) => {
178+
const achievementFilters = JSON.parse(
179+
JSON.stringify(search.selectedAchievements)
180+
);
181+
const index = achievementFilters.findIndex((s) => s.id === achievement.id);
182+
183+
if (index === -1) {
184+
return;
185+
}
186+
187+
achievementFilters.splice(index, 1);
188+
search["selectAchievements"](achievementFilters);
189+
};
190+
183191
const addCompanyAttributeToFilter = (attrId, data) => {
184192
const companyAttrFilters = JSON.parse(
185193
JSON.stringify(search.selectedCompanyAttributes)
@@ -319,25 +327,26 @@ export default function SearchTabFilters({ achievements }) {
319327
)}
320328
{search.isFilterActive(FILTERS.ACHIEVEMENTS) && (
321329
<div className={utilityStyles.mt32}>
322-
<Collapsible
323-
title="Achievements"
324-
onCollapsed={(isCollapsed) =>
325-
filterData("", achievements, "name", setAchievementsData)
326-
}
327-
>
328-
<SearchBox
330+
<Collapsible title="Achievements">
331+
<SuggestionBox
329332
placeholder="Search for an achievement"
330-
name={"achievements search"}
331-
onChange={(q) =>
332-
filterData(q.trim(), achievements, "name", setAchievementsData)
333-
}
334-
/>
335-
<TagList
336-
tags={achievementsData}
337-
selected={search.selectedAchievements}
338-
selector={"selectAchievements"}
339-
noResultsText={"No achievement found"}
333+
purpose="achievements"
334+
onSelect={addAchievementToFilter}
340335
/>
336+
{search.selectedAchievements.length > 0 && (
337+
<div className={utilityStyles.mt16}>
338+
{search.selectedAchievements.map((achievement) => {
339+
return (
340+
<Pill
341+
key={achievement.id}
342+
name={achievement.name}
343+
removable={true}
344+
onRemove={() => removeAchievementFromFilter(achievement)}
345+
/>
346+
);
347+
})}
348+
</div>
349+
)}
341350
</Collapsible>
342351
</div>
343352
)}
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
import React from "react";
2-
import PT from "prop-types";
32

43
import style from "./style.module.scss";
54
import SearchTabFilters from "./filters";
65

76
export default function FiltersSideMenu({ achievements }) {
87
return (
98
<div className={style.container}>
10-
<SearchTabFilters achievements={achievements} />
9+
<SearchTabFilters />
1110
</div>
1211
);
1312
}
14-
15-
FiltersSideMenu.propTypes = {
16-
achievements: PT.array.isRequired,
17-
};

client/src/components/SuggestionBox/index.jsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import api from "../../services/api";
55
import style from "./style.module.scss";
66
import _ from "lodash";
77
import { useSearch, FILTERS } from "../../lib/search";
8+
import { getAchievements } from "../../lib/achievements";
89

910
const NO_RESULTS_FOUND = "no results found";
1011
const DELAY_SEARCH = 300;
@@ -66,6 +67,22 @@ const getSkillsSuggestions = async (apiClient, inputValue) => {
6667
return data.skills;
6768
};
6869

70+
/**
71+
* Returns the suggestions for achievements
72+
* @param {Object} apiClient The api client to make the query
73+
* @param {String} inputValue The search query
74+
*/
75+
const getAchievementSuggestions = async (apiClient, inputValue) => {
76+
let term = inputValue.trim();
77+
if (term.length < 1) {
78+
return [];
79+
}
80+
81+
term = encodeURIComponent(term);
82+
const suggestions = await getAchievements(apiClient, term);
83+
return suggestions;
84+
};
85+
6986
/**
7087
* Returns the suggestions for company attributes
7188
* @param {Object} apiClient The api client to make the query
@@ -112,6 +129,11 @@ export default function SuggestionBox({
112129
if (purpose === "skills") {
113130
let data = await getSkillsSuggestions(apiClient, value);
114131

132+
if (data.length < 1) data = [{ name: NO_RESULTS_FOUND }];
133+
setSuggestions(data);
134+
} else if (purpose === "achievements") {
135+
let data = await getAchievementSuggestions(apiClient, value);
136+
115137
if (data.length < 1) data = [{ name: NO_RESULTS_FOUND }];
116138
setSuggestions(data);
117139
} else {
@@ -137,6 +159,8 @@ export default function SuggestionBox({
137159
if (suggestion.name !== NO_RESULTS_FOUND) onSelect(suggestion);
138160
} else if (purpose === "locations") {
139161
if (suggestion.name !== NO_RESULTS_FOUND) onSelect(suggestion);
162+
} else if (purpose === "achievements") {
163+
if (suggestion.name !== NO_RESULTS_FOUND) onSelect(suggestion);
140164
} else {
141165
if (suggestion.name !== NO_RESULTS_FOUND)
142166
onSelect(companyAttrId, suggestion);

client/src/lib/achievements.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import config from "../config";
2+
import * as OrgService from "../services/user-org";
3+
4+
/**
5+
* Returns achivement suggestions based on query
6+
* @param {Object} apiClient The api client (you can get this from src/services/api and then call api() to get the apiClient)
7+
* @param {String} query query to search for
8+
*/
9+
export async function getAchievements(apiClient, query) {
10+
let response;
11+
const organizationId = OrgService.getSingleOrg();
12+
let url = `${config.API_URL}/search/userAchievements?organizationId=${organizationId}&keyword=${query}`;
13+
14+
try {
15+
response = await apiClient.get(url);
16+
} catch (error) {
17+
console.log(error);
18+
return [];
19+
}
20+
21+
if (!response.data || response.data.length < 1) {
22+
return [];
23+
}
24+
25+
return response.data;
26+
}

client/src/pages/Search/Global.jsx

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { useSearch, FILTERS } from "../../lib/search";
1414
import { makeColorIterator, avatarColors } from "../../lib/colors";
1515
import config from "../../config";
1616
import api from "../../services/api";
17-
import staticData from "../../services/static-data";
1817

1918
import style from "./style.module.scss";
2019
import _ from "lodash";
@@ -50,7 +49,6 @@ export default function SearchGlobal({ keyword }) {
5049
const apiClient = api();
5150
const searchContext = useSearch();
5251
const [isSearching, setIsSearching] = React.useState(false);
53-
const [achievements, setAchievements] = React.useState([]);
5452
const [users, setUsers] = React.useState([]);
5553
const [page, setPage] = React.useState(1);
5654
const [totalResults, setTotalResults] = React.useState(0);
@@ -75,26 +73,6 @@ export default function SearchGlobal({ keyword }) {
7573
};
7674
});
7775

78-
// Static data only
79-
React.useEffect(() => {
80-
if (isLoading || !isAuthenticated) {
81-
return;
82-
}
83-
84-
let isSubscribed = true;
85-
86-
(async () => {
87-
const achievements = await staticData.getAchievements();
88-
89-
if (isSubscribed) {
90-
setAchievements(achievements);
91-
}
92-
})();
93-
94-
return () => (isSubscribed = false);
95-
// eslint-disable-next-line react-hooks/exhaustive-deps
96-
}, [isLoading, isAuthenticated]);
97-
9876
// Non-static data and Non-user related data
9977
React.useEffect(() => {
10078
if (isLoading || !isAuthenticated) {
@@ -165,7 +143,9 @@ export default function SearchGlobal({ keyword }) {
165143
searchContext.filters[FILTERS.ACHIEVEMENTS].active &&
166144
searchContext.selectedAchievements.length > 0
167145
) {
168-
criteria.achievements = searchContext.selectedAchievements;
146+
criteria.achievements = searchContext.selectedAchievements.map(
147+
(a) => a.name
148+
);
169149
}
170150
if (searchContext.filters[FILTERS.AVAILABILITY].active) {
171151
if (
@@ -312,7 +292,7 @@ export default function SearchGlobal({ keyword }) {
312292
return (
313293
<>
314294
<div className={style.sideMenu}>
315-
<FiltersSideMenu achievements={achievements} />
295+
<FiltersSideMenu />
316296
</div>
317297
{!isSearching && users.length > 0 && (
318298
<div className={style.rightSide}>

client/src/services/static-data.js

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)