summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-05-29 01:23:15 -0300
committerSebastian <sebasjm@gmail.com>2022-05-29 01:23:21 -0300
commit029340469ac661bab1450b1ff4dcc6e717780e5b (patch)
tree0e4495cbc332ed5ed2059b8ba12de9be6c2dc98e /packages/taler-wallet-webextension/src
parentced08c502fc36ef90bb34fafcb1e2cbfe82f1280 (diff)
downloadwallet-core-029340469ac661bab1450b1ff4dcc6e717780e5b.tar.gz
wallet-core-029340469ac661bab1450b1ff4dcc6e717780e5b.tar.bz2
wallet-core-029340469ac661bab1450b1ff4dcc6e717780e5b.zip
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/src')
-rw-r--r--packages/taler-wallet-webextension/src/components/Part.tsx29
-rw-r--r--packages/taler-wallet-webextension/src/components/TransactionItem.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/wallet/History.stories.tsx1
-rw-r--r--packages/taler-wallet-webextension/src/wallet/History.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx30
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Transaction.tsx78
-rw-r--r--packages/taler-wallet-webextension/src/wxApi.ts9
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> {