diff options
author | Sebastian <sebasjm@gmail.com> | 2022-05-29 01:23:15 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2022-05-29 01:23:21 -0300 |
commit | 029340469ac661bab1450b1ff4dcc6e717780e5b (patch) | |
tree | 0e4495cbc332ed5ed2059b8ba12de9be6c2dc98e /packages/taler-wallet-webextension | |
parent | ced08c502fc36ef90bb34fafcb1e2cbfe82f1280 (diff) |
show refund info in purchase
notify refund pending with accept button on the purchase details
better payto box
Diffstat (limited to 'packages/taler-wallet-webextension')
8 files changed, 134 insertions, 19 deletions
diff --git a/packages/taler-wallet-webextension/src/components/Part.tsx b/packages/taler-wallet-webextension/src/components/Part.tsx index 58165a349..06e2985cf 100644 --- a/packages/taler-wallet-webextension/src/components/Part.tsx +++ b/packages/taler-wallet-webextension/src/components/Part.tsx @@ -92,6 +92,7 @@ const CollasibleBox = styled.div` } `; import arrowDown from "../svg/chevron-down.svg"; +import { useTranslationContext } from "../context/translation.js"; export function PartCollapsible({ text, title, big, showSign }: Props): VNode { const Text = big ? ExtraLargeText : LargeText; @@ -137,27 +138,37 @@ interface PropsPayto { } export function PartPayto({ payto, kind, big }: PropsPayto): VNode { const Text = big ? ExtraLargeText : LargeText; - let text: string | undefined = undefined; + let text: VNode | undefined = undefined; let title = ""; + const { i18n } = useTranslationContext(); if (payto.isKnown) { if (payto.targetType === "x-taler-bank") { - text = payto.account; - title = "Bank account"; + text = <Fragment>{payto.account}</Fragment>; + title = i18n.str`Bank account`; } else if (payto.targetType === "bitcoin") { - text = payto.targetPath; - title = "Bitcoin addr"; + text = + payto.segwitAddrs && payto.segwitAddrs.length > 0 ? ( + <ul> + <li>{payto.targetPath}</li> + <li>{payto.segwitAddrs[0]}</li> + <li>{payto.segwitAddrs[1]}</li> + </ul> + ) : ( + <Fragment>{payto.targetPath}</Fragment> + ); + title = i18n.str`Bitcoin address`; } else if (payto.targetType === "iban") { - text = payto.targetPath; - title = "IBAN"; + text = <Fragment>{payto.targetPath}</Fragment>; + title = i18n.str`IBAN`; } } if (!text) { - text = stringifyPaytoUri(payto); + text = <Fragment>{stringifyPaytoUri(payto)}</Fragment>; title = "Payto URI"; } return ( <div style={{ margin: "1em" }}> - <SmallLightText style={{ margin: ".5em" }}>{title}</SmallLightText> + <SmallBoldText>{title}</SmallBoldText> <Text style={{ color: diff --git a/packages/taler-wallet-webextension/src/components/TransactionItem.tsx b/packages/taler-wallet-webextension/src/components/TransactionItem.tsx index 985ddf552..bfffa3267 100644 --- a/packages/taler-wallet-webextension/src/components/TransactionItem.tsx +++ b/packages/taler-wallet-webextension/src/components/TransactionItem.tsx @@ -207,7 +207,7 @@ function TransactionAmount(props: TransactionAmountProps): VNode { > <ExtraLargeText> {sign} - {Amounts.stringifyValue(props.amount)} + {Amounts.stringifyValue(props.amount, 2)} </ExtraLargeText> {props.pending && ( <div> diff --git a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx index 3080a866e..004327c94 100644 --- a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx @@ -78,6 +78,7 @@ const exampleData = { summary: "the summary", fulfillmentMessage: "", }, + refunds: [], refundPending: undefined, totalRefundEffective: "USD:0", totalRefundRaw: "USD:0", diff --git a/packages/taler-wallet-webextension/src/wallet/History.tsx b/packages/taler-wallet-webextension/src/wallet/History.tsx index 4a435d0cf..59f245522 100644 --- a/packages/taler-wallet-webextension/src/wallet/History.tsx +++ b/packages/taler-wallet-webextension/src/wallet/History.tsx @@ -193,7 +193,7 @@ export function HistoryView({ margin: 8, }} > - {Amounts.stringifyValue(currencyAmount)} + {Amounts.stringifyValue(currencyAmount, 2)} </CenteredBoldText> )} </div> diff --git a/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx index 587e24e98..895c301c2 100644 --- a/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx @@ -45,7 +45,7 @@ export const TalerBank = createExample(TestedComponent, { export const IBAN = createExample(TestedComponent, { reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG", paytoURI: parsePaytoUri( - "payto://iban/ASDQWEASDZXCASDQWE?amount=COL%3A1&message=Taler+Withdrawal+A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG", + "payto://iban/ES8877998399652238?amount=COL%3A1&message=Taler+Withdrawal+A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG", ), amount: { currency: "USD", diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx index 493cdd1d7..83848d005 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx @@ -93,6 +93,7 @@ const exampleData = { // address_lines: [""], // }, }, + refunds: [], refundPending: undefined, totalRefundEffective: "KUDOS:0", totalRefundRaw: "KUDOS:0", @@ -199,7 +200,7 @@ export const WithdrawPendingManual = createExample(TestedComponent, () => ({ ...exampleData.withdraw, withdrawalDetails: { type: WithdrawalType.ManualTransfer, - exchangePaytoUris: ["payto://iban/asdasdasd"], + exchangePaytoUris: ["payto://iban/ES8877998399652238"], reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG", } as WithdrawalDetails, pending: true, @@ -254,6 +255,14 @@ export const PaymentWithRefund = createExample(TestedComponent, { amountRaw: "KUDOS:12", totalRefundEffective: "KUDOS:1", totalRefundRaw: "KUDOS:1", + refunds: [ + { + transactionId: "1123123", + amountRaw: "KUDOS:1", + amountEffective: "KUDOS:1", + timestamp: TalerProtocolTimestamp.fromSeconds(1546546544), + }, + ], }, }); @@ -410,6 +419,25 @@ export const PaymentWithLongSummary = createExample(TestedComponent, { export const Deposit = createExample(TestedComponent, { transaction: exampleData.deposit, }); +export const DepositTalerBank = createExample(TestedComponent, { + transaction: { + ...exampleData.deposit, + targetPaytoUri: "payto://x-taler-bank/bank.demo.taler.net/Exchange", + }, +}); +export const DepositBitcoin = createExample(TestedComponent, { + transaction: { + ...exampleData.deposit, + targetPaytoUri: + "payto://bitcoin/bcrt1q6ps8qs6v8tkqrnru4xqqqa6rfwcx5ufpdfqht4?amount=BTC:0.1&subject=0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00", + }, +}); +export const DepositIBAN = createExample(TestedComponent, { + transaction: { + ...exampleData.deposit, + targetPaytoUri: "payto://iban/ES8877998399652238", + }, +}); export const DepositError = createExample(TestedComponent, { transaction: { diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx index 9ccb353a9..8165953ab 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx @@ -22,6 +22,8 @@ import { NotificationType, parsePaytoUri, parsePayUri, + PaytoUri, + stringifyPaytoUri, TalerProtocolTimestamp, Transaction, TransactionDeposit, @@ -50,6 +52,7 @@ import { ButtonDestructive, ButtonPrimary, CenteredDialog, + HistoryRow, InfoBox, ListOfProducts, Overlay, @@ -83,7 +86,7 @@ async function getTransaction(tid: string): Promise<Transaction> { export function TransactionPage({ tid, goToWalletHistory }: Props): VNode { const { i18n } = useTranslationContext(); - const state = useAsyncAsHook(() => getTransaction(tid)); + const state = useAsyncAsHook(() => getTransaction(tid), [tid]); useEffect(() => { wxApi.onUpdateNotification([NotificationType.WithdrawGroupFinished], () => { @@ -119,6 +122,7 @@ export function TransactionPage({ tid, goToWalletHistory }: Props): VNode { onRetry={() => wxApi.retryTransaction(tid).then(() => goToWalletHistory(currency)) } + onRefund={(id) => wxApi.applyRefundFromPurchaseId(id)} onBack={() => goToWalletHistory(currency)} /> ); @@ -128,6 +132,7 @@ export interface WalletTransactionProps { transaction: Transaction; onDelete: () => void; onRetry: () => void; + onRefund: (id: string) => void; onBack: () => void; } @@ -143,7 +148,7 @@ export function TransactionView({ transaction, onDelete, onRetry, - onBack, + onRefund, }: WalletTransactionProps): VNode { const [confirmBeforeForget, setConfirmBeforeForget] = useState(false); @@ -334,6 +339,40 @@ export function TransactionView({ )} </Header> <br /> + {transaction.refunds.length > 0 ? ( + <Part + title={<i18n.Translate>Refunds</i18n.Translate>} + text={ + <table> + {transaction.refunds.map((r, i) => { + return ( + <tr key={i}> + <td> + {<Amount value={r.amountEffective} />}{" "} + <a + href={Pages.balance_transaction.replace( + ":tid", + r.transactionId, + )} + > + was refunded + </a>{" "} + on{" "} + { + <Time + timestamp={AbsoluteTime.fromTimestamp(r.timestamp)} + format="dd MMMM yyyy" + /> + } + </td> + </tr> + ); + })} + </table> + } + kind="neutral" + /> + ) : undefined} {pendingRefund !== undefined && Amounts.isNonZero(pendingRefund) && ( <InfoBox> <i18n.Translate> @@ -348,7 +387,7 @@ export function TransactionView({ <div> <div /> <div> - <ButtonPrimary> + <ButtonPrimary onClick={() => onRefund(transaction.proposalId)}> <i18n.Translate>Accept</i18n.Translate> </ButtonPrimary> </div> @@ -385,9 +424,9 @@ export function TransactionView({ total={total} kind="negative" > - {transaction.targetPaytoUri} + {!payto ? transaction.targetPaytoUri : <NicePayto payto={payto} />} </Header> - {payto && <PartPayto big payto={payto} kind="neutral" />} + {payto && <PartPayto payto={payto} kind="neutral" />} <Part title={<i18n.Translate>Details</i18n.Translate>} text={<DepositDetails transaction={transaction} />} @@ -669,7 +708,7 @@ function PurchaseDetails({ <tr> <td>Refunded</td> <td> - <Amount value={transaction.totalRefundEffective} /> + <Amount value={transaction.totalRefundRaw} /> </td> </tr> )} @@ -988,3 +1027,30 @@ function Header({ </div> ); } + +function NicePayto({ payto }: { payto: PaytoUri }): VNode { + if (payto.isKnown) { + switch (payto.targetType) { + case "bitcoin": { + return <div>{payto.targetPath.substring(0, 20)}...</div>; + } + case "x-taler-bank": { + const url = new URL("/", `https://${payto.host}`); + return ( + <Fragment> + <div>{payto.account}</div> + <SmallLightText> + <a href={url.href} target="_bank" rel="noreferrer"> + {url.toString()} + </a> + </SmallLightText> + </Fragment> + ); + } + case "iban": { + return <div>{payto.targetPath.substring(0, 20)}</div>; + } + } + } + return <Fragment>{stringifyPaytoUri(payto)}</Fragment>; +} diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts index dd4eb2cf4..63840017b 100644 --- a/packages/taler-wallet-webextension/src/wxApi.ts +++ b/packages/taler-wallet-webextension/src/wxApi.ts @@ -312,6 +312,15 @@ export function applyRefund( } /** + * Do refund for purchase. + */ +export function applyRefundFromPurchaseId( + purchaseId: string, +): Promise<ApplyRefundResponse> { + return callBackend("applyRefundFromPurchaseId", { purchaseId }); +} + +/** * Get details about a pay operation. */ export function preparePay(talerPayUri: string): Promise<PreparePayResult> { |