some ui fixing from belen comments
This commit is contained in:
parent
8cde98947b
commit
b1bf3538e6
@ -407,7 +407,7 @@ export class Amounts {
|
|||||||
return `${a.currency}:${s}`;
|
return `${a.currency}:${s}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static stringifyValue(a: AmountJson): string {
|
static stringifyValue(a: AmountJson, minFractional: number = 0): string {
|
||||||
const av = a.value + Math.floor(a.fraction / amountFractionalBase);
|
const av = a.value + Math.floor(a.fraction / amountFractionalBase);
|
||||||
const af = a.fraction % amountFractionalBase;
|
const af = a.fraction % amountFractionalBase;
|
||||||
let s = av.toString();
|
let s = av.toString();
|
||||||
@ -416,7 +416,7 @@ export class Amounts {
|
|||||||
s = s + ".";
|
s = s + ".";
|
||||||
let n = af;
|
let n = af;
|
||||||
for (let i = 0; i < amountFractionalLength; i++) {
|
for (let i = 0; i < amountFractionalLength; i++) {
|
||||||
if (!n) {
|
if (!n && i >= minFractional) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s = s + Math.floor((n / amountFractionalBase) * 10).toString();
|
s = s + Math.floor((n / amountFractionalBase) * 10).toString();
|
||||||
|
@ -22,7 +22,7 @@ export function ErrorMessage({ title, description }: { title?: string|VNode; des
|
|||||||
const [showErrorDetail, setShowErrorDetail] = useState(false);
|
const [showErrorDetail, setShowErrorDetail] = useState(false);
|
||||||
if (!title)
|
if (!title)
|
||||||
return null;
|
return null;
|
||||||
return <ErrorBox>
|
return <ErrorBox style={{paddingTop: 0, paddingBottom: 0}}>
|
||||||
<div>
|
<div>
|
||||||
<p>{title}</p>
|
<p>{title}</p>
|
||||||
{ description && <button onClick={() => { setShowErrorDetail(v => !v); }}>
|
{ description && <button onClick={() => { setShowErrorDetail(v => !v); }}>
|
||||||
|
@ -520,8 +520,7 @@ export const ErrorBox = styled.div`
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
/* margin: 0.5em; */
|
/* margin: 0.5em; */
|
||||||
padding-left: 1em;
|
padding: 1em;
|
||||||
padding-right: 1em;
|
|
||||||
/* width: 100%; */
|
/* width: 100%; */
|
||||||
color: #721c24;
|
color: #721c24;
|
||||||
background: #f8d7da;
|
background: #f8d7da;
|
||||||
@ -539,6 +538,19 @@ export const ErrorBox = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const SuccessBox = styled(ErrorBox)`
|
||||||
|
color: #0f5132;
|
||||||
|
background-color: #d1e7dd;
|
||||||
|
border-color: #badbcc;
|
||||||
|
`
|
||||||
|
|
||||||
|
export const WarningBox = styled(ErrorBox)`
|
||||||
|
color: #664d03;
|
||||||
|
background-color: #fff3cd;
|
||||||
|
border-color: #ffecb5;
|
||||||
|
`
|
||||||
|
|
||||||
export const PopupNavigation = styled.div<{ devMode?: boolean }>`
|
export const PopupNavigation = styled.div<{ devMode?: boolean }>`
|
||||||
background-color:#0042b2;
|
background-color:#0042b2;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
@ -30,7 +30,7 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InsufficientBalance = createExample(TestedComponent, {
|
export const NoBalance = createExample(TestedComponent, {
|
||||||
payStatus: {
|
payStatus: {
|
||||||
status: PreparePayResultType.InsufficientBalance,
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
noncePriv: '',
|
noncePriv: '',
|
||||||
@ -46,6 +46,27 @@ export const InsufficientBalance = createExample(TestedComponent, {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const NoEnoughBalance = createExample(TestedComponent, {
|
||||||
|
payStatus: {
|
||||||
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
|
noncePriv: '',
|
||||||
|
proposalId: "proposal1234",
|
||||||
|
contractTerms: {
|
||||||
|
merchant: {
|
||||||
|
name: 'someone'
|
||||||
|
},
|
||||||
|
summary: 'some beers',
|
||||||
|
amount: 'USD:10',
|
||||||
|
} as Partial<ContractTerms> as any,
|
||||||
|
amountRaw: 'USD:10',
|
||||||
|
},
|
||||||
|
balance: {
|
||||||
|
currency: 'USD',
|
||||||
|
fraction: 40000000,
|
||||||
|
value: 9
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export const PaymentPossible = createExample(TestedComponent, {
|
export const PaymentPossible = createExample(TestedComponent, {
|
||||||
uri: 'taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0',
|
uri: 'taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0',
|
||||||
payStatus: {
|
payStatus: {
|
||||||
@ -66,6 +87,26 @@ export const PaymentPossible = createExample(TestedComponent, {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const PaymentPossibleWithFee = createExample(TestedComponent, {
|
||||||
|
uri: 'taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0',
|
||||||
|
payStatus: {
|
||||||
|
status: PreparePayResultType.PaymentPossible,
|
||||||
|
amountEffective: 'USD:10.20',
|
||||||
|
amountRaw: 'USD:10',
|
||||||
|
noncePriv: '',
|
||||||
|
contractTerms: {
|
||||||
|
nonce: '123213123',
|
||||||
|
merchant: {
|
||||||
|
name: 'someone'
|
||||||
|
},
|
||||||
|
amount: 'USD:10',
|
||||||
|
summary: 'some beers',
|
||||||
|
} as Partial<ContractTerms> as any,
|
||||||
|
contractTermsHash: '123456',
|
||||||
|
proposalId: 'proposal1234'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
|
export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
|
||||||
payStatus: {
|
payStatus: {
|
||||||
status: PreparePayResultType.AlreadyConfirmed,
|
status: PreparePayResultType.AlreadyConfirmed,
|
||||||
@ -102,3 +143,22 @@ export const AlreadyConfirmedWithoutFullfilment = createExample(TestedComponent,
|
|||||||
paid: false,
|
paid: false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const AlreadyPaid = createExample(TestedComponent, {
|
||||||
|
payStatus: {
|
||||||
|
status: PreparePayResultType.AlreadyConfirmed,
|
||||||
|
amountEffective: 'USD:10',
|
||||||
|
amountRaw: 'USD:10',
|
||||||
|
contractTerms: {
|
||||||
|
merchant: {
|
||||||
|
name: 'someone'
|
||||||
|
},
|
||||||
|
fulfillment_message: 'congratulations! you are looking at the fulfillment message! ',
|
||||||
|
summary: 'some beers',
|
||||||
|
amount: 'USD:10',
|
||||||
|
} as Partial<ContractTerms> as any,
|
||||||
|
contractTermsHash: '123456',
|
||||||
|
proposalId: 'proposal1234',
|
||||||
|
paid: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
@ -24,56 +24,45 @@
|
|||||||
*/
|
*/
|
||||||
// import * as i18n from "../i18n";
|
// import * as i18n from "../i18n";
|
||||||
|
|
||||||
import { renderAmount, ProgressButton } from "../renderHtml";
|
import { AmountJson, AmountLike, Amounts, ConfirmPayResult, ConfirmPayResultDone, ConfirmPayResultType, ContractTerms, getJsonI18n, i18n, PreparePayResult, PreparePayResultType } from "@gnu-taler/taler-util";
|
||||||
import * as wxApi from "../wxApi";
|
import { Fragment, JSX, VNode } from "preact";
|
||||||
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { useState, useEffect } from "preact/hooks";
|
|
||||||
|
|
||||||
import { AmountLike, ConfirmPayResultDone, getJsonI18n, i18n } from "@gnu-taler/taler-util";
|
|
||||||
import {
|
|
||||||
PreparePayResult,
|
|
||||||
ConfirmPayResult,
|
|
||||||
AmountJson,
|
|
||||||
PreparePayResultType,
|
|
||||||
Amounts,
|
|
||||||
ContractTerms,
|
|
||||||
ConfirmPayResultType,
|
|
||||||
} from "@gnu-taler/taler-util";
|
|
||||||
import { JSX, VNode, h, Fragment } from "preact";
|
|
||||||
import { ButtonDestructive, ButtonSuccess, ButtonWarning, LinkSuccess, LinkWarning, WalletAction } from "../components/styled";
|
|
||||||
import { LogoHeader } from "../components/LogoHeader";
|
import { LogoHeader } from "../components/LogoHeader";
|
||||||
import { Part } from "../components/Part";
|
import { Part } from "../components/Part";
|
||||||
import { QR } from "../components/QR";
|
import { QR } from "../components/QR";
|
||||||
|
import { ButtonSuccess, LinkSuccess, SuccessBox, WalletAction, WarningBox } from "../components/styled";
|
||||||
|
import { useBalances } from "../hooks/useBalances";
|
||||||
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
talerPayUri?: string
|
talerPayUri?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AlreadyPaid({ payStatus }: { payStatus: PreparePayResult }) {
|
// export function AlreadyPaid({ payStatus }: { payStatus: PreparePayResult }) {
|
||||||
const fulfillmentUrl = payStatus.contractTerms.fulfillment_url;
|
// const fulfillmentUrl = payStatus.contractTerms.fulfillment_url;
|
||||||
let message;
|
// let message;
|
||||||
if (fulfillmentUrl) {
|
// if (fulfillmentUrl) {
|
||||||
message = (
|
// message = (
|
||||||
<span>
|
// <span>
|
||||||
You have already paid for this article. Click{" "}
|
// You have already paid for this article. Click{" "}
|
||||||
<a href={fulfillmentUrl} target="_bank" rel="external">here</a> to view it again.
|
// <a href={fulfillmentUrl} target="_bank" rel="external">here</a> to view it again.
|
||||||
</span>
|
// </span>
|
||||||
);
|
// );
|
||||||
} else {
|
// } else {
|
||||||
message = <span>
|
// message = <span>
|
||||||
You have already paid for this article:{" "}
|
// You have already paid for this article:{" "}
|
||||||
<em>
|
// <em>
|
||||||
{payStatus.contractTerms.fulfillment_message ?? "no message given"}
|
// {payStatus.contractTerms.fulfillment_message ?? "no message given"}
|
||||||
</em>
|
// </em>
|
||||||
</span>;
|
// </span>;
|
||||||
}
|
// }
|
||||||
return <section class="main">
|
// return <section class="main">
|
||||||
<h1>GNU Taler Wallet</h1>
|
// <h1>GNU Taler Wallet</h1>
|
||||||
<article class="fade">
|
// <article class="fade">
|
||||||
{message}
|
// {message}
|
||||||
</article>
|
// </article>
|
||||||
</section>
|
// </section>
|
||||||
}
|
// }
|
||||||
|
|
||||||
const doPayment = async (payStatus: PreparePayResult): Promise<ConfirmPayResultDone> => {
|
const doPayment = async (payStatus: PreparePayResult): Promise<ConfirmPayResultDone> => {
|
||||||
if (payStatus.status !== "payment-possible") {
|
if (payStatus.status !== "payment-possible") {
|
||||||
@ -98,6 +87,12 @@ export function PayPage({ talerPayUri }: Props): JSX.Element {
|
|||||||
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>(undefined);
|
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>(undefined);
|
||||||
const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
|
const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
|
||||||
|
|
||||||
|
const balance = useBalances()
|
||||||
|
const balanceWithoutError = balance?.error ? [] : (balance?.response.balances || [])
|
||||||
|
|
||||||
|
const foundBalance = balanceWithoutError.find(b => payStatus && Amounts.parseOrThrow(b.available).currency === Amounts.parseOrThrow(payStatus?.amountRaw).currency)
|
||||||
|
const foundAmount = foundBalance ? Amounts.parseOrThrow(foundBalance.available) : undefined
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!talerPayUri) return;
|
if (!talerPayUri) return;
|
||||||
const doFetch = async (): Promise<void> => {
|
const doFetch = async (): Promise<void> => {
|
||||||
@ -115,24 +110,24 @@ export function PayPage({ talerPayUri }: Props): JSX.Element {
|
|||||||
return <span>Loading payment information ...</span>;
|
return <span>Loading payment information ...</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payResult && payResult.type === ConfirmPayResultType.Done) {
|
// if (payResult && payResult.type === ConfirmPayResultType.Done) {
|
||||||
if (payResult.contractTerms.fulfillment_message) {
|
// if (payResult.contractTerms.fulfillment_message) {
|
||||||
const obj = {
|
// const obj = {
|
||||||
fulfillment_message: payResult.contractTerms.fulfillment_message,
|
// fulfillment_message: payResult.contractTerms.fulfillment_message,
|
||||||
fulfillment_message_i18n:
|
// fulfillment_message_i18n:
|
||||||
payResult.contractTerms.fulfillment_message_i18n,
|
// payResult.contractTerms.fulfillment_message_i18n,
|
||||||
};
|
// };
|
||||||
const msg = getJsonI18n(obj, "fulfillment_message");
|
// const msg = getJsonI18n(obj, "fulfillment_message");
|
||||||
return (
|
// return (
|
||||||
<div>
|
// <div>
|
||||||
<p>Payment succeeded.</p>
|
// <p>Payment succeeded.</p>
|
||||||
<p>{msg}</p>
|
// <p>{msg}</p>
|
||||||
</div>
|
// </div>
|
||||||
);
|
// );
|
||||||
} else {
|
// } else {
|
||||||
return <span>Redirecting ...</span>;
|
// return <span>Redirecting ...</span>;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const onClick = async () => {
|
const onClick = async () => {
|
||||||
try {
|
try {
|
||||||
@ -147,7 +142,7 @@ export function PayPage({ talerPayUri }: Props): JSX.Element {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return <PaymentRequestView uri={talerPayUri} payStatus={payStatus} onClick={onClick} payErrMsg={payErrMsg} />;
|
return <PaymentRequestView uri={talerPayUri} payStatus={payStatus} onClick={onClick} payErrMsg={payErrMsg} balance={foundAmount} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PaymentRequestViewProps {
|
export interface PaymentRequestViewProps {
|
||||||
@ -155,8 +150,9 @@ export interface PaymentRequestViewProps {
|
|||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
payErrMsg?: string;
|
payErrMsg?: string;
|
||||||
uri: string;
|
uri: string;
|
||||||
|
balance: AmountJson | undefined;
|
||||||
}
|
}
|
||||||
export function PaymentRequestView({ uri, payStatus, onClick, payErrMsg }: PaymentRequestViewProps) {
|
export function PaymentRequestView({ uri, payStatus, onClick, payErrMsg, balance }: PaymentRequestViewProps) {
|
||||||
let totalFees: AmountJson = Amounts.getZero(payStatus.amountRaw);
|
let totalFees: AmountJson = Amounts.getZero(payStatus.amountRaw);
|
||||||
const contractTerms: ContractTerms = payStatus.contractTerms;
|
const contractTerms: ContractTerms = payStatus.contractTerms;
|
||||||
|
|
||||||
@ -183,71 +179,98 @@ export function PaymentRequestView({ uri, payStatus, onClick, payErrMsg }: Payme
|
|||||||
merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>;
|
merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [showQR, setShowQR] = useState<boolean>(false)
|
function Alternative() {
|
||||||
const privateUri = payStatus.status !== PreparePayResultType.AlreadyConfirmed ? `${uri}&n=${payStatus.noncePriv}` : uri
|
const [showQR, setShowQR] = useState<boolean>(false)
|
||||||
return <WalletAction>
|
const privateUri = payStatus.status !== PreparePayResultType.AlreadyConfirmed ? `${uri}&n=${payStatus.noncePriv}` : uri
|
||||||
<LogoHeader />
|
return <section>
|
||||||
<h2>
|
<LinkSuccess upperCased onClick={() => setShowQR(qr => !qr)}>
|
||||||
{i18n.str`Digital cash payment`}
|
{!showQR ? i18n.str`Pay with a mobile phone` : i18n.str`Hide QR`}
|
||||||
</h2>
|
</LinkSuccess>
|
||||||
<section>
|
{showQR && <div>
|
||||||
{payStatus.status === PreparePayResultType.InsufficientBalance ?
|
<QR text={privateUri} />
|
||||||
<Part title="Insufficient balance" text="No enough coins to pay" kind='negative' /> :
|
Scan the QR code or <a href={privateUri}>click here</a>
|
||||||
<Part big title="Total amount with fee" text={amountToString(payStatus.amountEffective)} kind='negative' />
|
</div>}
|
||||||
}
|
|
||||||
<Part big title="Purchase amount" text={amountToString(payStatus.amountRaw)} kind='neutral' />
|
|
||||||
{Amounts.isNonZero(totalFees) && <Part big title="Fee" text={amountToString(totalFees)} kind='negative' />}
|
|
||||||
<Part title="Merchant" text={contractTerms.merchant.name} kind='neutral' />
|
|
||||||
<Part title="Purchase" text={contractTerms.summary} kind='neutral' />
|
|
||||||
{contractTerms.order_id && <Part title="Receipt" text={`#${contractTerms.order_id}`} kind='neutral' />}
|
|
||||||
</section>
|
</section>
|
||||||
{showQR && <section>
|
}
|
||||||
<QR text={privateUri} />
|
|
||||||
Scan the QR code or <a href={privateUri}>click here</a>
|
function ButtonsSection() {
|
||||||
</section>}
|
if (payErrMsg) {
|
||||||
<section>
|
return <section>
|
||||||
{payErrMsg ? (
|
|
||||||
<div>
|
<div>
|
||||||
<p>Payment failed: {payErrMsg}</p>
|
<p>Payment failed: {payErrMsg}</p>
|
||||||
<button class="pure-button button-success" onClick={onClick} >
|
<button class="pure-button button-success" onClick={onClick} >
|
||||||
{i18n.str`Retry`}
|
{i18n.str`Retry`}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
</section>
|
||||||
payStatus.status === PreparePayResultType.PaymentPossible ? <Fragment>
|
}
|
||||||
<LinkSuccess upperCased onClick={() => setShowQR(qr => !qr)}>
|
if (payStatus.status === PreparePayResultType.PaymentPossible) {
|
||||||
{!showQR ? i18n.str`Complete with mobile wallet` : i18n.str`Hide QR`}
|
return <Fragment>
|
||||||
</LinkSuccess>
|
<section>
|
||||||
<ButtonSuccess upperCased>
|
<ButtonSuccess upperCased>
|
||||||
{i18n.str`Confirm payment`}
|
{i18n.str`Pay`} {amountToString(payStatus.amountEffective)}
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</Fragment> : (
|
</section>
|
||||||
payStatus.status === PreparePayResultType.InsufficientBalance ? <Fragment>
|
<Alternative />
|
||||||
<LinkSuccess upperCased onClick={() => setShowQR(qr => !qr)}>
|
</Fragment>
|
||||||
{!showQR ? i18n.str`Pay with other device` : i18n.str`Hide QR`}
|
}
|
||||||
</LinkSuccess>
|
if (payStatus.status === PreparePayResultType.InsufficientBalance) {
|
||||||
<ButtonDestructive upperCased disabled>
|
return <Fragment>
|
||||||
{i18n.str`No enough coins`}
|
<section>
|
||||||
</ButtonDestructive>
|
{balance ? <WarningBox>
|
||||||
</Fragment> :
|
Your balance of {amountToString(balance)} is not enough to pay for this purchase
|
||||||
<Fragment>
|
</WarningBox> : <WarningBox>
|
||||||
{payStatus.contractTerms.fulfillment_message && <div>
|
Your balance is not enough to pay for this purchase.
|
||||||
{payStatus.contractTerms.fulfillment_message}
|
</WarningBox>}
|
||||||
</div>}
|
</section>
|
||||||
<LinkWarning upperCased href={payStatus.contractTerms.fulfillment_url}>
|
<section>
|
||||||
{i18n.str`Already paid`}
|
<ButtonSuccess upperCased>
|
||||||
</LinkWarning>
|
{i18n.str`Withdraw digital cash`}
|
||||||
</Fragment>
|
</ButtonSuccess>
|
||||||
|
</section>
|
||||||
|
<Alternative />
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
if (payStatus.status === PreparePayResultType.AlreadyConfirmed) {
|
||||||
|
return <Fragment>
|
||||||
|
<section>
|
||||||
|
{payStatus.paid && contractTerms.fulfillment_message && <Part title="Merchant message" text={contractTerms.fulfillment_message} kind='neutral' />}
|
||||||
|
</section>
|
||||||
|
{!payStatus.paid && <Alternative />}
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
return <span />
|
||||||
|
}
|
||||||
|
|
||||||
)
|
return <WalletAction>
|
||||||
)}
|
<LogoHeader />
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
{i18n.str`Digital cash payment`}
|
||||||
|
</h2>
|
||||||
|
{payStatus.status === PreparePayResultType.AlreadyConfirmed &&
|
||||||
|
(payStatus.paid ? <SuccessBox> Already paid </SuccessBox> : <WarningBox> Already confirmed </WarningBox>)
|
||||||
|
}
|
||||||
|
<section>
|
||||||
|
{payStatus.status !== PreparePayResultType.InsufficientBalance && Amounts.isNonZero(totalFees) &&
|
||||||
|
<Part big title="Total to pay" text={amountToString(payStatus.amountEffective)} kind='negative' />
|
||||||
|
}
|
||||||
|
<Part big title="Purchase amount" text={amountToString(payStatus.amountRaw)} kind='neutral' />
|
||||||
|
{Amounts.isNonZero(totalFees) && <Fragment>
|
||||||
|
<Part big title="Fee" text={amountToString(totalFees)} kind='negative' />
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
<Part title="Merchant" text={contractTerms.merchant.name} kind='neutral' />
|
||||||
|
<Part title="Purchase" text={contractTerms.summary} kind='neutral' />
|
||||||
|
{contractTerms.order_id && <Part title="Receipt" text={`#${contractTerms.order_id}`} kind='neutral' />}
|
||||||
</section>
|
</section>
|
||||||
|
<ButtonsSection />
|
||||||
|
|
||||||
</WalletAction>
|
</WalletAction>
|
||||||
}
|
}
|
||||||
|
|
||||||
function amountToString(text: AmountLike) {
|
function amountToString(text: AmountLike) {
|
||||||
const aj = Amounts.jsonifyAmount(text)
|
const aj = Amounts.jsonifyAmount(text)
|
||||||
const amount = Amounts.stringifyValue(aj)
|
const amount = Amounts.stringifyValue(aj, 2)
|
||||||
return `${amount} ${aj.currency}`
|
return `${amount} ${aj.currency}`
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@ export type BalancesHook = BalancesHookOk | BalancesHookError | undefined;
|
|||||||
|
|
||||||
export function useBalances(): BalancesHook {
|
export function useBalances(): BalancesHook {
|
||||||
const [balance, setBalance] = useState<BalancesHook>(undefined);
|
const [balance, setBalance] = useState<BalancesHook>(undefined);
|
||||||
console.log('render balance')
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function checkBalance() {
|
async function checkBalance() {
|
||||||
try {
|
try {
|
||||||
|
Loading…
Reference in New Issue
Block a user