Wallet filters (#1627)

* Add wallet filters

* Fix grid layout shift

* Store filter state in query params

* Use auto-fill instead of auto-fit

This doesn't seem to change anything but this is closer to our intention how the grid should work with fixed column width.

* Use same order for filters as icons in card

* Use state update function

* Use user-select: none for wallet filters

* Remove unnecessary '|| false'

* Add media query to keep centered grid layout on small screens

* Decrease wallet filter margin-top to 1rem

* fix wallet support usage

* improve grid

---------

Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
Co-authored-by: k00b <k00b@stacker.news>
This commit is contained in:
ekzyis 2024-11-27 18:39:30 +01:00 committed by GitHub
parent 0bff478d39
commit a032da57b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 89 additions and 27 deletions

View File

@ -7,6 +7,11 @@ import { useCallback, useState } from 'react'
import { useIsClient } from '@/components/use-client' import { useIsClient } from '@/components/use-client'
import WalletCard from '@/components/wallet-card' import WalletCard from '@/components/wallet-card'
import { useToast } from '@/components/toast' import { useToast } from '@/components/toast'
import BootstrapForm from 'react-bootstrap/Form'
import RecvIcon from '@/svgs/arrow-left-down-line.svg'
import SendIcon from '@/svgs/arrow-right-up-line.svg'
import { useRouter } from 'next/router'
import { supportsReceive, supportsSend } from '@/wallets/common'
export const getServerSideProps = getGetServerSideProps({ authRequired: true }) export const getServerSideProps = getGetServerSideProps({ authRequired: true })
@ -17,6 +22,12 @@ export default function Wallet ({ ssrData }) {
const [sourceIndex, setSourceIndex] = useState(null) const [sourceIndex, setSourceIndex] = useState(null)
const [targetIndex, setTargetIndex] = useState(null) const [targetIndex, setTargetIndex] = useState(null)
const router = useRouter()
const [filter, setFilter] = useState({
send: router.query.send === 'true',
receive: router.query.receive === 'true'
})
const reorder = useCallback(async (sourceIndex, targetIndex) => { const reorder = useCallback(async (sourceIndex, targetIndex) => {
const newOrder = [...wallets.filter(w => w.config?.enabled)] const newOrder = [...wallets.filter(w => w.config?.enabled)]
const [source] = newOrder.splice(sourceIndex, 1) const [source] = newOrder.splice(sourceIndex, 1)
@ -65,6 +76,13 @@ export default function Wallet ({ ssrData }) {
} }
}, [sourceIndex, reorder, onReorderError]) }, [sourceIndex, reorder, onReorderError])
const onFilterChange = useCallback((key) => {
return e => {
setFilter(old => ({ ...old, [key]: e.target.checked }))
router.replace({ query: { ...router.query, [key]: e.target.checked } }, undefined, { shallow: true })
}
}, [router])
return ( return (
<Layout> <Layout>
<div className='py-5 w-100'> <div className='py-5 w-100'>
@ -76,33 +94,52 @@ export default function Wallet ({ ssrData }) {
</Link> </Link>
</div> </div>
<div className={styles.walletGrid} onDragEnd={onDragEnd}> <div className={styles.walletGrid} onDragEnd={onDragEnd}>
{wallets.map((w, i) => { <div className={styles.walletFilters}>
const draggable = isClient && w.config?.enabled <BootstrapForm.Check
inline
label={<span><RecvIcon width={16} height={16} /> receive</span>}
onChange={onFilterChange('receive')}
checked={filter.receive}
/>
<BootstrapForm.Check
inline
label={<span><SendIcon width={16} height={16} /> send</span>}
onChange={onFilterChange('send')}
checked={filter.send}
/>
</div>
{wallets
.filter(w => {
return (!filter.send || (filter.send && supportsSend(w))) &&
(!filter.receive || (filter.receive && supportsReceive(w)))
})
.map((w, i) => {
const draggable = isClient && w.config?.enabled
return ( return (
<div <div
key={w.def.name} key={w.def.name}
className={ className={
!draggable !draggable
? '' ? ''
: (`${sourceIndex === i ? styles.drag : ''} ${draggable && targetIndex === i ? styles.drop : ''}`) : (`${sourceIndex === i ? styles.drag : ''} ${draggable && targetIndex === i ? styles.drop : ''}`)
} }
suppressHydrationWarning suppressHydrationWarning
> >
<WalletCard <WalletCard
wallet={w} wallet={w}
draggable={draggable} draggable={draggable}
onDragStart={draggable ? onDragStart(i) : undefined} onDragStart={draggable ? onDragStart(i) : undefined}
onTouchStart={draggable ? onTouchStart(i) : undefined} onTouchStart={draggable ? onTouchStart(i) : undefined}
onDragEnter={draggable ? onDragEnter(i) : undefined} onDragEnter={draggable ? onDragEnter(i) : undefined}
sourceIndex={sourceIndex} sourceIndex={sourceIndex}
targetIndex={targetIndex} targetIndex={targetIndex}
index={i} index={i}
/> />
</div> </div>
) )
} }
)} )}
</div> </div>
</div> </div>

View File

@ -1,10 +1,34 @@
.walletGrid { .walletGrid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); grid-template-columns: repeat(auto-fill, 160px);
grid-gap: 20px; grid-gap: 20px;
justify-items: center; padding: 20px 0;
align-items: center; justify-content: center;
margin-top: 3rem; }
@media (max-width: 440px) {
.walletGrid {
grid-template-columns: repeat(auto-fill, 140px);
grid-gap: 15px;
}
.card {
width: 140px;
}
}
@media (max-width: 330px) {
.walletGrid {
grid-template-columns: 100%;
}
.walletGrid > * {
justify-self: center;
}
}
.walletFilters {
grid-column: 1 / -1;
margin-left: 0.2rem;
user-select: none;
} }
.drag { .drag {
@ -17,7 +41,8 @@
.card { .card {
width: 160px; width: 160px;
height: 180px; max-width: 100%;
aspect-ratio: 160 / 180;
} }
.indicators { .indicators {