mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-20 13:28:21 +02:00
chore(orderbook): use dialog for orderbook overlay
This commit is contained in:
parent
7918a64878
commit
77392c397d
5 changed files with 46 additions and 37 deletions
|
|
@ -1,13 +1,23 @@
|
|||
import { useState, useMemo } from 'react'
|
||||
import { DropdownMenu } from '@radix-ui/react-dropdown-menu'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import type { RowModel } from '@tanstack/react-table'
|
||||
import type { i18n } from 'i18next'
|
||||
import { ChevronDownIcon, RefreshCwIcon, PlusIcon, AlertCircleIcon, Loader2Icon } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStore } from 'zustand'
|
||||
import { DevBadge } from '@/components/dev/DevBadge'
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { ButtonGroup } from '@/components/ui/button-group'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { JM_DUST_THRESHOLD } from '@/constants/jm'
|
||||
import * as OrderbookApi from '@/lib/api/orderbook'
|
||||
|
|
@ -23,11 +33,6 @@ import {
|
|||
} from '@/lib/utils'
|
||||
import { jamSettingsStore } from '@/store/jamSettingsStore'
|
||||
import { jmSessionStore } from '@/store/jmSessionStore'
|
||||
import { DevBadge } from '../dev/DevBadge'
|
||||
import { Alert, AlertDescription } from '../ui/alert'
|
||||
import { ButtonGroup } from '../ui/button-group'
|
||||
import { DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuTrigger } from '../ui/dropdown-menu'
|
||||
import { Label } from '../ui/label'
|
||||
import { OrderbookTable, type OrderTableEntry } from './OrderbookTable'
|
||||
|
||||
const offerToTableEntry = (
|
||||
|
|
@ -89,9 +94,10 @@ const offerToTableEntry = (
|
|||
|
||||
interface OrderbookContentProps {
|
||||
className?: string
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export const OrderbookContent = ({ className }: OrderbookContentProps) => {
|
||||
export const OrderbookContent = ({ enabled, className }: OrderbookContentProps) => {
|
||||
const { t, i18n } = useTranslation()
|
||||
|
||||
const nickname = useStore(jmSessionStore, (state) => state.state?.nickname)
|
||||
|
|
@ -142,6 +148,7 @@ export const OrderbookContent = ({ className }: OrderbookContentProps) => {
|
|||
queryFn: withQueryDelay(OrderbookApi.fetchOrderbook, {
|
||||
delayAfter: 210,
|
||||
}),
|
||||
enabled,
|
||||
})
|
||||
|
||||
const isFetching = isFetchingOrderbookData || isFetchingOrderbookRefresh
|
||||
|
|
@ -225,9 +232,15 @@ export const OrderbookContent = ({ className }: OrderbookContentProps) => {
|
|||
|
||||
<div className="flex items-center space-x-2">
|
||||
{showDemoButton && (
|
||||
<Button variant="outline" size="sm" onClick={__dev_generateDemoReportEntryButton} disabled={isFetching}>
|
||||
<PlusIcon />
|
||||
Generate Demo Entry
|
||||
<Button
|
||||
className="text-xs"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={__dev_generateDemoReportEntryButton}
|
||||
disabled={isFetching}
|
||||
>
|
||||
<PlusIcon className="size-3" />
|
||||
Add Demo Entry
|
||||
<DevBadge />
|
||||
</Button>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { XIcon } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import PageTitle from '../ui/jam/PageTitle'
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||||
import PageTitle from '@/components/ui/jam/PageTitle'
|
||||
import { OrderbookContent } from './OrderbookContent'
|
||||
|
||||
interface OrderbookOverlayProps {
|
||||
|
|
@ -11,23 +10,19 @@ interface OrderbookOverlayProps {
|
|||
|
||||
export function OrderbookOverlay({ open, onOpenChange }: OrderbookOverlayProps) {
|
||||
const { t } = useTranslation()
|
||||
if (!open) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="light:bg-white animate-slide-up fixed inset-0 z-50 flex flex-col bg-zinc-900">
|
||||
<div className="flex items-center justify-between border-b px-6 py-4">
|
||||
<PageTitle title={t('orderbook.title')} />
|
||||
<Button variant="ghost" size="lg" onClick={() => onOpenChange(false)} title={t('global.close')}>
|
||||
<XIcon />
|
||||
<span className="sr-only">{t('global.close')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
<Dialog open={open} onOpenChange={() => onOpenChange(false)}>
|
||||
<DialogContent className="data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom flex h-screen max-w-screen! flex-col rounded-none border-none">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<PageTitle title={t('orderbook.title')} />
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<OrderbookContent className="flex h-full flex-col p-4" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="overflow-hidden">
|
||||
<OrderbookContent enabled={open} className="flex h-full flex-col" />
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export const OrderbookPage = () => {
|
|||
return (
|
||||
<div className="mx-auto space-y-3 p-4">
|
||||
<PageTitle title={t('orderbook.title')} />
|
||||
<OrderbookContent />
|
||||
<OrderbookContent enabled={true} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,14 +57,12 @@ export const SeedPhraseDialog = ({ walletFileName, open, onOpenChange }: SeedPhr
|
|||
retry: false,
|
||||
select: (data) => data.seedphrase,
|
||||
})
|
||||
const seedQueryData = useMemo(() => seedQuery.data, [seedQuery.data])
|
||||
const seedQueryRefetch = useMemo(() => seedQuery.refetch, [seedQuery.refetch])
|
||||
|
||||
useEffect(() => {
|
||||
if (open && isPasswordVerified && seedQueryData === undefined) {
|
||||
seedQueryRefetch()
|
||||
if (open && isPasswordVerified && seedQuery.data === undefined) {
|
||||
seedQuery.refetch()
|
||||
}
|
||||
}, [open, isPasswordVerified, seedQueryData, seedQueryRefetch])
|
||||
}, [open, isPasswordVerified, seedQuery])
|
||||
|
||||
useEffect(() => {
|
||||
if (passwordVerifiedAt === undefined) {
|
||||
|
|
@ -186,7 +184,7 @@ export const SeedPhraseDialog = ({ walletFileName, open, onOpenChange }: SeedPhr
|
|||
<Button variant="outline" onClick={handleClose}>
|
||||
{t('global.cancel')}
|
||||
</Button>
|
||||
<Button onClick={handlePasswordSubmit} disabled={!password || isSubmitting}>
|
||||
<Button type="submit" onClick={handlePasswordSubmit} disabled={!password || isSubmitting}>
|
||||
{isSubmitting ? (
|
||||
<>
|
||||
<Loader2Icon className="h-4 w-4 animate-spin motion-reduce:hidden" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import * as React from 'react'
|
||||
import * as DialogPrimitive from '@radix-ui/react-dialog'
|
||||
import { XIcon } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
||||
|
|
@ -40,6 +41,7 @@ function DialogContent({
|
|||
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
||||
showCloseButton?: boolean
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<DialogPortal data-slot="dialog-portal">
|
||||
<DialogOverlay />
|
||||
|
|
@ -54,11 +56,12 @@ function DialogContent({
|
|||
{children}
|
||||
{showCloseButton && (
|
||||
<DialogPrimitive.Close
|
||||
title={t('global.close')}
|
||||
data-slot="dialog-close"
|
||||
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 cursor-pointer rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
||||
>
|
||||
<XIcon />
|
||||
<span className="sr-only">Close</span>
|
||||
<span className="sr-only">{t('global.close')}</span>
|
||||
</DialogPrimitive.Close>
|
||||
)}
|
||||
</DialogPrimitive.Content>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue