mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-20 13:28:21 +02:00
feat: add recheck button to OrderbookEmptyAlert
This commit is contained in:
parent
c7fef02ac7
commit
5ddb9a5f00
6 changed files with 60 additions and 10 deletions
|
|
@ -186,7 +186,12 @@ export function SendForm({
|
|||
|
||||
const {
|
||||
hasOrders,
|
||||
queryResult: { isLoading: orderbookCheckIsLoading, isError: orderbookCheckIsError },
|
||||
queryResult: {
|
||||
isLoading: orderbookCheckIsLoading,
|
||||
isFetching: orderbookCheckIsFetching,
|
||||
isError: orderbookCheckIsError,
|
||||
refetch: orderbookRefetch,
|
||||
},
|
||||
} = useQueryOrderbook()
|
||||
|
||||
const destinationAddressInfo = useMemo(() => {
|
||||
|
|
@ -369,7 +374,9 @@ export function SendForm({
|
|||
{hasCoinjoinPreconditionWarning && coinjoinPreconditionSummary && (
|
||||
<SendCoinjoinPreconditionAlert summary={coinjoinPreconditionSummary} />
|
||||
)}
|
||||
{isCoinJoin && !orderbookCheckIsLoading && !orderbookCheckIsError && !hasOrders && <OrderbookEmptyAlert />}
|
||||
{isCoinJoin && !orderbookCheckIsLoading && !orderbookCheckIsError && !hasOrders && (
|
||||
<OrderbookEmptyAlert isChecking={orderbookCheckIsFetching} onCheckClick={orderbookRefetch} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
|
|
|
|||
|
|
@ -76,7 +76,12 @@ export const SweepPage = ({ walletFileName }: SweepPageProps) => {
|
|||
const [alertMessage, setAlertMessage] = useState<string>()
|
||||
const {
|
||||
hasOrders,
|
||||
queryResult: { isLoading: orderbookCheckIsLoading, isError: orderbookCheckIsError },
|
||||
queryResult: {
|
||||
isLoading: orderbookCheckIsLoading,
|
||||
isError: orderbookCheckIsError,
|
||||
isFetching: orderbookCheckIsFetching,
|
||||
refetch: orderbookRefetch,
|
||||
},
|
||||
} = useQueryOrderbook()
|
||||
|
||||
const feeConfigValidation = useFeeConfigValidation({ walletFileName })
|
||||
|
|
@ -290,7 +295,9 @@ export const SweepPage = ({ walletFileName }: SweepPageProps) => {
|
|||
<FeeConfigErrorAlert onOpenFeeConfig={() => setShowFeeConfigDialog(true)} className="mb-4" />
|
||||
)}
|
||||
|
||||
{!orderbookCheckIsLoading && !orderbookCheckIsError && !hasOrders && <OrderbookEmptyAlert className="mb-4" />}
|
||||
{!orderbookCheckIsLoading && !orderbookCheckIsError && !hasOrders && (
|
||||
<OrderbookEmptyAlert isChecking={orderbookCheckIsFetching} onCheckClick={orderbookRefetch} />
|
||||
)}
|
||||
|
||||
{alertMessage && (
|
||||
<Alert variant="destructive">
|
||||
|
|
|
|||
|
|
@ -20,11 +20,27 @@ vi.mock('react-router-dom', () => ({
|
|||
}))
|
||||
|
||||
describe('OrderbookEmptyAlert', () => {
|
||||
it('renders title, description and link to orderbook page', () => {
|
||||
render(<OrderbookEmptyAlert />)
|
||||
it('renders title, description, button and link to orderbook page', () => {
|
||||
render(<OrderbookEmptyAlert isChecking={false} onCheckClick={async () => {}} />)
|
||||
|
||||
expect(screen.getByText('orderbook.alert_precheck_empty_title')).toBeInTheDocument()
|
||||
expect(screen.getByText(/orderbook.alert_precheck_empty_description/u)).toBeInTheDocument()
|
||||
expect(screen.getByRole('link')).toHaveAttribute('href', '/orderbook')
|
||||
|
||||
const actionCheck = screen.getByRole('button', { name: 'orderbook.alert_precheck_empty_text_button_check' })
|
||||
expect(actionCheck).toBeEnabled()
|
||||
|
||||
const actionChecking = screen.queryByRole('button', { name: 'orderbook.alert_precheck_empty_text_button_checking' })
|
||||
expect(actionChecking).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('disables button while checking', () => {
|
||||
render(<OrderbookEmptyAlert isChecking={true} onCheckClick={async () => {}} />)
|
||||
|
||||
const actionChecking = screen.getByRole('button', { name: 'orderbook.alert_precheck_empty_text_button_checking' })
|
||||
expect(actionChecking).toBeDisabled()
|
||||
|
||||
const actionCheck = screen.queryByRole('button', { name: 'orderbook.alert_precheck_empty_text_button_check' })
|
||||
expect(actionCheck).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
import { AlertTriangleIcon } from 'lucide-react'
|
||||
import { AlertTriangleIcon, RefreshCwIcon } from 'lucide-react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
|
||||
import { Alert, AlertAction, AlertDescription, AlertTitle } from '@/components/ui/alert'
|
||||
import { routes } from '@/constants/routes'
|
||||
import { Button } from '../button'
|
||||
|
||||
interface OrderbookEmptyAlertProps {
|
||||
className?: string
|
||||
isChecking?: boolean
|
||||
onCheckClick?: () => Promise<unknown>
|
||||
}
|
||||
|
||||
export const OrderbookEmptyAlert = ({ className }: OrderbookEmptyAlertProps) => {
|
||||
export const OrderbookEmptyAlert = ({ className, isChecking, onCheckClick }: OrderbookEmptyAlertProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
|
|
@ -23,6 +26,16 @@ export const OrderbookEmptyAlert = ({ className }: OrderbookEmptyAlertProps) =>
|
|||
}}
|
||||
/>
|
||||
</AlertDescription>
|
||||
{onCheckClick && (
|
||||
<AlertAction>
|
||||
<Button size="xs" type="button" onClick={() => void onCheckClick()} disabled={isChecking}>
|
||||
<RefreshCwIcon className={isChecking ? 'motion-safe:animate-spin' : undefined} />
|
||||
{isChecking
|
||||
? t('orderbook.alert_precheck_empty_text_button_checking')
|
||||
: t('orderbook.alert_precheck_empty_text_button_check')}
|
||||
</Button>
|
||||
</AlertAction>
|
||||
)}
|
||||
</Alert>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useQuery, type UseQueryResult } from '@tanstack/react-query'
|
||||
import { fetchOrderbook, type OrderbookResponse } from '@/lib/api/orderbook'
|
||||
import { withQueryDelay } from '@/lib/queryClient'
|
||||
|
||||
export type UseQueryOrderbookResult = {
|
||||
hasOrders: boolean
|
||||
|
|
@ -9,7 +10,11 @@ export type UseQueryOrderbookResult = {
|
|||
export function useQueryOrderbook(): UseQueryOrderbookResult {
|
||||
const queryResult = useQuery({
|
||||
queryKey: ['orderbook-precheck'],
|
||||
queryFn: fetchOrderbook,
|
||||
queryFn: withQueryDelay(fetchOrderbook, {
|
||||
// avoid flickering and let user briefly know that something is happening in the background
|
||||
delayBefore: 1_000,
|
||||
}),
|
||||
staleTime: 30 * 1_000,
|
||||
retry: false,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -755,6 +755,8 @@
|
|||
"alert_empty_orderbook": "Orderbook is empty",
|
||||
"alert_precheck_empty_title": "No active makers found",
|
||||
"alert_precheck_empty_description": "Your local Orderbook appears to be empty right now. Collaborative transactions might fail. Please check <1>your local Orderbook</1>.",
|
||||
"alert_precheck_empty_text_button_check": "Check again",
|
||||
"alert_precheck_empty_text_button_checking": "Checking...",
|
||||
"error_loading_orderbook_failed": "Error while loading the orderbook. Your current local setup might not support fetching the orderbook. Reason: {{ reason }}",
|
||||
"text_offer_type_absolute": "absolute",
|
||||
"text_offer_type_relative": "relative",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue