From 28f9c7da6c24fe6b6aad8e279408dc7eb39c6f24 Mon Sep 17 00:00:00 2001 From: Jeff Sieu Date: Mon, 10 Oct 2022 01:15:29 +0800 Subject: [PATCH] [question][feat] cache filter options to localStorage --- apps/portal/src/pages/questions/index.tsx | 110 ++++++++++-------- .../src/utils/questions/useSearchFilter.ts | 54 +++++++++ 2 files changed, 115 insertions(+), 49 deletions(-) create mode 100644 apps/portal/src/utils/questions/useSearchFilter.ts diff --git a/apps/portal/src/pages/questions/index.tsx b/apps/portal/src/pages/questions/index.tsx index 7ac08d25..cfa6bf44 100644 --- a/apps/portal/src/pages/questions/index.tsx +++ b/apps/portal/src/pages/questions/index.tsx @@ -15,18 +15,32 @@ import { QUESTION_TYPES, SAMPLE_QUESTION, } from '~/utils/questions/constants'; +import { + useSearchFilter, + useSearchFilterSingle, +} from '~/utils/questions/useSearchFilter'; export default function QuestionsHomePage() { const router = useRouter(); - const [selectedCompanies, setSelectedCompanies] = useState>([]); + const [selectedCompanies, setSelectedCompanies, areCompaniesInitialized] = + useSearchFilter('companies'); + + const [ + selectedQuestionTypes, + setSelectedQuestionTypes, + areQuestionTypesInitialized, + ] = useSearchFilter('questionTypes'); + const [ + selectedQuestionAge, + setSelectedQuestionAge, + isQuestionAgeInitialized, + ] = useSearchFilterSingle('questionAge', 'all'); + const [selectedLocations, setSelectedLocations, areLocationsInitialized] = + useSearchFilter('locations'); - const [selectedQuestionTypes, setSelectedQuestionTypes] = useState< - Array - >([]); - const [selectedQuestionAge, setSelectedQuestionAge] = useState('all'); - const [selectedLocations, setSelectedLocations] = useState>([]); const [hasLanded, setHasLanded] = useState(false); + // Const [loaded, setLoaded] = useState(false); const companyFilterOptions = useMemo(() => { return COMPANIES.map((company) => ({ @@ -64,30 +78,22 @@ export default function QuestionsHomePage() { setHasLanded(true); }; - const paramToArray = ( - param: Array | string | undefined, - ): Array => { - if (typeof param === 'string') { - return [param]; - } - return param ?? []; - }; - - const [isSearchInitialized, setIsSearchInitialized] = useState(false); + const areFiltersInitialized = useMemo(() => { + return ( + areCompaniesInitialized && + areQuestionTypesInitialized && + isQuestionAgeInitialized && + areLocationsInitialized + ); + }, [ + areCompaniesInitialized, + areQuestionTypesInitialized, + isQuestionAgeInitialized, + areLocationsInitialized, + ]); - // Set url query params useEffect(() => { - if (router.isReady && !isSearchInitialized) { - const paramQuestionAge = router.query.questionAge; - const questionAge = Array.isArray(paramQuestionAge) - ? paramQuestionAge[0] - : paramQuestionAge ?? 'all'; - setSelectedCompanies(paramToArray(router.query.companies)); - setSelectedQuestionTypes(paramToArray(router.query.questionTypes)); - setSelectedQuestionAge(questionAge); - setSelectedLocations(paramToArray(router.query.locations)); - setIsSearchInitialized(true); - + if (areFiltersInitialized) { const hasFilter = router.query.companies || router.query.questionTypes || @@ -96,21 +102,14 @@ export default function QuestionsHomePage() { if (hasFilter) { setHasLanded(true); } + // Console.log('shit'); + // setLoaded(true); } - }, [ - router.isReady, - router.query, - isSearchInitialized, - hasLanded, - selectedCompanies, - selectedQuestionTypes, - selectedQuestionAge, - selectedLocations, - ]); + }, [areFiltersInitialized, router.query]); // Update url query params useEffect(() => { - if (router.isReady && isSearchInitialized) { + if (router.isReady && areFiltersInitialized) { router.replace( { query: { @@ -135,9 +134,13 @@ export default function QuestionsHomePage() { selectedLocations, router, router.isReady, - isSearchInitialized, + areFiltersInitialized, ]); + // If (!loaded) { + // return
hi
; + // } + return !hasLanded ? ( ) : ( @@ -152,10 +155,12 @@ export default function QuestionsHomePage() { searchPlaceholder="Add company filter" onOptionChange={(optionValue, checked) => { if (checked) { - setSelectedCompanies((prev) => [...prev, optionValue]); + setSelectedCompanies([...selectedCompanies, optionValue]); } else { - setSelectedCompanies((prev) => - prev.filter((company) => company !== optionValue), + setSelectedCompanies( + selectedCompanies.filter( + (company) => company !== optionValue, + ), ); } }} @@ -166,10 +171,15 @@ export default function QuestionsHomePage() { showAll={true} onOptionChange={(optionValue, checked) => { if (checked) { - setSelectedQuestionTypes((prev) => [...prev, optionValue]); + setSelectedQuestionTypes([ + ...selectedQuestionTypes, + optionValue, + ]); } else { - setSelectedQuestionTypes((prev) => - prev.filter((questionType) => questionType !== optionValue), + setSelectedQuestionTypes( + selectedQuestionTypes.filter( + (questionType) => questionType !== optionValue, + ), ); } }} @@ -189,10 +199,12 @@ export default function QuestionsHomePage() { searchPlaceholder="Add location filter" onOptionChange={(optionValue, checked) => { if (checked) { - setSelectedLocations((prev) => [...prev, optionValue]); + setSelectedLocations([...selectedLocations, optionValue]); } else { - setSelectedLocations((prev) => - prev.filter((location) => location !== optionValue), + setSelectedLocations( + selectedLocations.filter( + (location) => location !== optionValue, + ), ); } }} diff --git a/apps/portal/src/utils/questions/useSearchFilter.ts b/apps/portal/src/utils/questions/useSearchFilter.ts new file mode 100644 index 00000000..2ede6db8 --- /dev/null +++ b/apps/portal/src/utils/questions/useSearchFilter.ts @@ -0,0 +1,54 @@ +import { useRouter } from 'next/router'; +import { useCallback, useEffect, useState } from 'react'; + +export const useSearchFilter = ( + name: string, + defaultValues?: Array, +) => { + const [isInitialized, setIsInitialized] = useState(false); + const router = useRouter(); + + const [filters, setFilters] = useState>(defaultValues || []); + + useEffect(() => { + if (router.isReady && !isInitialized) { + // Initialize from query params + const query = router.query[name]; + if (query) { + const queryValues = Array.isArray(query) ? query : [query]; + setFilters(queryValues); + } else { + // Try to load from local storage + const localStorageValue = localStorage.getItem(name); + if (localStorageValue !== null) { + setFilters(JSON.parse(localStorageValue)); + } + } + setIsInitialized(true); + } + }, [router.isReady, isInitialized, router.query, name]); + + const setFiltersAndSaveToLocalStorage = useCallback( + (newFilters: Array) => { + setFilters(newFilters); + localStorage.setItem(name, JSON.stringify(newFilters)); + }, + [name], + ); + + return [filters, setFiltersAndSaveToLocalStorage, isInitialized] as const; +}; + +export const useSearchFilterSingle = (name: string, defaultValue: string) => { + const [filters, setFilters, isInitialized] = useSearchFilter(name, [ + defaultValue, + ]); + + return [ + filters[0], + (value: string) => { + setFilters([value]); + }, + isInitialized, + ] as const; +};