diff --git a/centrifuge-app/src/pages/Loan/ChargeFeesFields.tsx b/centrifuge-app/src/pages/Loan/ChargeFeesFields.tsx index 2781b6733b..60cfc6c9ac 100644 --- a/centrifuge-app/src/pages/Loan/ChargeFeesFields.tsx +++ b/centrifuge-app/src/pages/Loan/ChargeFeesFields.tsx @@ -6,7 +6,7 @@ import { useCentrifugeApi, wrapProxyCallsForAccount, } from '@centrifuge/centrifuge-react' -import { Box, CurrencyInput, IconMinusCircle, IconPlusCircle, Select, Shelf, Stack, Text } from '@centrifuge/fabric' +import { Box, CurrencyInput, IconPlus, IconX, Select, Shelf, Stack, Text } from '@centrifuge/fabric' import { Field, FieldArray, FieldProps, useFormikContext } from 'formik' import React from 'react' import { combineLatest, map, of } from 'rxjs' @@ -101,11 +101,11 @@ export const ChargeFeesFields = ({ background="none" border="none" as="button" - mt={4} + mt="34px" style={{ cursor: 'pointer' }} onClick={() => remove(index)} > - + ) @@ -125,7 +125,7 @@ export const ChargeFeesFields = ({ return push({ id: '', amount: '' }) }} > - + Add fee @@ -148,8 +148,10 @@ function ChargePoolFeeSummary({ poolId }: { poolId: string }) { return form.values.fees.length > 0 ? ( - Fees - {formatBalance(Dec(totalFees), pool.currency.symbol, 2)} + + Fees + + {formatBalance(Dec(totalFees), pool.currency.symbol, 2)} ) : null diff --git a/centrifuge-app/src/pages/Loan/CorrectionForm.tsx b/centrifuge-app/src/pages/Loan/CorrectionForm.tsx index 659e191734..d2718c1f7e 100644 --- a/centrifuge-app/src/pages/Loan/CorrectionForm.tsx +++ b/centrifuge-app/src/pages/Loan/CorrectionForm.tsx @@ -1,10 +1,11 @@ import { ActiveLoan, CurrencyBalance, Pool, Price } from '@centrifuge/centrifuge-js' import { useCentrifugeApi, useCentrifugeTransaction, wrapProxyCallsForAccount } from '@centrifuge/centrifuge-react' -import { Button, CurrencyInput, Shelf, Stack, Text, TextInput } from '@centrifuge/fabric' +import { Box, Button, CurrencyInput, Shelf, Stack, Text, TextInput } from '@centrifuge/fabric' import Decimal from 'decimal.js-light' import { Field, FieldProps, Form, FormikProvider, useFormik } from 'formik' import * as React from 'react' import { combineLatest, switchMap } from 'rxjs' +import { useTheme } from 'styled-components' import { FieldWithErrorMessage } from '../../components/FieldWithErrorMessage' import { Dec } from '../../utils/Decimal' import { formatBalance } from '../../utils/formatting' @@ -25,6 +26,7 @@ export type CorrectionValues = { } export function CorrectionForm({ loan }: { loan: ActiveLoan }) { + const theme = useTheme() const pool = usePool(loan.poolId) as Pool const account = useBorrower(loan.poolId, loan.id) const poolFees = useChargePoolFees(loan.poolId, loan.id) @@ -116,105 +118,111 @@ export function CorrectionForm({ loan }: { loan: ActiveLoan }) { Correction - - {isExternalLoan(loan) ? ( - <> - - - {({ field, form, meta }: FieldProps) => { - return ( - form.setFieldValue('quantity', value)} - errorMessage={meta.touched ? meta.error : undefined} - /> - ) - }} - - - {({ field, form, meta }: FieldProps) => { - return ( - form.setFieldValue('price', value)} - decimals={8} - errorMessage={meta.touched ? meta.error : undefined} - /> - ) - }} - - - - - ={' '} - {formatBalance( - Dec(correctionForm.values.price || 0).mul(correctionForm.values.quantity || 0), - pool.currency.symbol, - 2 - )}{' '} - principal - - - - ) : isInternalLoan(loan) ? ( + + + {isExternalLoan(loan) ? ( + <> + + + {({ field, form, meta }: FieldProps) => { + return ( + form.setFieldValue('quantity', value)} + errorMessage={meta.touched ? meta.error : undefined} + /> + ) + }} + + + {({ field, form, meta }: FieldProps) => { + return ( + form.setFieldValue('price', value)} + decimals={8} + errorMessage={meta.touched ? meta.error : undefined} + /> + ) + }} + + + + + ={' '} + {formatBalance( + Dec(correctionForm.values.price || 0).mul(correctionForm.values.quantity || 0), + pool.currency.symbol, + 2 + )}{' '} + principal + + + + ) : isInternalLoan(loan) ? ( + + {({ field, form, meta }: FieldProps) => { + return ( + form.setFieldValue('principal', value)} + errorMessage={meta.touched ? meta.error : undefined} + /> + ) + }} + + ) : null} - {({ field, form, meta }: FieldProps) => { - return ( - form.setFieldValue('principal', value)} - errorMessage={meta.touched ? meta.error : undefined} - /> - ) - }} - - ) : null} - - - - {poolFees.render()} + validate={required()} + name="reason" + as={TextInput} + label="Reason" + placeholder="" + maxLength={40} + /> + {poolFees.render()} + + - + Summary - + Old holdings - {formatBalance(oldPrincipal, pool.currency.symbol, 2)} + {formatBalance(oldPrincipal, pool.currency.symbol, 2)} - + New holdings - + {formatBalance(newPrincipal, pool.currency.symbol, 2)} ( {isIncrease ? '+' : ''} diff --git a/centrifuge-app/src/pages/Loan/ExternalFinanceForm.tsx b/centrifuge-app/src/pages/Loan/ExternalFinanceForm.tsx index cf409ba4a4..4b3c599f00 100644 --- a/centrifuge-app/src/pages/Loan/ExternalFinanceForm.tsx +++ b/centrifuge-app/src/pages/Loan/ExternalFinanceForm.tsx @@ -8,12 +8,24 @@ import { WithdrawAddress, } from '@centrifuge/centrifuge-js' import { useCentrifugeApi, useCentrifugeTransaction, wrapProxyCallsForAccount } from '@centrifuge/centrifuge-react' -import { Button, CurrencyInput, InlineFeedback, Shelf, Stack, Text, Tooltip } from '@centrifuge/fabric' +import { + Box, + Button, + CurrencyInput, + IconCheckCircle, + IconClock, + InlineFeedback, + Shelf, + Stack, + Text, + Tooltip, +} from '@centrifuge/fabric' import { BN } from 'bn.js' import Decimal from 'decimal.js-light' import { Field, FieldProps, Form, FormikProvider, useFormik } from 'formik' import * as React from 'react' import { combineLatest, switchMap } from 'rxjs' +import styled, { useTheme } from 'styled-components' import { AnchorTextLink } from '../../components/TextLink' import { Dec } from '../../utils/Decimal' import { formatBalance } from '../../utils/formatting' @@ -25,6 +37,7 @@ import { combine, maxPriceVariance, positiveNumber, required } from '../../utils import { useChargePoolFees } from './ChargeFeesFields' import { ErrorMessage } from './ErrorMessage' import { useWithdraw } from './FinanceForm' +import { SourceSelect } from './SourceSelect' export type FinanceValues = { price: number | '' | Decimal @@ -33,10 +46,34 @@ export type FinanceValues = { fees: { id: string; amount: '' | number | Decimal }[] } +const StyledSuccessButton = styled(Button)` + span { + color: ${({ theme }) => theme.colors.textPrimary}; + background-color: ${({ theme }) => theme.colors.statusOkBg}; + border-color: ${({ theme }) => theme.colors.statusOk}; + border-width: 1px; + &:hover { + background-color: ${({ theme }) => theme.colors.statusOkBg}; + border-color: ${({ theme }) => theme.colors.statusOk}; + border-width: 1px; + box-shadow: none; + } + } +` + /** * Finance form for loans with `valuationMethod === oracle` */ -export function ExternalFinanceForm({ loan, source }: { loan: ExternalLoan; source: string }) { +export function ExternalFinanceForm({ + loan, + source, + setSource, +}: { + loan: ExternalLoan + source: string + setSource: (source: string) => void +}) { + const theme = useTheme() const pool = usePool(loan.poolId) as Pool const account = useBorrower(loan.poolId, loan.id) const poolFees = useChargePoolFees(loan.poolId, loan.id) @@ -44,6 +81,7 @@ export function ExternalFinanceForm({ loan, source }: { loan: ExternalLoan; sour const loans = useLoans(loan.poolId) const sourceLoan = loans?.find((l) => l.id === source) as CreatedLoan | ActiveLoan const displayCurrency = source === 'reserve' ? pool.currency.symbol : 'USD' + const [transactionSuccess, setTransactionSuccess] = React.useState(false) const { execute: doFinanceTransaction, isLoading: isFinanceLoading } = useCentrifugeTransaction( 'Purchase asset', (cent) => (args: [poolId: string, loanId: string, quantity: Price, price: CurrencyBalance], options) => { @@ -79,7 +117,7 @@ export function ExternalFinanceForm({ loan, source }: { loan: ExternalLoan; sour }, { onSuccess: () => { - financeForm.resetForm() + setTransactionSuccess(true) }, } ) @@ -125,62 +163,69 @@ export function ExternalFinanceForm({ loan, source }: { loan: ExternalLoan; sour { - - - - {({ field, form }: FieldProps) => { - return ( - form.setFieldValue('quantity', value)} - /> - ) - }} - - { - const financeAmount = Dec(val).mul(financeForm.values.quantity || 1) - return financeAmount.gt(maxAvailable) - ? `Amount exceeds available (${formatBalance(maxAvailable, displayCurrency, 2)})` - : '' - }, - maxPriceVariance(loan.pricing) - )} - > - {({ field, form }: FieldProps) => { - return ( - form.setFieldValue('price', value)} - decimals={8} - /> - ) - }} - - - - - ={' '} - {formatBalance( - Dec(financeForm.values.price || 0).mul(financeForm.values.quantity || 0), - displayCurrency, - 2 - )}{' '} - principal - - - - {source === 'reserve' && withdraw.render()} - - {poolFees.render()} + + + + + + {({ field, form }: FieldProps) => { + return ( + form.setFieldValue('quantity', value)} + /> + ) + }} + + { + const financeAmount = Dec(val).mul(financeForm.values.quantity || 1) + return financeAmount.gt(maxAvailable) + ? `Amount exceeds available (${formatBalance(maxAvailable, displayCurrency, 2)})` + : '' + }, + maxPriceVariance(loan.pricing) + )} + > + {({ field, form }: FieldProps) => { + return ( + form.setFieldValue('price', value)} + decimals={8} + /> + ) + }} + + + + + ={' '} + {formatBalance( + Dec(financeForm.values.price || 0).mul(financeForm.values.quantity || 0), + displayCurrency, + 2 + )}{' '} + principal + + + {source === 'reserve' && withdraw.render()} + {poolFees.render()} + + Principal amount ({formatBalance(totalFinance, displayCurrency, 2)}) is greater than the available balance @@ -202,61 +247,71 @@ export function ExternalFinanceForm({ loan, source }: { loan: ExternalLoan; sour Liquidity tab. - + Transaction summary - - - - Available balance - - + + + - {formatBalance(maxAvailable, displayCurrency, 2)} + + Available balance + - - - - - - Principal amount - - {formatBalance(totalFinance, displayCurrency, 2)} + {formatBalance(maxAvailable, displayCurrency, 2)} - - {poolFees.renderSummary()} - + + + + Principal amount + + {formatBalance(totalFinance, displayCurrency, 2)} + + + {poolFees.renderSummary()} + - {source === 'reserve' ? ( - - - Stablecoins will be transferred to the designated withdrawal addresses on the specified networks. A - delay may occur before the transfer is completed. - - - ) : ( - - - Virtual accounting process. No onchain stablecoin transfers are expected. - - - )} + {source === 'reserve' ? ( + + + Stablecoins will be transferred to the designated withdrawal addresses on the specified networks. + A delay may occur before the transfer is completed. + + + ) : ( + + + Virtual accounting process. No onchain stablecoin transfers are expected. + + + )} + - + {transactionSuccess ? ( + }>Transaction successful + ) : ( + + )} diff --git a/centrifuge-app/src/pages/Loan/ExternalRepayForm.tsx b/centrifuge-app/src/pages/Loan/ExternalRepayForm.tsx index 18e8b025e8..b445e56df0 100644 --- a/centrifuge-app/src/pages/Loan/ExternalRepayForm.tsx +++ b/centrifuge-app/src/pages/Loan/ExternalRepayForm.tsx @@ -5,12 +5,13 @@ import { useCentrifugeUtils, wrapProxyCallsForAccount, } from '@centrifuge/centrifuge-react' -import { Button, CurrencyInput, InlineFeedback, Shelf, Stack, Text } from '@centrifuge/fabric' +import { Box, Button, CurrencyInput, InlineFeedback, Shelf, Stack, Text } from '@centrifuge/fabric' import { BN } from 'bn.js' import Decimal from 'decimal.js-light' import { Field, FieldProps, Form, FormikProvider, useFormik } from 'formik' import * as React from 'react' import { combineLatest, switchMap } from 'rxjs' +import { useTheme } from 'styled-components' import { copyable } from '../../components/Report/utils' import { Tooltips } from '../../components/Tooltips' import { Dec } from '../../utils/Decimal' @@ -22,6 +23,7 @@ import { usePool } from '../../utils/usePools' import { combine, maxNotRequired, nonNegativeNumberNotRequired } from '../../utils/validation' import { useChargePoolFees } from './ChargeFeesFields' import { ErrorMessage } from './ErrorMessage' +import { SourceSelect } from './SourceSelect' type RepayValues = { price: number | '' | Decimal @@ -36,7 +38,16 @@ const UNLIMITED = Dec(1000000000000000) /** * Repay form for loans with `valuationMethod === oracle */ -export function ExternalRepayForm({ loan, destination }: { loan: ExternalLoan; destination: string }) { +export function ExternalRepayForm({ + loan, + destination, + setDestination, +}: { + loan: ExternalLoan + destination: string + setDestination: (destination: string) => void +}) { + const theme = useTheme() const pool = usePool(loan.poolId) const account = useBorrower(loan.poolId, loan.id) const balances = useBalances(account?.actingAddress) @@ -187,94 +198,101 @@ export function ExternalRepayForm({ loan, destination }: { loan: ExternalLoan; d return ( - - + + + + + { + if (Dec(val || 0).gt(maxQuantity.toDecimal())) { + return `Quantity exeeds max (${maxQuantity.toString()})` + } + return '' + })} + name="quantity" + > + {({ field, form }: FieldProps) => { + return ( + form.setFieldValue('quantity', value)} + placeholder="0" + onSetMax={() => + form.setFieldValue('quantity', loan.pricing.outstandingQuantity.toDecimal().toNumber()) + } + /> + ) + }} + + + {({ field, form }: FieldProps) => { + return ( + form.setFieldValue('price', value)} + decimals={8} + currency={displayCurrency} + /> + ) + }} + + + + + = {formatBalance(principal, displayCurrency, 2)} principal + + + {'outstandingInterest' in loan && loan.outstandingInterest.toDecimal().gt(0) && ( + + {({ field, form }: FieldProps) => { + return ( + form.setFieldValue('interest', value)} + onSetMax={() => form.setFieldValue('interest', maxInterest.toNumber())} + /> + ) + }} + + )} { - if (Dec(val || 0).gt(maxQuantity.toDecimal())) { - return `Quantity exeeds max (${maxQuantity.toString()})` - } - return '' - })} - name="quantity" + name="amountAdditional" + validate={combine(nonNegativeNumberNotRequired(), maxNotRequired(maxAvailable.toNumber()))} > {({ field, form }: FieldProps) => { return ( form.setFieldValue('quantity', value)} - placeholder="0" - onSetMax={() => - form.setFieldValue('quantity', loan.pricing.outstandingQuantity.toDecimal().toNumber()) - } - /> - ) - }} - - - {({ field, form }: FieldProps) => { - return ( - form.setFieldValue('price', value)} - decimals={8} currency={displayCurrency} + onChange={(value) => form.setFieldValue('amountAdditional', value)} /> ) }} - - - - = {formatBalance(principal, displayCurrency, 2)} principal - - - - {'outstandingInterest' in loan && loan.outstandingInterest.toDecimal().gt(0) && ( - - {({ field, form }: FieldProps) => { - return ( - form.setFieldValue('interest', value)} - onSetMax={() => form.setFieldValue('interest', maxInterest.toNumber())} - /> - ) - }} - - )} - - {({ field, form }: FieldProps) => { - return ( - } - disabled={isRepayLoading} - currency={displayCurrency} - onChange={(value) => form.setFieldValue('amountAdditional', value)} - /> - ) - }} - - - {poolFees.render()} + {poolFees.render()} + + The balance of the asset originator account ({formatBalance(balance, displayCurrency, 2)}) is insufficient. @@ -292,41 +310,48 @@ export function ExternalRepayForm({ loan, destination }: { loan: ExternalLoan; d outstanding interest ({formatBalance(maxInterest, displayCurrency, 2)}). - - + + Transaction summary - - - - {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)} - - - - + - - Sale amount + + + {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)} - {formatBalance(totalRepay, displayCurrency, 2)} - - {poolFees.renderSummary()} + + + + Sale amount + + {formatBalance(totalRepay, displayCurrency, 2)} + + + + {poolFees.renderSummary()} + - {destination === 'reserve' ? ( - - Stablecoins will be transferred to the onchain reserve. - - ) : ( - - - Virtual accounting process. No onchain stablecoin transfers are expected. - - - )} + + {destination === 'reserve' ? ( + + + Stablecoins will be transferred to the onchain reserve. + + + ) : ( + + + Virtual accounting process. No onchain stablecoin transfers are expected. + + + )} + diff --git a/centrifuge-app/src/pages/Loan/FinanceForm.tsx b/centrifuge-app/src/pages/Loan/FinanceForm.tsx index c11fe7011d..294c595180 100644 --- a/centrifuge-app/src/pages/Loan/FinanceForm.tsx +++ b/centrifuge-app/src/pages/Loan/FinanceForm.tsx @@ -41,6 +41,7 @@ import Decimal from 'decimal.js-light' import { Field, FieldProps, Form, FormikProvider, useField, useFormik, useFormikContext } from 'formik' import * as React from 'react' import { combineLatest, map, of, switchMap } from 'rxjs' +import { useTheme } from 'styled-components' import { AnchorTextLink } from '../../components/TextLink' import { parachainIcons, parachainNames } from '../../config' import { Dec, min } from '../../utils/Decimal' @@ -75,8 +76,7 @@ export function FinanceForm({ loan }: { loan: LoanType }) { return ( Purchase - - + ) } @@ -84,8 +84,7 @@ export function FinanceForm({ loan }: { loan: LoanType }) { return ( {isCashLoan(loan) ? 'Deposit' : 'Finance'} - - + ) } @@ -93,7 +92,16 @@ export function FinanceForm({ loan }: { loan: LoanType }) { /** * Finance form for loans with `valuationMethod: outstandingDebt, discountedCashflow, cash` */ -function InternalFinanceForm({ loan, source }: { loan: LoanType; source: string }) { +function InternalFinanceForm({ + loan, + source, + onChange, +}: { + loan: LoanType + source: string + onChange: (source: string) => void +}) { + const theme = useTheme() const pool = usePool(loan.poolId) as Pool const account = useBorrower(loan.poolId, loan.id) const api = useCentrifugeApi() @@ -189,104 +197,120 @@ function InternalFinanceForm({ loan, source }: { loan: LoanType; source: string <> {!maturityDatePassed && ( - - { - const principalValue = typeof val === 'number' ? Dec(val) : (val as Decimal) - if (maxAvailable !== UNLIMITED && principalValue.gt(maxAvailable)) { - return `Principal exceeds available financing` - } - return '' - })} - > - {({ field, form }: FieldProps) => { - return ( - form.setFieldValue('principal', value)} - onSetMax={ - maxAvailable !== UNLIMITED ? () => form.setFieldValue('principal', maxAvailable) : undefined - } - /> - ) - }} - - {source === 'other' && ( - - {({ field }: FieldProps) => { + + + + { + const principalValue = typeof val === 'number' ? Dec(val) : (val as Decimal) + if (maxAvailable !== UNLIMITED && principalValue.gt(maxAvailable)) { + return `Principal exceeds available financing` + } + return '' + })} + > + {({ field, form }: FieldProps) => { return ( - + ) + }} + + )} + {source === 'reserve' && withdraw.render()} - {poolFees.render()} + {poolFees.render()} - - {isCashLoan(loan) ? 'Deposit amount' : 'Financing amount'} ( - {formatBalance(totalFinance, displayCurrency, 2)}) is greater than the available balance ( - {formatBalance(maxAvailable, displayCurrency, 2)}). - - - - There is an additional{' '} - {formatBalance( - new CurrencyBalance(pool.reserve.total.sub(pool.reserve.available), pool.currency.decimals), - displayCurrency - )}{' '} - available from repayments or deposits. This requires first executing the orders on the{' '} - Liquidity tab. - - - - Transaction summary - + + {isCashLoan(loan) ? 'Deposit amount' : 'Financing amount'} ( + {formatBalance(totalFinance, displayCurrency, 2)}) is greater than the available balance ( + {formatBalance(maxAvailable, displayCurrency, 2)}). + + + + There is an additional{' '} + {formatBalance( + new CurrencyBalance(pool.reserve.total.sub(pool.reserve.available), pool.currency.decimals), + displayCurrency + )}{' '} + available from repayments or deposits. This requires first executing the orders on the{' '} + Liquidity tab. + + + + + + Transaction summary + + - - Available balance - - - - {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)} - + + + Available balance + + + + {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)} - + {isCashLoan(loan) ? 'Deposit amount' : 'Financing amount'} - {formatBalance(totalFinance, displayCurrency, 2)} + {formatBalance(totalFinance, displayCurrency, 2)} @@ -295,42 +319,42 @@ function InternalFinanceForm({ loan, source }: { loan: LoanType; source: string {source === 'reserve' ? ( - + Stablecoins will be transferred to the designated withdrawal addresses on the specified networks. A delay may occur before the transfer is completed. ) : source === 'other' ? ( - + Virtual accounting process. No onchain stablecoin transfers are expected. This action will lead to an increase in the NAV of the pool. ) : ( - + Virtual accounting process. No onchain stablecoin transfers are expected. )} - + + - - - + + )} @@ -372,16 +396,18 @@ function WithdrawSelect({ withdrawAddresses, poolId }: { withdrawAddresses: With ) return ( - helpers.setValue(JSON.parse(event.target.value))} + onBlur={field.onBlur} + errorMessage={(meta.touched || form.submitCount > 0) && meta.error ? meta.error : undefined} + value={field.value ? JSON.stringify(field.value) : ''} + options={options} + disabled={withdrawAddresses.length === 1} + /> + ) } diff --git a/centrifuge-app/src/pages/Loan/RepayForm.tsx b/centrifuge-app/src/pages/Loan/RepayForm.tsx index be07e098c0..03ccbbde16 100644 --- a/centrifuge-app/src/pages/Loan/RepayForm.tsx +++ b/centrifuge-app/src/pages/Loan/RepayForm.tsx @@ -14,11 +14,12 @@ import { useCentrifugeUtils, wrapProxyCallsForAccount, } from '@centrifuge/centrifuge-react' -import { Button, CurrencyInput, InlineFeedback, Select, Shelf, Stack, Text } from '@centrifuge/fabric' +import { Box, Button, CurrencyInput, InlineFeedback, Select, Shelf, Stack, Text } from '@centrifuge/fabric' import Decimal from 'decimal.js-light' import { Field, FieldProps, Form, FormikProvider, useFormik } from 'formik' import * as React from 'react' import { combineLatest, switchMap } from 'rxjs' +import { useTheme } from 'styled-components' import { copyable } from '../../components/Report/utils' import { Tooltips } from '../../components/Tooltips' import { Dec } from '../../utils/Decimal' @@ -56,8 +57,7 @@ export function RepayForm({ loan }: { loan: CreatedLoan | ActiveLoan }) { return ( Sell - - + ) } @@ -65,15 +65,23 @@ export function RepayForm({ loan }: { loan: CreatedLoan | ActiveLoan }) { return ( {isCashLoan(loan) ? 'Withdraw' : 'Repay'} - - + ) } /** * Repay form for loans with `valuationMethod: outstandingDebt, discountedCashflow, cash` */ -function InternalRepayForm({ loan, destination }: { loan: ActiveLoan | CreatedLoan; destination: string }) { +function InternalRepayForm({ + loan, + destination, + setDestination, +}: { + loan: ActiveLoan | CreatedLoan + destination: string + setDestination: (destination: string) => void +}) { + const theme = useTheme() const pool = usePool(loan.poolId) const account = useBorrower(loan.poolId, loan.id) const balances = useBalances(account?.actingAddress) @@ -225,154 +233,184 @@ function InternalRepayForm({ loan, destination }: { loan: ActiveLoan | CreatedLo <> - - {({ field, form }: FieldProps) => { - return ( - form.setFieldValue('principal', value)} - onSetMax={() => { - form.setFieldValue('principal', maxPrincipal.gte(0) ? maxPrincipal : 0) + + + + {({ field, form }: FieldProps) => { + return ( + form.setFieldValue('principal', value)} + onSetMax={() => { + form.setFieldValue('principal', maxPrincipal.gte(0) ? maxPrincipal : 0) + }} + secondaryLabel={`${formatBalance(maxPrincipal, displayCurrency)} outstanding`} + /> + ) + }} + + {'outstandingInterest' in loan && loan.outstandingInterest.toDecimal().gt(0) && !isCashLoan(loan) && ( + + {({ field, form }: FieldProps) => { + return ( + form.setFieldValue('interest', value)} + onSetMax={() => form.setFieldValue('interest', maxInterest.gte(0) ? maxInterest : 0)} + /> + ) }} - secondaryLabel={`${formatBalance(maxPrincipal, displayCurrency)} outstanding`} - /> - ) - }} - - {'outstandingInterest' in loan && loan.outstandingInterest.toDecimal().gt(0) && !isCashLoan(loan) && ( - )} - name="interest" - > - {({ field, form }: FieldProps) => { - return ( - form.setFieldValue('interest', value)} - onSetMax={() => form.setFieldValue('interest', maxInterest.gte(0) ? maxInterest : 0)} - /> - ) - }} - - )} - {!isCashLoan(loan) && ( - + {({ field, form }: FieldProps) => { + return ( + form.setFieldValue('amountAdditional', value)} + /> + ) + }} + )} - > - {({ field, form }: FieldProps) => { - return ( - } - disabled={isRepayLoading} - currency={displayCurrency} - onChange={(value) => form.setFieldValue('amountAdditional', value)} - /> - ) - }} - - )} - {destination === 'other' && ( - - {({ field }: FieldProps) => { - return ( - + ) + }} + + )} + {poolFees.render()} - - {isCashLoan(loan) ? 'Amount' : 'Principal'} ( - {formatBalance(Dec(repayForm.values.principal || 0), displayCurrency, 2)}) is greater than the outstanding{' '} - {isCashLoan(loan) ? 'balance' : 'principal'} ({formatBalance(maxPrincipal, displayCurrency, 2)}). - + + {isCashLoan(loan) ? 'Amount' : 'Principal'} ( + {formatBalance(Dec(repayForm.values.principal || 0), displayCurrency, 2)}) is greater than the + outstanding {isCashLoan(loan) ? 'balance' : 'principal'} ( + {formatBalance(maxPrincipal, displayCurrency, 2)}). + - - Interest ({formatBalance(Dec(repayForm.values.interest || 0), displayCurrency, 2)}) is greater than the - outstanding interest ({formatBalance(maxInterest, displayCurrency, 2)}). - + + Interest ({formatBalance(Dec(repayForm.values.interest || 0), displayCurrency, 2)}) is greater than the + outstanding interest ({formatBalance(maxInterest, displayCurrency, 2)}). + - - The balance of the asset originator account ({formatBalance(balance, displayCurrency, 2)}) is insufficient. - Transfer {formatBalance(totalRepay.sub(balance), displayCurrency, 2)} to{' '} - {copyable(utils.formatAddress(account?.actingAddress || ''))} on Centrifuge. - + + The balance of the asset originator account ({formatBalance(balance, displayCurrency, 2)}) is + insufficient. Transfer {formatBalance(totalRepay.sub(balance), displayCurrency, 2)} to{' '} + {copyable(utils.formatAddress(account?.actingAddress || ''))} on Centrifuge. + + + - + Transaction summary - - - - - {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)} - - - + - - {isCashLoan(loan) ? 'Withdrawal amount' : 'Repayment amount'} + + + {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)} - {formatBalance(totalRepay, displayCurrency, 2)} - - {poolFees.renderSummary()} - + + + + {isCashLoan(loan) ? 'Withdrawal amount' : 'Repayment amount'} + + {formatBalance(totalRepay, displayCurrency, 2)} + + + + {poolFees.renderSummary()} + - {destination === 'reserve' ? ( - - Stablecoins will be transferred to the onchain reserve. - - ) : destination === 'other' ? ( - - - Virtual accounting process. No onchain stablecoin transfers are expected. This action will lead to a - decrease in the NAV of the pool. - - - ) : ( - - - Virtual accounting process. No onchain stablecoin transfers are expected. - - - )} + + {destination === 'reserve' ? ( + + + Stablecoins will be transferred to the onchain reserve. + + + ) : destination === 'other' ? ( + + + Virtual accounting process. No onchain stablecoin transfers are expected. This action will lead to + a decrease in the NAV of the pool. + + + ) : ( + + + Virtual accounting process. No onchain stablecoin transfers are expected. + + + )} + + diff --git a/fabric/src/components/InlineFeedback/index.tsx b/fabric/src/components/InlineFeedback/index.tsx index d7d6f4d0ab..7dcda45a8f 100644 --- a/fabric/src/components/InlineFeedback/index.tsx +++ b/fabric/src/components/InlineFeedback/index.tsx @@ -26,7 +26,7 @@ export function InlineFeedback({ status = 'default', children }: InlineFeedbackP - + {children} diff --git a/fabric/src/components/InputUnit/index.tsx b/fabric/src/components/InputUnit/index.tsx index f5f25902f4..0b6d13bd4f 100644 --- a/fabric/src/components/InputUnit/index.tsx +++ b/fabric/src/components/InputUnit/index.tsx @@ -42,7 +42,7 @@ export function InputUnit({ id, label, secondaryLabel, errorMessage, inputElemen {inputElement} {secondaryLabel && ( - + {secondaryLabel} )} @@ -63,7 +63,7 @@ export function InputLabel({ }) { return (