Search views (#367)

Add support for switching between viewing newly added items and recently
used items in search for weapons and summons
This commit is contained in:
Justin Edmund 2023-08-23 02:49:27 -07:00 committed by GitHub
parent 8877f3cfeb
commit 62b957034f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 116 additions and 40 deletions

View file

@ -16,9 +16,6 @@
@include breakpoint(phone) {
place-items: flex-end;
overflow-y: hidden;
&.filter {
}
}
.dialogContent {
@ -72,7 +69,7 @@
box-sizing: border-box;
display: flex;
flex-direction: column;
min-height: 430px;
height: 60vh;
max-height: none;
padding: 0;
@ -93,7 +90,8 @@
}
&.editParty {
min-height: 80vh;
// min-height: 80vh;
height: 60vh;
.container {
display: flex;
@ -103,6 +101,8 @@
}
.container {
display: flex;
flex-direction: column;
overflow-y: hidden;
&.scrollable {

View file

@ -1,5 +1,6 @@
.header {
align-items: inherit;
border-bottom: 1px solid var(--button-contained-bg);
display: flex;
flex-direction: column;
gap: $unit;
@ -65,23 +66,59 @@
}
.results {
flex-grow: 1;
margin: 0;
padding: 0 ($unit * 1.5);
padding: $unit-2x ($unit * 1.5) 0;
padding-bottom: $unit * 1.5;
// Infinite scroll
overflow-y: auto;
max-height: 500px;
@include breakpoint(phone) {
max-height: initial;
}
h5.total {
font-size: $font-regular;
font-weight: $normal;
color: var(--text-tertiary);
padding: $unit-half ($unit * 1.5);
.totalRow {
font-size: $font-small;
display: flex;
justify-content: space-between;
padding-bottom: $unit-half;
h5.total {
font-weight: $bold;
color: var(--text-tertiary);
padding: $unit-half ($unit * 1.5);
}
.viewSwitcher {
align-items: center;
display: flex;
gap: $unit-fourth;
span {
color: var(--text-tertiary);
margin-right: $unit-half;
}
.link {
background: none;
border-radius: $item-corner-small;
color: var(--text-secondary);
display: inline-block;
font-size: $font-small;
&:hover {
background: var(--button-contained-bg);
cursor: pointer;
text-decoration: none;
}
&.active {
background: var(--button-contained-bg);
font-weight: $bold;
}
}
}
}
.footer {

View file

@ -26,6 +26,7 @@ import type { SearchableObject, SearchableObjectArray } from '~types'
import styles from './index.module.scss'
import CrossIcon from '~public/icons/Cross.svg'
import classNames from 'classnames'
interface Props extends DialogProps {
send: (object: SearchableObject, position: number) => any
@ -57,8 +58,20 @@ const SearchModal = (props: Props) => {
// Pagination states
const [recordCount, setRecordCount] = useState(0)
const [currentPage, setCurrentPage] = useState(1)
const [currentView, setCurrentView] = useState(0)
const [totalPages, setTotalPages] = useState(1)
// Classes
const newestViewClasses = classNames({
[styles.link]: true,
[styles.active]: currentView === 0,
})
const recentViewClasses = classNames({
[styles.link]: true,
[styles.active]: currentView === 1,
})
useEffect(() => {
if (searchInput.current) searchInput.current.focus()
}, [searchInput])
@ -119,6 +132,7 @@ const SearchModal = (props: Props) => {
const cookieObj: SearchableObjectArray = cookie
? JSON.parse(cookie as string)
: []
let recents: SearchableObjectArray = []
if (props.object === 'weapons') {
@ -187,31 +201,6 @@ const SearchModal = (props: Props) => {
}
}, [open, currentPage])
useEffect(() => {
// Filters changed
const key = `recent_${props.object}`
const cookie = getCookie(key)
const cookieObj: Weapon[] | Summon[] | Character[] = cookie
? JSON.parse(cookie as string)
: []
if (open) {
if (
firstLoad &&
cookieObj &&
cookieObj.length > 0 &&
!extraPositions().includes(props.fromPosition)
) {
setResults(cookieObj)
setRecordCount(cookieObj.length)
setFirstLoad(false)
} else {
setCurrentPage(1)
fetchResults({ replace: true })
}
}
}, [filters])
useEffect(() => {
// Query changed
if (open && query.length != 1) {
@ -231,6 +220,33 @@ const SearchModal = (props: Props) => {
setCurrentPage(currentPage + 1)
}
function showNewest() {
if (currentView !== 0) {
setCurrentView(0)
setCurrentPage(1)
fetchResults({ replace: true })
}
}
function showRecent() {
if (currentView !== 1) {
setCurrentView(1)
// Fetch recently used items
const key = `recent_${props.object}`
const cookie = getCookie(key)
const cookieObj: Weapon[] | Summon[] | Character[] = cookie
? JSON.parse(cookie as string)
: []
// Set the view
setResults(cookieObj)
setRecordCount(cookieObj.length)
setFirstLoad(false)
}
}
function renderResults() {
let jsx
@ -437,9 +453,22 @@ const SearchModal = (props: Props) => {
</header>
<div className={styles.results} ref={scrollContainer}>
<h5 className={styles.total}>
{t('search.result_count', { record_count: recordCount })}
</h5>
<div className={styles.totalRow}>
<h5 className={styles.total}>
{t('search.result_count', { record_count: recordCount })}
</h5>
{(props.object === 'weapons' || props.object === 'summons') && (
<div className={styles.viewSwitcher}>
<span>{t('search.labels.view')}</span>
<button className={newestViewClasses} onClick={showNewest}>
{t('search.labels.newest')}
</button>
<button className={recentViewClasses} onClick={showRecent}>
{t('search.labels.recently_used')}
</button>
</div>
)}
</div>
{open ? renderResults() : ''}
</div>
</DialogContent>

View file

@ -512,6 +512,11 @@
"end_results": "No more results",
"type": "Keep typing..."
},
"labels": {
"view": "View:",
"newest": "Newly added",
"recently_used": "Recently used"
},
"placeholders": {
"weapon": "Search for a weapon...",
"summon": "Search for a summon...",

View file

@ -510,6 +510,11 @@
"end_results": "検索結果これ以上ありません",
"type": "もっと入力してください"
},
"labels": {
"view": "表示:",
"newest": "最新発表",
"recently_used": "最近使用"
},
"placeholders": {
"weapon": "武器を検索...",
"summon": "召喚石を検索...",