mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-20 13:28:21 +02:00
chore(orderbook): split orderbook dialog and content
This commit is contained in:
parent
bfae11d780
commit
1118bfe803
2 changed files with 88 additions and 164 deletions
|
|
@ -85,11 +85,11 @@ const offerToTableEntry = (
|
|||
}
|
||||
}
|
||||
|
||||
interface OrderbookProps {
|
||||
isModal?: boolean
|
||||
interface OrderbookContentProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const Orderbook = ({ isModal = false }: OrderbookProps) => {
|
||||
export const OrderbookContent = ({ className }: OrderbookContentProps) => {
|
||||
const { t, i18n } = useTranslation()
|
||||
|
||||
const nickname = useStore(jmSessionStore, (state) => state.state?.nickname)
|
||||
|
|
@ -248,173 +248,86 @@ export const Orderbook = ({ isModal = false }: OrderbookProps) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn('mx-auto space-y-3 p-4', {
|
||||
'flex h-full flex-col p-10': isModal,
|
||||
})}
|
||||
>
|
||||
{/* Header */}
|
||||
{!isModal && (
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<PageTitle title={t('orderbook.title')} />
|
||||
<p className="text-muted-foreground mt-1">
|
||||
{searchQuery === ''
|
||||
? t('orderbook.text_orderbook_summary', {
|
||||
count: tableEntries.length,
|
||||
counterpartyCount: new Set(tableEntries.map((e) => e.counterparty)).size,
|
||||
})
|
||||
: t('orderbook.text_orderbook_summary_filtered', summary)}
|
||||
</p>
|
||||
</div>
|
||||
<div className={cn('mx-auto space-y-3', className)}>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{searchQuery === ''
|
||||
? t('orderbook.text_orderbook_summary', {
|
||||
count: tableEntries.length,
|
||||
counterpartyCount: new Set(tableEntries.map((e) => e.counterparty)).size,
|
||||
})
|
||||
: t('orderbook.text_orderbook_summary_filtered', summary)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{showDemoButton && (
|
||||
<div className="flex items-center space-x-2">
|
||||
{showDemoButton && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={__dev_generateDemoReportEntryButton}
|
||||
disabled={isFetching}
|
||||
className="relative"
|
||||
>
|
||||
Generate Demo Entry
|
||||
<PlusIcon className="ml-2 h-4 w-4" />
|
||||
<DevBadge />
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<div className="relative" ref={dropdownRef}>
|
||||
<div className="flex">
|
||||
<Button
|
||||
variant="outline"
|
||||
className="rounded-r-none"
|
||||
size="sm"
|
||||
onClick={__dev_generateDemoReportEntryButton}
|
||||
onClick={handleReload}
|
||||
disabled={isFetching}
|
||||
className="relative"
|
||||
>
|
||||
<PlusIcon className="ml-2 h-4 w-4" />
|
||||
Generate Demo Entry
|
||||
<DevBadge />
|
||||
{t('orderbook.button_reload_title')}
|
||||
<RefreshCwIcon
|
||||
className={cn('ml-2 h-4 w-4', {
|
||||
'motion-safe: animate-spin': isFetching,
|
||||
})}
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<div className="relative" ref={dropdownRef}>
|
||||
<div className="flex">
|
||||
<div className="relative">
|
||||
<Button
|
||||
variant="outline"
|
||||
className="rounded-r-none"
|
||||
size="sm"
|
||||
onClick={handleReload}
|
||||
className="rounded-l-none border-l-0 px-2"
|
||||
onClick={() => setShowRefreshDropdown(!showRefreshDropdown)}
|
||||
disabled={isFetching}
|
||||
>
|
||||
<RefreshCwIcon className={cn('h-4 w-4', { 'motion-safe:animate-spin': isFetching })} />
|
||||
{t('orderbook.button_reload_title')}
|
||||
<ChevronDownIcon className="h-4 w-4" />
|
||||
</Button>
|
||||
<div className="relative">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="rounded-l-none border-l-0 px-2"
|
||||
onClick={() => setShowRefreshDropdown(!showRefreshDropdown)}
|
||||
disabled={isFetching}
|
||||
>
|
||||
<ChevronDownIcon className="h-4 w-4" />
|
||||
</Button>
|
||||
{showRefreshDropdown && (
|
||||
<div className="bg-background absolute top-full right-0 z-10 mt-1 min-w-[200px] rounded-md border py-2 shadow-lg">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="w-full justify-start rounded-none"
|
||||
onClick={handleClearAndReload}
|
||||
disabled={isFetching}
|
||||
>
|
||||
{t('orderbook.button_refresh_text')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{showRefreshDropdown && (
|
||||
<div className="bg-background absolute top-full right-0 z-10 mt-1 min-w-[200px] rounded-md border py-2 shadow-lg">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="w-full justify-start rounded-none"
|
||||
onClick={handleClearAndReload}
|
||||
disabled={isFetching}
|
||||
>
|
||||
{t('orderbook.button_refresh_text')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Input
|
||||
placeholder={t('orderbook.placeholder_search')}
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-64"
|
||||
disabled={isFetching}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Input
|
||||
placeholder={t('orderbook.placeholder_search')}
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-64"
|
||||
disabled={isFetching}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Modal Header with controls */}
|
||||
{isModal && (
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{searchQuery === ''
|
||||
? t('orderbook.text_orderbook_summary', {
|
||||
count: tableEntries.length,
|
||||
counterpartyCount: new Set(tableEntries.map((e) => e.counterparty)).size,
|
||||
})
|
||||
: t('orderbook.text_orderbook_summary_filtered', summary)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
{showDemoButton && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={__dev_generateDemoReportEntryButton}
|
||||
disabled={isFetching}
|
||||
className="relative"
|
||||
>
|
||||
Generate Demo Entry
|
||||
<PlusIcon className="ml-2 h-4 w-4" />
|
||||
<DevBadge />
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<div className="relative" ref={dropdownRef}>
|
||||
<div className="flex">
|
||||
<Button
|
||||
variant="outline"
|
||||
className="rounded-r-none"
|
||||
size="sm"
|
||||
onClick={handleReload}
|
||||
disabled={isFetching}
|
||||
>
|
||||
{t('orderbook.button_reload_title')}
|
||||
<RefreshCwIcon
|
||||
className={cn('ml-2 h-4 w-4', {
|
||||
'motion-safe: animate-spin': isFetching,
|
||||
})}
|
||||
/>
|
||||
</Button>
|
||||
<div className="relative">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="rounded-l-none border-l-0 px-2"
|
||||
onClick={() => setShowRefreshDropdown(!showRefreshDropdown)}
|
||||
disabled={isFetching}
|
||||
>
|
||||
<ChevronDownIcon className="h-4 w-4" />
|
||||
</Button>
|
||||
{showRefreshDropdown && (
|
||||
<div className="bg-background absolute top-full right-0 z-10 mt-1 min-w-[200px] rounded-md border py-2 shadow-lg">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="w-full justify-start rounded-none"
|
||||
onClick={handleClearAndReload}
|
||||
disabled={isFetching}
|
||||
>
|
||||
{t('orderbook.button_refresh_text')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Input
|
||||
placeholder={t('orderbook.placeholder_search')}
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-64"
|
||||
disabled={isFetching}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Controls */}
|
||||
{nickname && (
|
||||
|
|
@ -480,3 +393,14 @@ export const Orderbook = ({ isModal = false }: OrderbookProps) => {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const Orderbook = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="mx-auto space-y-3 p-4">
|
||||
<PageTitle title={t('orderbook.title')} />
|
||||
<OrderbookContent />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { XIcon } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Orderbook } from './Orderbook'
|
||||
import PageTitle from '../PageTitle'
|
||||
import { OrderbookContent } from './Orderbook'
|
||||
|
||||
interface OrderbookDialogProps {
|
||||
open: boolean
|
||||
|
|
@ -10,23 +11,22 @@ interface OrderbookDialogProps {
|
|||
|
||||
export function OrderbookDialog({ open, onOpenChange }: OrderbookDialogProps) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
if (!open) return null
|
||||
if (!open) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="light:bg-white fixed inset-0 z-50 flex flex-col bg-zinc-900">
|
||||
{/* Header with close button */}
|
||||
<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">
|
||||
<h1 className="text-lg font-semibold">{t('orderbook.title')}</h1>
|
||||
<Button variant="ghost" size="lg" onClick={() => onOpenChange(false)} className="h-8 w-8 p-0">
|
||||
<XIcon className="h-10 w-10" />
|
||||
<span className="sr-only">Close</span>
|
||||
<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>
|
||||
|
||||
{/* Orderbook content */}
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<Orderbook isModal={true} />
|
||||
<OrderbookContent className="flex h-full flex-col p-4" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue