1- import React , { useCallback , useMemo } from "react" ;
2- import { useTranslation , Trans } from "~/context/Locale" ;
3- import { TouchableOpacity } from "react-native" ;
1+ import { Box , Button , Flex , Text } from "@ledgerhq/native-ui" ;
42import { Account } from "@ledgerhq/types-live" ;
5- import { BigNumber } from "bignumber.js" ;
6- import { Flex , Text , Button , Box } from "@ledgerhq/native-ui" ;
7- import Clipboard from "@react-native-clipboard/clipboard" ;
8- import { useAccountUnit } from "LLM/hooks/useAccountUnit" ;
9- import { CantonAccount } from "@ledgerhq/live-common/families/canton/types" ;
10- import { isCantonAccount } from "@ledgerhq/coin-canton" ;
11- import { useTimeRemaining } from "@ledgerhq/live-common/families/canton/react" ;
12- import QueuedDrawer from "~/components/QueuedDrawer" ;
3+ import React from "react" ;
4+ import { TouchableOpacity } from "react-native" ;
135import CurrencyUnitValue from "~/components/CurrencyUnitValue" ;
146import FormatDate from "~/components/DateFormat/FormatDate" ;
15- import { type TransferProposalAction } from "./types" ;
16-
17- type PendingProposal = {
18- contract_id : string ;
19- sender : string ;
20- receiver : string ;
21- amount : BigNumber ;
22- memo : string ;
23- expires_at_micros : number ;
24- isExpired : boolean ;
25- } ;
7+ import QueuedDrawer from "~/components/QueuedDrawer" ;
8+ import { Trans , useTranslation } from "~/context/Locale" ;
9+ import { type ProcessedProposal , type TransferProposalAction } from "./types" ;
10+ import {
11+ usePendingTransferProposalsDetailsViewModel ,
12+ type PendingTransferProposalsDetailsViewModel ,
13+ } from "./usePendingTransferProposalsDetailsViewModel" ;
2614
2715type Props = {
2816 account : Account ;
29- parentAccount : Account ;
30- contractId : string ;
17+ proposal : ProcessedProposal | null ;
3118 onOpenModal : ( contractId : string , action : TransferProposalAction ) => void ;
3219 isOpen : boolean ;
3320 onClose ?: ( ) => void ;
3421} ;
3522
36- const PendingTransferProposalsDetails : React . FC < Props > = ( {
37- account,
38- parentAccount,
39- contractId,
40- onOpenModal,
23+ type ViewProps = PendingTransferProposalsDetailsViewModel & {
24+ proposal : ProcessedProposal | null ;
25+ isOpen : boolean ;
26+ onClose ?: ( ) => void ;
27+ } ;
28+
29+ export function View ( {
30+ unit,
31+ timeRemaining,
32+ handleAction,
33+ handleCopy,
34+ proposal,
4135 isOpen,
4236 onClose,
43- } ) => {
37+ } : ViewProps ) {
4438 const { t } = useTranslation ( ) ;
45- const unit = useAccountUnit ( account ) ;
46-
47- const cantonAccount : CantonAccount | null = isCantonAccount ( account ) ? account : null ;
48- const proposal = useMemo < PendingProposal | null > ( ( ) => {
49- const pendingTransferProposals = cantonAccount ?. cantonResources ?. pendingTransferProposals || [ ] ;
50- const found = pendingTransferProposals . find ( p => p . contract_id === contractId ) ;
51- if ( ! found ) return null ;
52-
53- const now = Date . now ( ) ;
54- const isExpired = now > found . expires_at_micros / 1000 ;
55- return {
56- ...found ,
57- isExpired,
58- amount : new BigNumber ( found . amount ) ,
59- } ;
60- } , [ cantonAccount , contractId ] ) ;
61-
62- const handleAcceptOffer = useCallback (
63- ( contractId : string ) => {
64- onOpenModal ( contractId , "accept" ) ;
65- } ,
66- [ onOpenModal ] ,
67- ) ;
68-
69- const handleRejectOffer = useCallback (
70- ( contractId : string ) => {
71- onOpenModal ( contractId , "reject" ) ;
72- } ,
73- [ onOpenModal ] ,
74- ) ;
75-
76- const handleWithdrawOffer = useCallback (
77- ( contractId : string ) => {
78- onOpenModal ( contractId , "withdraw" ) ;
79- } ,
80- [ onOpenModal ] ,
81- ) ;
82-
83- const handleCopy = useCallback ( ( text : string ) => {
84- Clipboard . setString ( text ) ;
85- } , [ ] ) ;
86-
87- const timeRemaining = useTimeRemaining ( proposal ?. expires_at_micros , proposal ?. isExpired ) ;
8839
8940 if ( ! proposal ) {
9041 return (
@@ -96,7 +47,7 @@ const PendingTransferProposalsDetails: React.FC<Props> = ({
9647 ) ;
9748 }
9849
99- const isIncoming = proposal . sender !== parentAccount . xpub ;
50+ const { isIncoming, isExpired } = proposal ;
10051
10152 return (
10253 < QueuedDrawer
@@ -165,11 +116,11 @@ const PendingTransferProposalsDetails: React.FC<Props> = ({
165116 { t ( "canton.pendingTransactions.expiresAt" ) }
166117 </ Text >
167118 < Text variant = "body" color = "neutral.c100" >
168- < FormatDate date = { new Date ( proposal . expires_at_micros / 1000 ) } />
119+ < FormatDate date = { proposal . expiresAt } />
169120 </ Text >
170121 </ Flex >
171122
172- { ! proposal . isExpired && timeRemaining && (
123+ { ! isExpired && timeRemaining && (
173124 < Flex mb = { 8 } >
174125 < Text variant = "paragraph" color = "neutral.c70" mb = { 2 } >
175126 { t ( "canton.pendingTransactions.expiresIn" ) }
@@ -180,7 +131,7 @@ const PendingTransferProposalsDetails: React.FC<Props> = ({
180131 </ Flex >
181132 ) }
182133
183- { proposal . isExpired && (
134+ { isExpired && (
184135 < Flex mb = { 8 } >
185136 < Text variant = "paragraph" color = "neutral.c70" mb = { 2 } >
186137 { t ( "canton.pendingTransactions.status.label" ) }
@@ -195,20 +146,20 @@ const PendingTransferProposalsDetails: React.FC<Props> = ({
195146 < Text variant = "paragraph" color = "neutral.c70" mb = { 2 } >
196147 { t ( "canton.pendingTransactions.deviceAppModal.contractId" ) }
197148 </ Text >
198- < TouchableOpacity onPress = { ( ) => handleCopy ( proposal . contract_id ) } >
149+ < TouchableOpacity onPress = { ( ) => handleCopy ( proposal . contractId ) } >
199150 < Text variant = "body" color = "neutral.c100" numberOfLines = { 1 } ellipsizeMode = "middle" >
200- { proposal . contract_id }
151+ { proposal . contractId }
201152 </ Text >
202153 </ TouchableOpacity >
203154 </ Flex >
204155
205156 < Flex flexDirection = "row" mt = { 4 } justifyContent = "center" columnGap = { 8 } >
206157 { isIncoming ? (
207158 < >
208- { ! proposal . isExpired && (
159+ { ! isExpired && (
209160 < Button
210161 type = "shade"
211- onPress = { ( ) => handleAcceptOffer ( proposal . contract_id ) }
162+ onPress = { ( ) => handleAction ( "accept" ) }
212163 iconName = "CheckAlone"
213164 flex = { 1 }
214165 >
@@ -218,7 +169,7 @@ const PendingTransferProposalsDetails: React.FC<Props> = ({
218169 < Button
219170 outline
220171 type = "main"
221- onPress = { ( ) => handleRejectOffer ( proposal . contract_id ) }
172+ onPress = { ( ) => handleAction ( "reject" ) }
222173 iconName = "Close"
223174 flex = { 1 }
224175 >
@@ -230,7 +181,7 @@ const PendingTransferProposalsDetails: React.FC<Props> = ({
230181 outline
231182 type = "main"
232183 iconName = "Close"
233- onPress = { ( ) => handleWithdrawOffer ( proposal . contract_id ) }
184+ onPress = { ( ) => handleAction ( "withdraw" ) }
234185 flex = { 1 }
235186 >
236187 < Trans i18nKey = "canton.pendingTransactions.withdraw" />
@@ -240,6 +191,17 @@ const PendingTransferProposalsDetails: React.FC<Props> = ({
240191 </ Flex >
241192 </ QueuedDrawer >
242193 ) ;
194+ }
195+
196+ const PendingTransferProposalsDetails : React . FC < Props > = ( {
197+ account,
198+ proposal,
199+ onOpenModal,
200+ isOpen,
201+ onClose,
202+ } ) => {
203+ const viewModel = usePendingTransferProposalsDetailsViewModel ( { account, proposal, onOpenModal } ) ;
204+ return < View { ...viewModel } proposal = { proposal } isOpen = { isOpen } onClose = { onClose } /> ;
243205} ;
244206
245207export default PendingTransferProposalsDetails ;
0 commit comments