Merge pull request #28 from jedmund/search-recents

Add recent searches
This commit is contained in:
Justin Edmund 2022-03-11 02:37:24 -08:00 committed by GitHub
commit b30d56ecc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 9 deletions

View file

@ -1,4 +1,5 @@
import React, { useEffect, useRef, useState } from 'react' import React, { useEffect, useRef, useState } from 'react'
import { useCookies } from 'react-cookie'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useSnapshot } from 'valtio' import { useSnapshot } from 'valtio'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@ -19,6 +20,7 @@ import SummonResult from '~components/SummonResult'
import './index.scss' import './index.scss'
import CrossIcon from '~public/icons/Cross.svg' import CrossIcon from '~public/icons/Cross.svg'
import cloneDeep from 'lodash.clonedeep'
interface Props { interface Props {
send: (object: Character | Weapon | Summon, position: number) => any send: (object: Character | Weapon | Summon, position: number) => any
@ -29,16 +31,23 @@ interface Props {
} }
const SearchModal = (props: Props) => { const SearchModal = (props: Props) => {
let { grid } = useSnapshot(appState) // Set up snapshot of app state
let { grid, search } = useSnapshot(appState)
// Set up router
const router = useRouter() const router = useRouter()
const locale = router.locale const locale = router.locale
// Set up translation
const { t } = useTranslation('common') const { t } = useTranslation('common')
// Set up cookies
const [cookies, setCookies] = useCookies()
let searchInput = React.createRef<HTMLInputElement>() let searchInput = React.createRef<HTMLInputElement>()
let scrollContainer = React.createRef<HTMLDivElement>() let scrollContainer = React.createRef<HTMLDivElement>()
const [firstLoad, setFirstLoad] = useState(true)
const [objects, setObjects] = useState<{[id: number]: GridCharacter | GridWeapon | GridSummon}>() const [objects, setObjects] = useState<{[id: number]: GridCharacter | GridWeapon | GridSummon}>()
const [filters, setFilters] = useState<{ [key: string]: number[] }>() const [filters, setFilters] = useState<{ [key: string]: number[] }>()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
@ -101,9 +110,30 @@ const SearchModal = (props: Props) => {
setResults([...results, ...list]) setResults([...results, ...list])
} }
function storeRecentResult(result: Character | Weapon | Summon) {
const key = `recent_${props.object}`
let recents: Character[] | Weapon[] | Summon[] = []
if (props.object === "weapons") {
recents = cloneDeep(cookies[key] as Weapon[])
if (!recents.find(item => item.granblue_id === result.granblue_id)) {
recents.unshift(result as Weapon)
}
} else if (props.object === "summons") {
recents = cloneDeep(cookies[key] as Summon[])
if (!recents.find(item => item.granblue_id === result.granblue_id)) {
recents.unshift(result as Summon)
}
}
if (recents.length > 5) recents.pop()
setCookies(`recent_${props.object}`, recents, { path: '/' })
sendData(result)
}
function sendData(result: Character | Weapon | Summon) { function sendData(result: Character | Weapon | Summon) {
props.send(result, props.fromPosition) props.send(result, props.fromPosition)
setOpen(false) openChange()
} }
function receiveFilters(filters: { [key: string]: number[] }) { function receiveFilters(filters: { [key: string]: number[] }) {
@ -123,9 +153,17 @@ const SearchModal = (props: Props) => {
useEffect(() => { useEffect(() => {
// Filters changed // Filters changed
const key = `recent_${props.object}`
if (open) { if (open) {
setCurrentPage(1) if (firstLoad && cookies[key].length > 0) {
fetchResults({ replace: true }) setResults(cookies[key])
setRecordCount(cookies[key].length)
setFirstLoad(false)
} else {
setCurrentPage(1)
fetchResults({ replace: true })
}
} }
}, [filters]) }, [filters])
@ -173,7 +211,7 @@ const SearchModal = (props: Props) => {
return <WeaponResult return <WeaponResult
key={result.id} key={result.id}
data={result} data={result}
onClick={() => { sendData(result) }} onClick={() => { storeRecentResult(result) }}
/> />
}) })
} }
@ -190,7 +228,7 @@ const SearchModal = (props: Props) => {
return <SummonResult return <SummonResult
key={result.id} key={result.id}
data={result} data={result}
onClick={() => { sendData(result) }} onClick={() => { storeRecentResult(result) }}
/> />
}) })
} }
@ -207,7 +245,7 @@ const SearchModal = (props: Props) => {
return <CharacterResult return <CharacterResult
key={result.id} key={result.id}
data={result} data={result}
onClick={() => { sendData(result) }} onClick={() => { storeRecentResult(result) }}
/> />
}) })
} }
@ -218,7 +256,10 @@ const SearchModal = (props: Props) => {
function openChange() { function openChange() {
if (open) { if (open) {
setQuery('') setQuery('')
setFirstLoad(true)
setResults([]) setResults([])
setRecordCount(0)
setCurrentPage(1)
setOpen(false) setOpen(false)
} else { } else {
setOpen(true) setOpen(true)

View file

@ -208,6 +208,7 @@
"not_found": "You haven't saved any teams" "not_found": "You haven't saved any teams"
}, },
"search": { "search": {
"recent": "Recently added",
"result_count": "{{record_count}} results", "result_count": "{{record_count}} results",
"errors": { "errors": {
"start_typing": "Start typing the name of a {{object}}", "start_typing": "Start typing the name of a {{object}}",

View file

@ -209,6 +209,7 @@
"not_found": "編成はまだ保存していません" "not_found": "編成はまだ保存していません"
}, },
"search": { "search": {
"recent": "最近追加した",
"result_count": "{{record_count}}件", "result_count": "{{record_count}}件",
"errors": { "errors": {
"start_typing": "{{object}}名を入力してください", "start_typing": "{{object}}名を入力してください",

View file

@ -28,7 +28,11 @@ interface AppState {
characters: GridArray<GridCharacter> characters: GridArray<GridCharacter>
}, },
search: { search: {
sourceItem: GridCharacter | GridWeapon | GridSummon | undefined recents: {
characters: Character[]
weapons: Weapon[]
summons: Summon[]
}
}, },
raids: Raid[] raids: Raid[]
} }
@ -59,7 +63,11 @@ export const initialAppState: AppState = {
characters: {} characters: {}
}, },
search: { search: {
sourceItem: undefined recents: {
characters: [],
weapons: [],
summons: []
}
}, },
raids: [] raids: []
} }