Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use sessionStorage to save state of filters #751

Merged
merged 8 commits into from
Feb 1, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { SearchBar } from "./SearchBar"
import { ImageDataLike } from "gatsby-plugin-image"
import { Label } from "./Label"

const isBrowser = typeof window !== "undefined"

function customSort(dateField: string, sortAscending: boolean) {
return function (a, b) {
let sortValue
Expand Down Expand Up @@ -37,6 +39,7 @@ function customSort(dateField: string, sortAscending: boolean) {
return sortValue
}
}

export interface ProjectPageProps {
title: string
lede: string
Expand Down Expand Up @@ -119,7 +122,16 @@ export const ProjectPage = ({
}
}

const [sortDirection, setSortDirection] = useState(sortingOptions[0])
let initialSortingDirection = sortingOptions[0]
if (isBrowser) {
const cachedSortingDirection = sessionStorage.getItem(
`${title}_sortDirection`
)
if (cachedSortingDirection) {
initialSortingDirection = JSON.parse(cachedSortingDirection)
}
}
const [sortDirection, setSortDirection] = useState(initialSortingDirection)

const [pageStart, setPageStart] = useState(0)
const [pageEnd, setPageEnd] = useState(ITEMS_PER_PAGE)
Expand All @@ -139,7 +151,14 @@ export const ProjectPage = ({
scrollToRef?.current?.scrollIntoView({ behavior: "smooth" })
}

const [searchQuery, setSearchQuery] = useState([])
let initialSearchQuery: string[] = []
if (isBrowser) {
const cachedSearchQuery = sessionStorage.getItem(`${title}_searchQuery`)
if (cachedSearchQuery) {
initialSearchQuery = JSON.parse(cachedSearchQuery)
}
}
const [searchQuery, setSearchQuery] = useState(initialSearchQuery)

let search = new JsSearch.Search("slug")
search.addIndex("topicNames")
Expand Down Expand Up @@ -195,14 +214,36 @@ export const ProjectPage = ({
setHasNext(pageEnd < displayProjects.length)
}, [list]) // triggered when list is changed

const [selectedTopicOptions, setSelectedTopicOptions] = useState<
MultiValue<any>
>([])
const [selectedAgencyOptions, setSelectedAgencyOptions] = useState<
MultiValue<any>
>([])
let initialTopicOptions = []
if (isBrowser) {
const cachedFilterByTopic = sessionStorage.getItem(`${title}_filterByTopic`)
if (cachedFilterByTopic) {
initialTopicOptions = JSON.parse(cachedFilterByTopic)
}
}
const [selectedTopicOptions, setSelectedTopicOptions] =
useState<MultiValue<any>>(initialTopicOptions)

let initialAgencyOptions = []
if (isBrowser) {
const cachedFilterByAgency = sessionStorage.getItem(
`${title}_filterByAgency`
)
if (cachedFilterByAgency) {
initialAgencyOptions = JSON.parse(cachedFilterByAgency)
}
}
const [selectedAgencyOptions, setSelectedAgencyOptions] =
useState<MultiValue<any>>(initialAgencyOptions)

useEffect(() => {
isBrowser &&
sessionStorage.setItem(
`${title}_sortDirection`,
JSON.stringify(sortDirection)
)
//1. Sort by. Custom sort function that filters in ascending or descending
// based on certain dates associated with the type of project.
const sortedList = [...allProjects]
sortedList.sort(
customSort(sortDirection.field, sortDirection.sortAscending)
Expand All @@ -225,28 +266,50 @@ export const ProjectPage = ({
// apply it to filteredProjects
// or else stick with sortedProjects (which may have been updated by sortOptions) aka the first check
if (selectedTopicOptions.length > 0) {
isBrowser &&
sessionStorage.setItem(
`${title}_filterByTopic`,
JSON.stringify(selectedTopicOptions)
)

const filteredTopics = selectedTopicOptions.map(({ value }) => value)
filteredProjects = sortedProjects.filter((project) =>
project.topics
.map((topic) => topic.slug)
.some((topicSlug) => filteredTopics.includes(topicSlug))
)
} else {
isBrowser && sessionStorage.setItem(`${title}_filterByTopic`, "")
}
setPageStart(0)
setPageEnd(ITEMS_PER_PAGE)

// 3. filter by agency. If there are any filters chosen
// apply it to filteredProjects
if (selectedAgencyOptions.length > 0) {
isBrowser &&
sessionStorage.setItem(
`${title}_filterByAgency`,
JSON.stringify(selectedAgencyOptions)
)

const filteredAgency = selectedAgencyOptions.map(({ value }) => value)
filteredProjects = filteredProjects.filter((project) =>
filteredAgency.includes(project.agency)
)
} else {
isBrowser && sessionStorage.setItem(`${title}_filterByAgency`, "")
}

// 4. search query
// if search query is used, we will now apply search results, to filteredProjects
if (searchQuery.length > 0) {
isBrowser &&
sessionStorage.setItem(
`${title}_searchQuery`,
JSON.stringify(searchQuery)
)

for (let i = 0; i < filteredProjects.length; i++) {
filteredProjects[i]["topicNames"] = flattenTopics(filteredProjects[i])
}
Expand All @@ -255,6 +318,8 @@ export const ProjectPage = ({
if (searchResults.length > 0) {
filteredProjects = searchResults
}
} else {
isBrowser && sessionStorage.setItem(`${title}_searchQuery`, "")
}

setFilterOptionsTopic(getTopics(filteredProjects))
Expand Down Expand Up @@ -331,6 +396,7 @@ export const ProjectPage = ({
label={"Search"}
placeholder="Type to filter posts..."
onChange={(e) => setSearchQuery(e.target.value)}
defaultValue={initialSearchQuery || null}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface SearchBarProps {
onChange: any
placeholder: string
autoFocus?: boolean
defaultValue: string[] | null
}

export const SearchBar: FunctionComponent<SearchBarProps> = ({
Expand All @@ -15,6 +16,7 @@ export const SearchBar: FunctionComponent<SearchBarProps> = ({
onChange,
placeholder,
autoFocus,
defaultValue
}) => {
return (
<>
Expand All @@ -28,6 +30,7 @@ export const SearchBar: FunctionComponent<SearchBarProps> = ({
aria-label="Search"
placeholder={placeholder}
onChange={onChange}
defaultValue={defaultValue || undefined}
/>
</>
)
Expand Down
Loading