mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-19 13:18:30 +02:00
paginate and sort UTXOs by value (#1031)
This commit is contained in:
parent
1942955e19
commit
7c454482bb
2 changed files with 99 additions and 34 deletions
|
|
@ -18,6 +18,13 @@ import { buttonVariants } from '@/components/ui/button-variants'
|
|||
import { Card, CardContent } from '@/components/ui/card'
|
||||
import { CopyButton } from '@/components/ui/jam/CopyButton'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Pagination,
|
||||
PaginationContent,
|
||||
PaginationItem,
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
} from '@/components/ui/pagination'
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
|
||||
import { Spinner } from '@/components/ui/spinner'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
|
|
@ -50,6 +57,8 @@ export function CreateFidelityBondDialogSteps({ wizard }: CreateFidelityBondDial
|
|||
jarsWithUtxos,
|
||||
selectedUtxos,
|
||||
availableUtxos,
|
||||
utxoPage,
|
||||
setUtxoPage,
|
||||
toggleUtxoSelection,
|
||||
selectAllUtxos,
|
||||
deselectAllUtxos,
|
||||
|
|
@ -233,40 +242,80 @@ export function CreateFidelityBondDialogSteps({ wizard }: CreateFidelityBondDial
|
|||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="max-h-72 space-y-2 overflow-x-hidden overflow-y-auto pr-1">
|
||||
{availableUtxos.map((utxo) => {
|
||||
const isSelected = selectedUtxos.some((u) => u.utxo === utxo.utxo)
|
||||
<div className="space-y-2">
|
||||
{(() => {
|
||||
const perPage = 5
|
||||
const totalPages = Math.ceil(availableUtxos.length / perPage)
|
||||
const page = Math.max(0, Math.min(utxoPage, totalPages - 1))
|
||||
const paged = availableUtxos.slice(page * perPage, (page + 1) * perPage)
|
||||
|
||||
return (
|
||||
<Card
|
||||
key={utxo.utxo}
|
||||
className={cn(
|
||||
'cursor-pointer transition-all duration-200',
|
||||
isSelected ? 'border-primary bg-primary/5 shadow-sm' : 'hover:bg-muted/30 hover:shadow-sm',
|
||||
<>
|
||||
{paged.map((utxo) => {
|
||||
const isSelected = selectedUtxos.some((u) => u.utxo === utxo.utxo)
|
||||
return (
|
||||
<Card
|
||||
key={utxo.utxo}
|
||||
className={cn(
|
||||
'cursor-pointer transition-all duration-200',
|
||||
isSelected ? 'border-primary bg-primary/5 shadow-sm' : 'hover:bg-muted/30 hover:shadow-sm',
|
||||
)}
|
||||
onClick={() => toggleUtxoSelection(utxo)}
|
||||
>
|
||||
<CardContent className="flex items-center gap-3 p-3">
|
||||
<div
|
||||
className={cn(
|
||||
'flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-all',
|
||||
isSelected
|
||||
? 'border-primary bg-primary text-primary-foreground'
|
||||
: 'border-muted-foreground/40',
|
||||
)}
|
||||
>
|
||||
{isSelected && <CheckIcon className="h-3.5 w-3.5" />}
|
||||
</div>
|
||||
<div className="min-w-0 flex-1 overflow-hidden">
|
||||
<p className="truncate font-mono text-xs break-all">{utxo.utxo}</p>
|
||||
<p className="text-muted-foreground mt-0.5 text-xs">
|
||||
{t('earn.fidelity_bond.select_utxos.utxo_card.confirmations', {
|
||||
confs: utxo.confirmations,
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
<div className="shrink-0 text-right">
|
||||
<p className="font-mono text-sm font-semibold whitespace-nowrap">
|
||||
{formatSats(utxo.value)}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
{totalPages > 1 && (
|
||||
<Pagination className="pt-2">
|
||||
<PaginationContent>
|
||||
<PaginationItem>
|
||||
<PaginationPrevious
|
||||
onClick={() => setUtxoPage(Math.max(0, page - 1))}
|
||||
disabled={page === 0}
|
||||
/>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<span className="text-muted-foreground px-2 text-sm">
|
||||
{page + 1} / {totalPages}
|
||||
</span>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationNext
|
||||
onClick={() => setUtxoPage(Math.min(totalPages - 1, page + 1))}
|
||||
disabled={page >= totalPages - 1}
|
||||
/>
|
||||
</PaginationItem>
|
||||
</PaginationContent>
|
||||
</Pagination>
|
||||
)}
|
||||
onClick={() => toggleUtxoSelection(utxo)}
|
||||
>
|
||||
<CardContent className="flex items-center gap-3 p-3">
|
||||
<div
|
||||
className={cn(
|
||||
'flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-all',
|
||||
isSelected ? 'border-primary bg-primary text-primary-foreground' : 'border-muted-foreground/40',
|
||||
)}
|
||||
>
|
||||
{isSelected && <CheckIcon className="h-3.5 w-3.5" />}
|
||||
</div>
|
||||
<div className="min-w-0 flex-1 overflow-hidden">
|
||||
<p className="truncate font-mono text-xs break-all">{utxo.utxo}</p>
|
||||
<p className="text-muted-foreground mt-0.5 text-xs">
|
||||
{t('earn.fidelity_bond.select_utxos.utxo_card.confirmations', { confs: utxo.confirmations })}
|
||||
</p>
|
||||
</div>
|
||||
<div className="shrink-0 text-right">
|
||||
<p className="font-mono text-sm font-semibold whitespace-nowrap">{formatSats(utxo.value)}</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
)
|
||||
})}
|
||||
})()}
|
||||
</div>
|
||||
|
||||
{selectedUtxos.length > 0 && (
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export function useCreateFidelityBondWizard(
|
|||
const [selectedJarIndex, setSelectedJarIndex] = useState<JarIndex | undefined>()
|
||||
const [selectedUtxos, setSelectedUtxos] = useState<Utxo[]>([])
|
||||
const [frozenUtxos, setFrozenUtxos] = useState<Utxo[]>([])
|
||||
const [utxoPage, setUtxoPage] = useState(0)
|
||||
const [confirmationChecked, setConfirmationChecked] = useState(false)
|
||||
const [txResult, setTxResult] = useState<DirectSendResponse | undefined>()
|
||||
const [error, setError] = useState<string | undefined>()
|
||||
|
|
@ -77,7 +78,9 @@ export function useCreateFidelityBondWizard(
|
|||
if (selectedJarIndex === undefined) return []
|
||||
const jar = walletInfo.jars.find((it) => it.jarIndex === selectedJarIndex)
|
||||
if (!jar) return []
|
||||
return jar.utxos.filter((utxo) => !utxo.frozen && !fb.utxo.isFidelityBond(utxo))
|
||||
return jar.utxos
|
||||
.filter((utxo) => !utxo.frozen && !fb.utxo.isFidelityBond(utxo))
|
||||
.toSorted((a, b) => b.value - a.value)
|
||||
}, [walletInfo.jars, selectedJarIndex])
|
||||
|
||||
const utxosToFreeze = useMemo(() => {
|
||||
|
|
@ -143,6 +146,7 @@ export function useCreateFidelityBondWizard(
|
|||
setSelectedJarIndex(undefined)
|
||||
setSelectedUtxos([])
|
||||
setFrozenUtxos([])
|
||||
setUtxoPage(0)
|
||||
setConfirmationChecked(false)
|
||||
setTxResult(undefined)
|
||||
setError(undefined)
|
||||
|
|
@ -162,16 +166,24 @@ export function useCreateFidelityBondWizard(
|
|||
setStep('select_date')
|
||||
break
|
||||
case 'select_utxos':
|
||||
setStep('select_jar')
|
||||
setSelectedUtxos([])
|
||||
if (jarsWithUtxos.length === 1) {
|
||||
setSelectedJarIndex(undefined)
|
||||
setSelectedUtxos([])
|
||||
setStep('select_date')
|
||||
} else {
|
||||
setSelectedUtxos([])
|
||||
setStep('select_jar')
|
||||
}
|
||||
break
|
||||
case 'freeze_utxos':
|
||||
setUtxoPage(0)
|
||||
setStep('select_utxos')
|
||||
break
|
||||
case 'review':
|
||||
if (utxosToFreeze.length > 0) {
|
||||
setStep('freeze_utxos')
|
||||
} else {
|
||||
setUtxoPage(0)
|
||||
setStep('select_utxos')
|
||||
}
|
||||
break
|
||||
|
|
@ -184,12 +196,14 @@ export function useCreateFidelityBondWizard(
|
|||
case 'select_date':
|
||||
if (jarsWithUtxos.length === 1) {
|
||||
setSelectedJarIndex(jarsWithUtxos[0].jarIndex)
|
||||
setUtxoPage(0)
|
||||
setStep('select_utxos')
|
||||
} else {
|
||||
setStep('select_jar')
|
||||
}
|
||||
break
|
||||
case 'select_jar':
|
||||
setUtxoPage(0)
|
||||
setStep('select_utxos')
|
||||
break
|
||||
case 'select_utxos':
|
||||
|
|
@ -324,6 +338,8 @@ export function useCreateFidelityBondWizard(
|
|||
jarsWithUtxos,
|
||||
selectedUtxos,
|
||||
availableUtxos,
|
||||
utxoPage,
|
||||
setUtxoPage,
|
||||
toggleUtxoSelection,
|
||||
selectAllUtxos,
|
||||
deselectAllUtxos,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue