diff --git a/client/src/components/FiltersSideMenu/filters.js b/client/src/components/FiltersSideMenu/filters.js index 2d054dc..9cd5552 100644 --- a/client/src/components/FiltersSideMenu/filters.js +++ b/client/src/components/FiltersSideMenu/filters.js @@ -21,9 +21,8 @@ import utilityStyles from "../../styles/utility.module.css"; * locations: the values for the location filter options * achievements: the values for the achievements filter options */ -export default function SearchTabFilters({ locations, achievements }) { +export default function SearchTabFilters({ achievements }) { const search = useSearch(); - const [locationsData, setLocationsData] = useState(locations); const [achievementsData, setAchievementsData] = useState(achievements); /** @@ -49,9 +48,8 @@ export default function SearchTabFilters({ locations, achievements }) { }; useEffect(() => { - setLocationsData(locations); setAchievementsData(achievements); - }, [locations, achievements]); + }, [achievements]); const filterData = (query, initialValues, property, setState) => { const q = query.toLowerCase(); @@ -134,6 +132,32 @@ export default function SearchTabFilters({ locations, achievements }) { } }; + const addLocationToFilter = (location) => { + const locationFilters = JSON.parse( + JSON.stringify(search.selectedLocations) + ); + + if (locationFilters.findIndex((s) => s.id === location.id) !== -1) { + return; + } + locationFilters.push({ name: location.value, id: location.id }); + search["selectLocations"](locationFilters); + }; + + const removeLocationFromFilter = (location) => { + const locationFilters = JSON.parse( + JSON.stringify(search.selectedLocations) + ); + const index = locationFilters.findIndex((s) => s.id === location.id); + + if (index === -1) { + return; + } + + locationFilters.splice(index, 1); + search["selectLocations"](locationFilters); + }; + const addSkillToFilter = (skill) => { const skillFilters = JSON.parse(JSON.stringify(search.selectedSkills)); @@ -230,27 +254,27 @@ export default function SearchTabFilters({ locations, achievements }) { /> {search.isFilterActive(FILTERS.LOCATIONS) && (
- - filterData("", locations, "name", setLocationsData) - } - title="Location" - collapsed={false} - > - - filterData(q.trim(), locations, "name", setLocationsData) - } - /> - + + {search.selectedLocations.length > 0 && ( +
+ {search.selectedLocations.map((location) => { + return ( + removeLocationFromFilter(location)} + /> + ); + })} +
+ )}
)} @@ -334,7 +358,6 @@ export default function SearchTabFilters({ locations, achievements }) { } SearchTabFilters.propTypes = { - locations: PT.array, achievements: PT.array, }; diff --git a/client/src/components/FiltersSideMenu/index.jsx b/client/src/components/FiltersSideMenu/index.jsx index c04003e..1932495 100644 --- a/client/src/components/FiltersSideMenu/index.jsx +++ b/client/src/components/FiltersSideMenu/index.jsx @@ -4,15 +4,14 @@ import PT from "prop-types"; import style from "./style.module.scss"; import SearchTabFilters from "./filters"; -export default function FiltersSideMenu({ locations, achievements }) { +export default function FiltersSideMenu({ achievements }) { return (
- +
); } FiltersSideMenu.propTypes = { - locations: PT.array.isRequired, achievements: PT.array.isRequired, }; diff --git a/client/src/components/SuggestionBox/index.jsx b/client/src/components/SuggestionBox/index.jsx index 0173ebf..1f12746 100644 --- a/client/src/components/SuggestionBox/index.jsx +++ b/client/src/components/SuggestionBox/index.jsx @@ -4,6 +4,7 @@ import config from "../../config"; import api from "../../services/api"; import style from "./style.module.scss"; import _ from "lodash"; +import { useSearch, FILTERS } from "../../lib/search"; const NO_RESULTS_FOUND = "no results found"; const DELAY_SEARCH = 300; @@ -95,6 +96,7 @@ export default function SuggestionBox({ placeholder, onSelect, }) { + const search = useSearch(); const apiClient = api(); const [suggestions, setSuggestions] = React.useState([]); const [value, setValue] = React.useState(""); @@ -102,6 +104,11 @@ export default function SuggestionBox({ const onChange = (event, { newValue }) => setValue(newValue.trim()); const onSuggestionsFetchRequested = async ({ value }) => { + if (purpose === "locations") { + if (!companyAttrId) { + companyAttrId = search.getAttributeId(FILTERS.LOCATIONS); + } + } if (purpose === "skills") { let data = await getSkillsSuggestions(apiClient, value); @@ -128,6 +135,8 @@ export default function SuggestionBox({ const onSuggestionSelected = (event, { suggestion }) => { if (purpose === "skills") { if (suggestion.name !== NO_RESULTS_FOUND) onSelect(suggestion); + } else if (purpose === "locations") { + if (suggestion.name !== NO_RESULTS_FOUND) onSelect(suggestion); } else { if (suggestion.name !== NO_RESULTS_FOUND) onSelect(companyAttrId, suggestion); diff --git a/client/src/lib/company-attributes.js b/client/src/lib/company-attributes.js index 7abfb00..d31ac72 100644 --- a/client/src/lib/company-attributes.js +++ b/client/src/lib/company-attributes.js @@ -14,7 +14,7 @@ let primaryAttributeIds = [ * Get the attributes associated with the company (organization) * @param {Object} apiClient The api client (you can get this from src/services/api and then call api() to get the apiClient) */ -export async function getCompanyAttributes(apiClient, cancelToken) { +export async function getAttributes(apiClient, cancelToken) { let response; let attributeGroups; let attributes = []; @@ -70,8 +70,8 @@ export async function getCompanyAttributes(apiClient, cancelToken) { } } - // Finally, we only need the company attributes - attributes = attributes.filter((attribute) => { + // Finally, split 2 attribute types + const companyAttrs = attributes.filter((attribute) => { if (primaryAttributeIds.includes(attribute.name)) { return false; } @@ -79,5 +79,13 @@ export async function getCompanyAttributes(apiClient, cancelToken) { return true; }); - return attributes; + const generalAttrs = attributes.filter((attribute) => { + if (primaryAttributeIds.includes(attribute.name)) { + return true; + } + + return false; + }); + + return [companyAttrs, generalAttrs]; } diff --git a/client/src/lib/search.js b/client/src/lib/search.js index 258814c..3b35849 100644 --- a/client/src/lib/search.js +++ b/client/src/lib/search.js @@ -66,6 +66,14 @@ function useProvideSearch() { setPopupShown(true); }; + const setFilter = (id, filter) => { + return (filters[id] = filter); + }; + + const getAttributeId = (filter) => { + return filters[filter].id; + }; + const isFilterActive = (filter) => { return filters[filter].active; }; @@ -132,7 +140,9 @@ function useProvideSearch() { popupShown, showPopup, filters, + setFilter, setFilters, + getAttributeId, isFilterActive, activateFilter, deactivateFilter, diff --git a/client/src/pages/Search/Global.jsx b/client/src/pages/Search/Global.jsx index 1417363..899eac6 100644 --- a/client/src/pages/Search/Global.jsx +++ b/client/src/pages/Search/Global.jsx @@ -9,7 +9,7 @@ import Pagination from "../../components/Pagination"; import * as helper from "./helper"; import { useAuth0 } from "../../react-auth0-spa"; -import { getCompanyAttributes } from "../../lib/company-attributes"; +import { getAttributes } from "../../lib/company-attributes"; import { useSearch, FILTERS } from "../../lib/search"; import { makeColorIterator, avatarColors } from "../../lib/colors"; import config from "../../config"; @@ -50,7 +50,6 @@ export default function SearchGlobal({ keyword }) { const apiClient = api(); const searchContext = useSearch(); const [isSearching, setIsSearching] = React.useState(false); - const [locations, setLocations] = React.useState([]); const [achievements, setAchievements] = React.useState([]); const [users, setUsers] = React.useState([]); const [page, setPage] = React.useState(1); @@ -85,11 +84,9 @@ export default function SearchGlobal({ keyword }) { let isSubscribed = true; (async () => { - const locations = await staticData.getLocations(); const achievements = await staticData.getAchievements(); if (isSubscribed) { - setLocations(locations); setAchievements(achievements); } })(); @@ -107,7 +104,7 @@ export default function SearchGlobal({ keyword }) { let isSubscribed = true; (async () => { - const companyAttrs = await getCompanyAttributes( + const [companyAttrs, generalAttrs] = await getAttributes( apiClient, cancelTokenSource.token ); @@ -125,6 +122,17 @@ export default function SearchGlobal({ keyword }) { searchContext.setFilters(filtersWithCompanyAttrs); } } + if (generalAttrs) { + generalAttrs.forEach((generalAttr) => { + if (generalAttr.name === config.STANDARD_USER_ATTRIBUTES.location) { + filtersWithCompanyAttrs[FILTERS.LOCATIONS].id = generalAttr.id; + searchContext.setFilter( + FILTERS.LOCATIONS, + filtersWithCompanyAttrs[FILTERS.LOCATIONS] + ); + } + }); + } })(); return () => { @@ -145,7 +153,7 @@ export default function SearchGlobal({ keyword }) { searchContext.filters[FILTERS.LOCATIONS].active && searchContext.selectedLocations.length > 0 ) { - criteria.locations = searchContext.selectedLocations; + criteria.locations = searchContext.selectedLocations.map((l) => l.name); } if ( searchContext.filters[FILTERS.SKILLS].active && @@ -209,10 +217,12 @@ export default function SearchGlobal({ keyword }) { pageChanged = true; } - if (_.isEqual(prevCriteria, criteria) - && prevKeyword === keyword - && prevOrderBy === orderBy - && pageChanged === false) { + if ( + _.isEqual(prevCriteria, criteria) && + prevKeyword === keyword && + prevOrderBy === orderBy && + pageChanged === false + ) { return; } else { setPrevCriteria(criteria); @@ -302,7 +312,7 @@ export default function SearchGlobal({ keyword }) { return ( <>
- +
{!isSearching && users.length > 0 && (
diff --git a/client/src/services/static-data.js b/client/src/services/static-data.js index fec7c18..68273c1 100644 --- a/client/src/services/static-data.js +++ b/client/src/services/static-data.js @@ -1,36 +1,3 @@ -async function getLocations() { - const mockLocationTags = [ - { name: "London" }, - { name: "New York" }, - { name: "East Carmen" }, - { name: "Savanahville" }, - { name: "Lake Audra" }, - { name: "Elainaville" }, - { name: "Howellstad" }, - { name: "West Reneefort" }, - { name: "Vanside" }, - { name: "East Jonatan" }, - { name: "Gottliebton" }, - { name: "Ervinchester" }, - { name: "Matteoburgh" }, - { name: "Curtmouth" }, - { name: "North Raphaelleton" }, - { name: "Laishaside" }, - { name: "West Trystanmouth" }, - { name: "West Torrey" }, - { name: "Abernathystad" }, - { name: "Danland" }, - { name: "Lednertown" }, - { name: "Athenamouth" }, - { name: "North Abagailport" }, - { name: "North Andres" }, - { name: "New Herbert" }, - { name: "Bergstrombury" }, - { name: "West Santinoside" }, - ]; - return mockLocationTags; -} - async function getAchievements() { const mockAchievementsTags = [ { name: "Informatika" }, @@ -42,6 +9,5 @@ async function getAchievements() { } export default { - getLocations, getAchievements, };