@@ -6,7 +6,7 @@ import { Button } from '@/components/ui/button'
66import { StatusBadge } from '@/shared/status-badge'
77import { TimeDisplay } from '@/shared/time-display'
88import { MoneyDisplay } from '@/shared/money-display'
9- import { AuditTrail , EntityLink , Breadcrumbs } from '@/shared'
9+ import { AuditTrail , EntityLink , Breadcrumbs , PageShell , PageHeader , ErrorState , DetailSkeleton } from '@/shared'
1010import { useAccountResolver } from '@/shared/use-account-resolver'
1111import { DepositDialog } from './deposit-dialog'
1212import { WithdrawDialog } from './withdraw-dialog'
@@ -17,26 +17,6 @@ import { CreateValuationFeatureDialog } from '@/features/reference-data/componen
1717import type { AccountStatus as AccountStatusType } from './types'
1818import { useAccountDetail , useAccountPostings , useAccountLiens } from '../hooks'
1919
20- // ---------------------------------------------------------------------------
21- // Skeleton
22- // ---------------------------------------------------------------------------
23-
24- function AccountDetailSkeleton ( ) {
25- return (
26- < div data-testid = "account-detail-skeleton" className = "animate-pulse space-y-6 p-6" >
27- < div className = "flex items-center gap-3" >
28- < div className = "h-4 w-24 rounded bg-muted" />
29- </ div >
30- < div className = "h-8 w-64 rounded bg-muted" />
31- < div className = "grid grid-cols-2 gap-4 md:grid-cols-4" >
32- { Array . from ( { length : 4 } ) . map ( ( _ , i ) => (
33- < div key = { i } className = "h-20 rounded bg-muted" />
34- ) ) }
35- </ div >
36- < div className = "h-64 rounded bg-muted" />
37- </ div >
38- )
39- }
4020
4121// ---------------------------------------------------------------------------
4222// Not found
@@ -87,7 +67,7 @@ function AccountActions({ status, accountId, currency }: AccountActionsProps) {
8767
8868 return (
8969 < >
90- < div className = "flex gap-2" >
70+ < div className = "flex flex-wrap justify-end gap-2" >
9171 { status === 'ACTIVE' && (
9272 < >
9373 < Button variant = "outline" size = "sm" onClick = { ( ) => setDepositOpen ( true ) } >
@@ -358,13 +338,23 @@ export function AccountDetailPage() {
358338 )
359339
360340 if ( isLoading ) {
361- return < AccountDetailSkeleton />
341+ return (
342+ < PageShell >
343+ < Breadcrumbs items = { [ { label : 'Accounts' , href : '/accounts' } ] } />
344+ < DetailSkeleton />
345+ </ PageShell >
346+ )
362347 }
363348
364349 // Current-account returned 404 — check if it's an internal account
365350 if ( account === null ) {
366351 if ( isResolving ) {
367- return < AccountDetailSkeleton />
352+ return (
353+ < PageShell >
354+ < Breadcrumbs items = { [ { label : 'Accounts' , href : '/accounts' } ] } />
355+ < DetailSkeleton />
356+ </ PageShell >
357+ )
368358 }
369359 if ( resolved ?. type === 'internal' ) {
370360 return < Navigate to = { `/internal-accounts/${ encodeURIComponent ( resolved . accountId ) } ` } replace />
@@ -374,57 +364,50 @@ export function AccountDetailPage() {
374364
375365 if ( isError || account === undefined ) {
376366 return (
377- < div data-testid = "account-error" className = "p-6" >
378- < Breadcrumbs items = { [ { label : 'Accounts' , href : '/accounts' } , { label : accountId ?? 'Error' } ] } />
379- < div className = "mt-8 text-center" >
380- < h2 className = "text-xl font-semibold" > Failed to load account</ h2 >
381- < p className = "mt-2 text-sm text-muted-foreground" >
382- There was a problem loading this account. Please try again.
383- </ p >
384- < Button
385- variant = "outline"
386- size = "sm"
387- className = "mt-4"
388- disabled = { isFetching }
389- onClick = { ( ) => void refetch ( ) }
390- >
391- { isFetching ? 'Retrying…' : 'Retry' }
392- </ Button >
393- </ div >
367+ < div data-testid = "account-error" >
368+ < PageShell >
369+ < Breadcrumbs items = { [ { label : 'Accounts' , href : '/accounts' } , { label : accountId ?? 'Error' } ] } />
370+ < ErrorState
371+ title = "Failed to load account"
372+ message = "There was a problem loading this account. Please try again."
373+ onRetry = { isFetching ? undefined : ( ) => void refetch ( ) }
374+ retryLabel = "Retry"
375+ />
376+ </ PageShell >
394377 </ div >
395378 )
396379 }
397380
398381 return (
399- < div className = "p-6" >
400- { /* Breadcrumb navigation */ }
382+ < PageShell >
401383 < Breadcrumbs
402384 items = { [
403385 { label : 'Accounts' , href : '/accounts' } ,
404386 { label : account . accountId } ,
405387 ] }
406388 />
407389
408- { /* Page header */ }
409- < div className = "mt-4 flex flex-wrap items-start justify-between gap-4" >
410- < div >
411- < div className = "flex items-center gap-3" >
412- < h1 className = "text-2xl font-semibold" > { account . accountId } </ h1 >
413- < StatusBadge status = { account . status } />
414- </ div >
390+ < div >
391+ < PageHeader
392+ title = { account . accountId }
393+ actions = {
394+ < AccountActions
395+ status = { account . status }
396+ accountId = { account . accountId }
397+ currency = { account . instrumentCode }
398+ />
399+ }
400+ />
401+ < div className = "mt-1 flex items-center gap-3" >
402+ < StatusBadge status = { account . status } />
415403 { account . externalReference && (
416- < p className = "mt-1 font-mono text-sm text-muted-foreground" > { account . externalReference } </ p >
404+ < p className = "font-mono text-sm text-muted-foreground" > { account . externalReference } </ p >
417405 ) }
418406 </ div >
419- < AccountActions
420- status = { account . status }
421- accountId = { account . accountId }
422- currency = { account . instrumentCode }
423- />
424407 </ div >
425408
426409 { /* Summary fields */ }
427- < Card className = "mt-6" >
410+ < Card >
428411 < CardContent >
429412 < dl className = "grid grid-cols-2 gap-4 pt-2 md:grid-cols-4" >
430413 < DetailField label = "Instrument" > { account . instrumentCode } </ DetailField >
@@ -444,73 +427,71 @@ export function AccountDetailPage() {
444427 </ Card >
445428
446429 { /* Tabs */ }
447- < div className = "mt-6" >
448- < Tabs defaultValue = "overview" >
449- < TabsList >
450- < TabsTrigger value = "overview" > Overview</ TabsTrigger >
451- < TabsTrigger value = "transactions" > Transactions</ TabsTrigger >
452- < TabsTrigger value = "liens" > Liens</ TabsTrigger >
453- < TabsTrigger value = "audit" > Audit Trail</ TabsTrigger >
454- </ TabsList >
455-
456- < TabsContent value = "overview" className = "mt-4" >
457- < Card >
458- < CardHeader >
459- < CardTitle > Account Details</ CardTitle >
460- </ CardHeader >
461- < CardContent >
462- < dl className = "grid grid-cols-1 gap-4 sm:grid-cols-2" >
463- < DetailField label = "Account ID" > { account . accountId } </ DetailField >
464- < DetailField label = "External Reference" > { account . externalReference || '—' } </ DetailField >
465- < DetailField label = "Status" >
466- < StatusBadge status = { account . status } />
467- </ DetailField >
468- < DetailField label = "Instrument" > { account . instrumentCode } </ DetailField >
469- < DetailField label = "Available Balance" >
470- { account . availableBalance ?? '—' }
430+ < Tabs defaultValue = "overview" >
431+ < TabsList >
432+ < TabsTrigger value = "overview" > Overview</ TabsTrigger >
433+ < TabsTrigger value = "transactions" > Transactions</ TabsTrigger >
434+ < TabsTrigger value = "liens" > Liens</ TabsTrigger >
435+ < TabsTrigger value = "audit" > Audit Trail</ TabsTrigger >
436+ </ TabsList >
437+
438+ < TabsContent value = "overview" className = "mt-4" >
439+ < Card >
440+ < CardHeader >
441+ < CardTitle > Account Details</ CardTitle >
442+ </ CardHeader >
443+ < CardContent >
444+ < dl className = "grid grid-cols-1 gap-4 sm:grid-cols-2" >
445+ < DetailField label = "Account ID" > { account . accountId } </ DetailField >
446+ < DetailField label = "External Reference" > { account . externalReference || '—' } </ DetailField >
447+ < DetailField label = "Status" >
448+ < StatusBadge status = { account . status } />
449+ </ DetailField >
450+ < DetailField label = "Instrument" > { account . instrumentCode } </ DetailField >
451+ < DetailField label = "Available Balance" >
452+ { account . availableBalance ?? '—' }
453+ </ DetailField >
454+ < DetailField label = "Reserved Balance" >
455+ { account . reservedBalance ?? '—' }
456+ </ DetailField >
457+ { account . name && (
458+ < DetailField label = "Name" > { account . name } </ DetailField >
459+ ) }
460+ { account . partyId && (
461+ < DetailField label = "Party ID" >
462+ < EntityLink type = "party" id = { account . partyId } />
471463 </ DetailField >
472- < DetailField label = "Reserved Balance" >
473- { account . reservedBalance ?? '—' }
474- </ DetailField >
475- { account . name && (
476- < DetailField label = "Name" > { account . name } </ DetailField >
477- ) }
478- { account . partyId && (
479- < DetailField label = "Party ID" >
480- < EntityLink type = "party" id = { account . partyId } />
481- </ DetailField >
482- ) }
483- < DetailField label = "Created" >
484- < TimeDisplay timestamp = { account . createdAt } format = "both" />
485- </ DetailField >
486- < DetailField label = "Last Updated" >
487- < TimeDisplay timestamp = { account . updatedAt } format = "both" />
488- </ DetailField >
489- </ dl >
490- </ CardContent >
491- </ Card >
492- </ TabsContent >
493-
494- < TabsContent value = "transactions" className = "mt-4" >
495- < AccountTransactions accountId = { account . accountId } instrumentCode = { account . instrumentCode } />
496- </ TabsContent >
497-
498- < TabsContent value = "liens" className = "mt-4" >
499- < AccountLiens accountId = { account . accountId } instrumentCode = { account . instrumentCode } />
500- </ TabsContent >
501-
502- < TabsContent value = "audit" className = "mt-4" >
503- < Card >
504- < CardHeader >
505- < CardTitle > Audit Trail</ CardTitle >
506- </ CardHeader >
507- < CardContent >
508- < AuditTrail entityType = "CurrentAccount" entityId = { account . accountId } />
509- </ CardContent >
510- </ Card >
511- </ TabsContent >
512- </ Tabs >
513- </ div >
514- </ div >
464+ ) }
465+ < DetailField label = "Created" >
466+ < TimeDisplay timestamp = { account . createdAt } format = "both" />
467+ </ DetailField >
468+ < DetailField label = "Last Updated" >
469+ < TimeDisplay timestamp = { account . updatedAt } format = "both" />
470+ </ DetailField >
471+ </ dl >
472+ </ CardContent >
473+ </ Card >
474+ </ TabsContent >
475+
476+ < TabsContent value = "transactions" className = "mt-4" >
477+ < AccountTransactions accountId = { account . accountId } instrumentCode = { account . instrumentCode } />
478+ </ TabsContent >
479+
480+ < TabsContent value = "liens" className = "mt-4" >
481+ < AccountLiens accountId = { account . accountId } instrumentCode = { account . instrumentCode } />
482+ </ TabsContent >
483+
484+ < TabsContent value = "audit" className = "mt-4" >
485+ < Card >
486+ < CardHeader >
487+ < CardTitle > Audit Trail</ CardTitle >
488+ </ CardHeader >
489+ < CardContent >
490+ < AuditTrail entityType = "CurrentAccount" entityId = { account . accountId } />
491+ </ CardContent >
492+ </ Card >
493+ </ TabsContent >
494+ </ Tabs >
495+ </ PageShell >
515496 )
516497}
0 commit comments