using extendedStatus
This commit is contained in:
parent
bc67ff0c7f
commit
0b2bf13def
@ -16,6 +16,7 @@
|
||||
import {
|
||||
AbsoluteTime,
|
||||
Amounts,
|
||||
ExtendedStatus,
|
||||
NotificationType,
|
||||
Transaction,
|
||||
} from "@gnu-taler/taler-util";
|
||||
@ -56,7 +57,9 @@ export function PendingTransactions({ goToTransaction }: Props): VNode {
|
||||
const transactions =
|
||||
!state || state.hasError
|
||||
? cache.tx
|
||||
: state.response.transactions.filter((t) => t.pending);
|
||||
: state.response.transactions.filter(
|
||||
(t) => t.extendedStatus === ExtendedStatus.Pending,
|
||||
);
|
||||
|
||||
if (state && !state.hasError) {
|
||||
cache.tx = transactions;
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
Transaction,
|
||||
TransactionType,
|
||||
WithdrawalType,
|
||||
ExtendedStatus,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { h, VNode } from "preact";
|
||||
import { useTranslationContext } from "../context/translation.js";
|
||||
@ -52,7 +53,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
|
||||
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)}
|
||||
iconPath={"W"}
|
||||
pending={
|
||||
tx.pending
|
||||
tx.extendedStatus === ExtendedStatus.Pending
|
||||
? tx.withdrawalDetails.type ===
|
||||
WithdrawalType.TalerBankIntegrationApi
|
||||
? !tx.withdrawalDetails.confirmed
|
||||
|
@ -48,7 +48,14 @@ type Type = {
|
||||
alerts: Alert[];
|
||||
pushAlert: (n: Alert) => void;
|
||||
removeAlert: (n: Alert) => void;
|
||||
/**
|
||||
*
|
||||
* @param h
|
||||
* @returns
|
||||
* @deprecated use safely
|
||||
*/
|
||||
pushAlertOnError: <T>(h: (p: T) => Promise<void>) => SafeHandler<T>;
|
||||
safely: <T>(h: (p: T) => Promise<void>, error: TranslatedString) => SafeHandler<T>;
|
||||
};
|
||||
|
||||
const initial: Type = {
|
||||
@ -56,6 +63,9 @@ const initial: Type = {
|
||||
pushAlertOnError: () => {
|
||||
throw Error("alert context not initialized");
|
||||
},
|
||||
safely: () => {
|
||||
throw Error("alert context not initialized");
|
||||
},
|
||||
pushAlert: () => {
|
||||
null;
|
||||
},
|
||||
@ -100,8 +110,18 @@ export const AlertProvider = ({ children }: Props): VNode => {
|
||||
});
|
||||
}
|
||||
|
||||
function safely<T>(
|
||||
handler: (p: T) => Promise<void>,
|
||||
message: TranslatedString
|
||||
): SafeHandler<T> {
|
||||
return withSafe(handler, (e) => {
|
||||
const a = alertFromError(message, e);
|
||||
pushAlert(a);
|
||||
});
|
||||
}
|
||||
|
||||
return h(Context.Provider, {
|
||||
value: { alerts, pushAlert, removeAlert, pushAlertOnError },
|
||||
value: { alerts, pushAlert, removeAlert, pushAlertOnError, safely },
|
||||
children,
|
||||
});
|
||||
};
|
||||
|
@ -20,6 +20,7 @@ import { theme, Colors, rippleEnabled, rippleEnabledOutlined } from "./style";
|
||||
// eslint-disable-next-line import/extensions
|
||||
import { alpha } from "./colors/manipulation";
|
||||
import { useState } from "preact/hooks";
|
||||
import { SafeHandler } from "./handlers.js";
|
||||
|
||||
export const buttonBaseStyle = css`
|
||||
display: inline-flex;
|
||||
@ -55,6 +56,7 @@ interface Props {
|
||||
tooltip?: string;
|
||||
color?: Colors;
|
||||
onClick?: () => Promise<void>;
|
||||
// onClick?: SafeHandler<void>;
|
||||
}
|
||||
|
||||
const button = css`
|
||||
|
@ -35,6 +35,7 @@ import * as popup from "./popup/index.stories.js";
|
||||
import * as wallet from "./wallet/index.stories.js";
|
||||
|
||||
import { renderStories } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import { AlertProvider } from "./context/alert.js";
|
||||
|
||||
function main(): void {
|
||||
renderStories(
|
||||
@ -56,28 +57,28 @@ function getWrapperForGroup(group: string): FunctionComponent {
|
||||
case "popup":
|
||||
return function PopupWrapper({ children }: any) {
|
||||
return (
|
||||
<Fragment>
|
||||
<AlertProvider>
|
||||
<PopupNavBar />
|
||||
<PopupBox>{children}</PopupBox>
|
||||
</Fragment>
|
||||
</AlertProvider>
|
||||
);
|
||||
};
|
||||
case "wallet":
|
||||
return function WalletWrapper({ children }: any) {
|
||||
return (
|
||||
<Fragment>
|
||||
<AlertProvider>
|
||||
<LogoHeader />
|
||||
<WalletNavBar />
|
||||
<WalletBox>{children}</WalletBox>
|
||||
</Fragment>
|
||||
</AlertProvider>
|
||||
);
|
||||
};
|
||||
case "cta":
|
||||
return function WalletWrapper({ children }: any) {
|
||||
return (
|
||||
<Fragment>
|
||||
<AlertProvider>
|
||||
<WalletAction>{children}</WalletAction>
|
||||
</Fragment>
|
||||
</AlertProvider>
|
||||
);
|
||||
};
|
||||
default:
|
||||
|
@ -556,9 +556,11 @@ function WalletTemplate({
|
||||
{goToTransaction ? (
|
||||
<PendingTransactions goToTransaction={goToTransaction} />
|
||||
) : undefined}
|
||||
<CurrentAlerts />
|
||||
<WalletBox>
|
||||
<AlertProvider>{children}</AlertProvider>
|
||||
<AlertProvider>
|
||||
<CurrentAlerts />
|
||||
{children}
|
||||
</AlertProvider>
|
||||
</WalletBox>
|
||||
</Fragment>
|
||||
);
|
||||
|
@ -39,14 +39,13 @@ import {
|
||||
WithdrawalDetails,
|
||||
WithdrawalType,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { DevContextProviderForTesting } from "../context/devContext.js";
|
||||
// import {
|
||||
// createExample,
|
||||
// createExampleWithCustomContext as createExampleInCustomContext,
|
||||
// } from "../test-utils.js";
|
||||
import { TransactionView as TestedComponent } from "./Transaction.js";
|
||||
import { tests } from "@gnu-taler/web-util/lib/index.browser";
|
||||
import beer from "../../static-dev/beer.png";
|
||||
import { TransactionView as TestedComponent } from "./Transaction.js";
|
||||
|
||||
export default {
|
||||
title: "transaction details",
|
||||
@ -54,6 +53,7 @@ export default {
|
||||
argTypes: {
|
||||
onRetry: { action: "onRetry" },
|
||||
onDelete: { action: "onDelete" },
|
||||
onCancel: { action: "onCancel" },
|
||||
onBack: { action: "onBack" },
|
||||
},
|
||||
};
|
||||
@ -62,10 +62,10 @@ const commonTransaction = {
|
||||
amountRaw: "KUDOS:11",
|
||||
amountEffective: "KUDOS:9.2",
|
||||
extendedStatus: ExtendedStatus.Done,
|
||||
pending: false,
|
||||
pending: undefined as any as boolean, //deprecated
|
||||
timestamp: TalerProtocolTimestamp.now(),
|
||||
transactionId: "txn:deposit:12",
|
||||
frozen: false,
|
||||
frozen: undefined as any as boolean, //deprecated
|
||||
type: TransactionType.Deposit,
|
||||
} as TransactionCommon;
|
||||
|
||||
@ -255,7 +255,7 @@ export const WithdrawFiveMinutesAgoAndPending = tests.createExample(
|
||||
timestamp: TalerProtocolTimestamp.fromSeconds(
|
||||
new Date().getTime() / 1000 - 60 * 5,
|
||||
),
|
||||
pending: true,
|
||||
extendedStatus: ExtendedStatus.Pending,
|
||||
},
|
||||
}),
|
||||
);
|
||||
@ -295,7 +295,7 @@ export const WithdrawPendingManual = tests.createExample(
|
||||
exchangePaytoUris: ["payto://iban/ES8877998399652238"],
|
||||
reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
|
||||
} as WithdrawalDetails,
|
||||
pending: true,
|
||||
extendedStatus: ExtendedStatus.Pending,
|
||||
},
|
||||
}),
|
||||
);
|
||||
@ -311,7 +311,7 @@ export const WithdrawPendingTalerBankUnconfirmed = tests.createExample(
|
||||
reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
|
||||
bankConfirmationUrl: "http://bank.demo.taler.net",
|
||||
},
|
||||
pending: true,
|
||||
extendedStatus: ExtendedStatus.Pending,
|
||||
},
|
||||
},
|
||||
);
|
||||
@ -326,7 +326,7 @@ export const WithdrawPendingTalerBankConfirmed = tests.createExample(
|
||||
confirmed: true,
|
||||
reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
|
||||
},
|
||||
pending: true,
|
||||
extendedStatus: ExtendedStatus.Pending,
|
||||
},
|
||||
},
|
||||
);
|
||||
@ -443,7 +443,10 @@ export const PaymentWithoutFee = tests.createExample(TestedComponent, {
|
||||
});
|
||||
|
||||
export const PaymentPending = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.payment, pending: true },
|
||||
transaction: {
|
||||
...exampleData.payment,
|
||||
extendedStatus: ExtendedStatus.Pending,
|
||||
},
|
||||
});
|
||||
|
||||
export const PaymentWithProducts = tests.createExample(TestedComponent, {
|
||||
@ -540,7 +543,10 @@ export const DepositError = tests.createExample(TestedComponent, {
|
||||
});
|
||||
|
||||
export const DepositPending = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.deposit, pending: true },
|
||||
transaction: {
|
||||
...exampleData.deposit,
|
||||
extendedStatus: ExtendedStatus.Pending,
|
||||
},
|
||||
});
|
||||
|
||||
export const Refresh = tests.createExample(TestedComponent, {
|
||||
@ -566,7 +572,7 @@ export const TipError = tests.createExample(TestedComponent, {
|
||||
});
|
||||
|
||||
export const TipPending = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.tip, pending: true },
|
||||
transaction: { ...exampleData.tip, extendedStatus: ExtendedStatus.Pending },
|
||||
});
|
||||
|
||||
export const Refund = tests.createExample(TestedComponent, {
|
||||
@ -581,7 +587,10 @@ export const RefundError = tests.createExample(TestedComponent, {
|
||||
});
|
||||
|
||||
export const RefundPending = tests.createExample(TestedComponent, {
|
||||
transaction: { ...exampleData.refund, pending: true },
|
||||
transaction: {
|
||||
...exampleData.refund,
|
||||
extendedStatus: ExtendedStatus.Pending,
|
||||
},
|
||||
});
|
||||
|
||||
export const InvoiceCreditComplete = tests.createExample(TestedComponent, {
|
||||
@ -591,7 +600,7 @@ export const InvoiceCreditComplete = tests.createExample(TestedComponent, {
|
||||
export const InvoiceCreditIncomplete = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.pull_credit,
|
||||
pending: true,
|
||||
extendedStatus: ExtendedStatus.Pending,
|
||||
},
|
||||
});
|
||||
|
||||
@ -609,6 +618,6 @@ export const TransferDebitComplete = tests.createExample(TestedComponent, {
|
||||
export const TransferDebitIncomplete = tests.createExample(TestedComponent, {
|
||||
transaction: {
|
||||
...exampleData.push_debit,
|
||||
pending: true,
|
||||
extendedStatus: ExtendedStatus.Pending,
|
||||
},
|
||||
});
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
AbsoluteTime,
|
||||
AmountJson,
|
||||
Amounts,
|
||||
ExtendedStatus,
|
||||
Location,
|
||||
MerchantInfo,
|
||||
NotificationType,
|
||||
@ -60,11 +61,12 @@ import {
|
||||
WarningBox,
|
||||
} from "../components/styled/index.js";
|
||||
import { Time } from "../components/Time.js";
|
||||
import { alertFromError } from "../context/alert.js";
|
||||
import { alertFromError, useAlertContext } from "../context/alert.js";
|
||||
import { useBackendContext } from "../context/backend.js";
|
||||
import { useTranslationContext } from "../context/translation.js";
|
||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
||||
import { Button } from "../mui/Button.js";
|
||||
import { SafeHandler } from "../mui/handlers.js";
|
||||
import { Pages } from "../NavigationBar.js";
|
||||
|
||||
interface Props {
|
||||
@ -116,6 +118,12 @@ export function TransactionPage({
|
||||
onSend={async () => {
|
||||
null;
|
||||
}}
|
||||
onCancel={async () => {
|
||||
await api.wallet.call(WalletApiOperation.AbortTransaction, {
|
||||
transactionId,
|
||||
});
|
||||
goToWalletHistory(currency);
|
||||
}}
|
||||
onDelete={async () => {
|
||||
await api.wallet.call(WalletApiOperation.DeleteTransaction, {
|
||||
transactionId,
|
||||
@ -141,6 +149,7 @@ export function TransactionPage({
|
||||
export interface WalletTransactionProps {
|
||||
transaction: Transaction;
|
||||
onSend: () => Promise<void>;
|
||||
onCancel: () => Promise<void>;
|
||||
onDelete: () => Promise<void>;
|
||||
onRetry: () => Promise<void>;
|
||||
onRefund: (id: string) => Promise<void>;
|
||||
@ -155,18 +164,29 @@ const PurchaseDetailsTable = styled.table`
|
||||
}
|
||||
`;
|
||||
|
||||
export function TransactionView({
|
||||
type TransactionTemplateProps = Omit<
|
||||
Omit<WalletTransactionProps, "onRefund">,
|
||||
"onBack"
|
||||
> & {
|
||||
children: ComponentChildren;
|
||||
};
|
||||
|
||||
function TransactionTemplate({
|
||||
transaction,
|
||||
onDelete,
|
||||
onRetry,
|
||||
onSend,
|
||||
onRefund,
|
||||
}: WalletTransactionProps): VNode {
|
||||
onCancel,
|
||||
children,
|
||||
}: TransactionTemplateProps): VNode {
|
||||
const { i18n } = useTranslationContext();
|
||||
const [confirmBeforeForget, setConfirmBeforeForget] = useState(false);
|
||||
const [confirmBeforeCancel, setConfirmBeforeCancel] = useState(false);
|
||||
const { safely } = useAlertContext();
|
||||
|
||||
async function doCheckBeforeForget(): Promise<void> {
|
||||
if (
|
||||
transaction.pending &&
|
||||
transaction.extendedStatus === ExtendedStatus.Pending &&
|
||||
transaction.type === TransactionType.Withdrawal
|
||||
) {
|
||||
setConfirmBeforeForget(true);
|
||||
@ -175,97 +195,64 @@ export function TransactionView({
|
||||
}
|
||||
}
|
||||
|
||||
const SHOWING_RETRY_THRESHOLD_SECS = 30;
|
||||
|
||||
const { i18n } = useTranslationContext();
|
||||
|
||||
function TransactionTemplate({
|
||||
children,
|
||||
}: {
|
||||
children: ComponentChildren;
|
||||
}): VNode {
|
||||
const showSend = false;
|
||||
// (transaction.type === TransactionType.PeerPullCredit ||
|
||||
// transaction.type === TransactionType.PeerPushDebit) &&
|
||||
// !transaction.info.completed;
|
||||
const showRetry =
|
||||
transaction.error !== undefined ||
|
||||
transaction.timestamp.t_s === "never" ||
|
||||
(transaction.pending &&
|
||||
differenceInSeconds(new Date(), transaction.timestamp.t_s * 1000) >
|
||||
SHOWING_RETRY_THRESHOLD_SECS);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<section style={{ padding: 8, textAlign: "center" }}>
|
||||
{transaction?.error ? (
|
||||
transaction.error.code === 7025 ? (
|
||||
<AlertView
|
||||
alert={{
|
||||
type: "warning",
|
||||
message: i18n.str`KYC check required for the transaction to complete`,
|
||||
description:
|
||||
transaction.error.kycUrl &&
|
||||
typeof transaction.error.kycUrl === "string" ? (
|
||||
<div>
|
||||
<i18n.Translate>
|
||||
Follow this link to the{` `}
|
||||
<a href={transaction.error.kycUrl}>KYC verifier</a>
|
||||
</i18n.Translate>
|
||||
</div>
|
||||
) : (
|
||||
i18n.str`No more information has been provided`
|
||||
),
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<ErrorAlertView
|
||||
error={alertFromError(
|
||||
i18n.str`There was an error trying to complete the transaction`,
|
||||
transaction.error,
|
||||
)}
|
||||
/>
|
||||
)
|
||||
) : undefined}
|
||||
{transaction.pending && (
|
||||
<WarningBox>
|
||||
<i18n.Translate>This transaction is not completed</i18n.Translate>
|
||||
</WarningBox>
|
||||
)}
|
||||
</section>
|
||||
<section>{children}</section>
|
||||
<footer>
|
||||
<div>
|
||||
{showSend ? (
|
||||
<Button variant="contained" onClick={onSend}>
|
||||
<i18n.Translate>Send</i18n.Translate>
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
<div>
|
||||
{showRetry ? (
|
||||
<Button variant="contained" onClick={onRetry}>
|
||||
<i18n.Translate>Retry</i18n.Translate>
|
||||
</Button>
|
||||
) : null}
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={doCheckBeforeForget}
|
||||
>
|
||||
<i18n.Translate>Forget</i18n.Translate>
|
||||
</Button>
|
||||
</div>
|
||||
</footer>
|
||||
</Fragment>
|
||||
);
|
||||
async function doCheckBeforeCancel(): Promise<void> {
|
||||
setConfirmBeforeCancel(true);
|
||||
}
|
||||
|
||||
if (transaction.type === TransactionType.Withdrawal) {
|
||||
const total = Amounts.parseOrThrow(transaction.amountEffective);
|
||||
const chosen = Amounts.parseOrThrow(transaction.amountRaw);
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
const SHOWING_RETRY_THRESHOLD_SECS = 30;
|
||||
|
||||
const showSend = false;
|
||||
// (transaction.type === TransactionType.PeerPullCredit ||
|
||||
// transaction.type === TransactionType.PeerPushDebit) &&
|
||||
// !transaction.info.completed;
|
||||
const showRetry =
|
||||
transaction.error !== undefined ||
|
||||
transaction.timestamp.t_s === "never" ||
|
||||
(transaction.extendedStatus === ExtendedStatus.Pending &&
|
||||
differenceInSeconds(new Date(), transaction.timestamp.t_s * 1000) >
|
||||
SHOWING_RETRY_THRESHOLD_SECS);
|
||||
|
||||
const transactionStillActive =
|
||||
transaction.extendedStatus !== ExtendedStatus.Aborted &&
|
||||
transaction.extendedStatus !== ExtendedStatus.Done &&
|
||||
transaction.extendedStatus !== ExtendedStatus.Failed;
|
||||
return (
|
||||
<Fragment>
|
||||
<section style={{ padding: 8, textAlign: "center" }}>
|
||||
{transaction?.error ? (
|
||||
transaction.error.code === 7025 ? (
|
||||
<AlertView
|
||||
alert={{
|
||||
type: "warning",
|
||||
message: i18n.str`KYC check required for the transaction to complete`,
|
||||
description:
|
||||
transaction.error.kycUrl &&
|
||||
typeof transaction.error.kycUrl === "string" ? (
|
||||
<div>
|
||||
<i18n.Translate>
|
||||
Follow this link to the{` `}
|
||||
<a href={transaction.error.kycUrl}>KYC verifier</a>
|
||||
</i18n.Translate>
|
||||
</div>
|
||||
) : (
|
||||
i18n.str`No more information has been provided`
|
||||
),
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<ErrorAlertView
|
||||
error={alertFromError(
|
||||
i18n.str`There was an error trying to complete the transaction`,
|
||||
transaction.error,
|
||||
)}
|
||||
/>
|
||||
)
|
||||
) : undefined}
|
||||
{transaction.extendedStatus === ExtendedStatus.Pending && (
|
||||
<WarningBox>
|
||||
<i18n.Translate>This transaction is not completed</i18n.Translate>
|
||||
</WarningBox>
|
||||
)}
|
||||
{confirmBeforeForget ? (
|
||||
<Overlay>
|
||||
<CenteredDialog>
|
||||
@ -282,18 +269,134 @@ export function TransactionView({
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={async () => setConfirmBeforeForget(false)}
|
||||
onClick={
|
||||
(async () =>
|
||||
setConfirmBeforeForget(false)) as SafeHandler<void>
|
||||
}
|
||||
>
|
||||
<i18n.Translate>Cancel</i18n.Translate>
|
||||
</Button>
|
||||
|
||||
<Button variant="contained" color="error" onClick={onDelete}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={safely(
|
||||
onDelete,
|
||||
i18n.str`Could not forget transaction`,
|
||||
)}
|
||||
>
|
||||
<i18n.Translate>Confirm</i18n.Translate>
|
||||
</Button>
|
||||
</footer>
|
||||
</CenteredDialog>
|
||||
</Overlay>
|
||||
) : undefined}
|
||||
{confirmBeforeCancel ? (
|
||||
<Overlay>
|
||||
<CenteredDialog>
|
||||
<header>
|
||||
<i18n.Translate>Caution!</i18n.Translate>
|
||||
</header>
|
||||
<section>
|
||||
<i18n.Translate>
|
||||
Doing a cancelation while the transaction still active might
|
||||
result in lost coins. Do you still want to cancel the
|
||||
transaction?
|
||||
</i18n.Translate>
|
||||
</section>
|
||||
<footer>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={
|
||||
(async () =>
|
||||
setConfirmBeforeCancel(false)) as SafeHandler<void>
|
||||
}
|
||||
>
|
||||
<i18n.Translate>No</i18n.Translate>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={safely(
|
||||
onCancel,
|
||||
i18n.str`Could not cancel the active transaction`,
|
||||
)}
|
||||
>
|
||||
<i18n.Translate>Yes</i18n.Translate>
|
||||
</Button>
|
||||
</footer>
|
||||
</CenteredDialog>
|
||||
</Overlay>
|
||||
) : undefined}
|
||||
</section>
|
||||
<section>{children}</section>
|
||||
<footer>
|
||||
<div>
|
||||
{showSend ? (
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={safely(onSend, i18n.str`Could not send`)}
|
||||
>
|
||||
<i18n.Translate>Send</i18n.Translate>
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
<div>
|
||||
{showRetry ? (
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={safely(onRetry, i18n.str`Could not retry`)}
|
||||
>
|
||||
<i18n.Translate>Retry</i18n.Translate>
|
||||
</Button>
|
||||
) : null}
|
||||
{transactionStillActive ? (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={doCheckBeforeCancel as SafeHandler<void>}
|
||||
>
|
||||
<i18n.Translate>Cancel</i18n.Translate>
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={doCheckBeforeForget as SafeHandler<void>}
|
||||
>
|
||||
<i18n.Translate>Forget</i18n.Translate>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</footer>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
export function TransactionView({
|
||||
transaction,
|
||||
onDelete,
|
||||
onRetry,
|
||||
onSend,
|
||||
onRefund,
|
||||
onCancel,
|
||||
}: WalletTransactionProps): VNode {
|
||||
const { i18n } = useTranslationContext();
|
||||
const { safely } = useAlertContext();
|
||||
|
||||
if (transaction.type === TransactionType.Withdrawal) {
|
||||
const total = Amounts.parseOrThrow(transaction.amountEffective);
|
||||
const chosen = Amounts.parseOrThrow(transaction.amountRaw);
|
||||
return (
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
type={i18n.str`Withdrawal`}
|
||||
@ -303,7 +406,8 @@ export function TransactionView({
|
||||
{transaction.exchangeBaseUrl}
|
||||
</Header>
|
||||
|
||||
{!transaction.pending ? undefined : transaction.withdrawalDetails
|
||||
{transaction.extendedStatus !==
|
||||
ExtendedStatus.Pending ? undefined : transaction.withdrawalDetails
|
||||
.type === WithdrawalType.ManualTransfer ? (
|
||||
<Fragment>
|
||||
<BankDetailsByPaytoType
|
||||
@ -418,7 +522,13 @@ export function TransactionView({
|
||||
const total = Amounts.sub(price.effective, refund.effective).amount;
|
||||
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
total={total}
|
||||
@ -491,7 +601,10 @@ export function TransactionView({
|
||||
<div>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => onRefund(transaction.proposalId)}
|
||||
onClick={safely(
|
||||
() => onRefund(transaction.proposalId),
|
||||
i18n.str`Could not refund`,
|
||||
)}
|
||||
>
|
||||
<i18n.Translate>Accept</i18n.Translate>
|
||||
</Button>
|
||||
@ -529,7 +642,13 @@ export function TransactionView({
|
||||
const total = Amounts.parseOrThrow(transaction.amountRaw);
|
||||
const payto = parsePaytoUri(transaction.targetPaytoUri);
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
type={i18n.str`Deposit`}
|
||||
@ -567,7 +686,13 @@ export function TransactionView({
|
||||
).amount;
|
||||
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
type={i18n.str`Refresh`}
|
||||
@ -588,7 +713,13 @@ export function TransactionView({
|
||||
const total = Amounts.parseOrThrow(transaction.amountEffective);
|
||||
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
type={i18n.str`Tip`}
|
||||
@ -613,7 +744,13 @@ export function TransactionView({
|
||||
if (transaction.type === TransactionType.Refund) {
|
||||
const total = Amounts.parseOrThrow(transaction.amountEffective);
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
type={i18n.str`Refund`}
|
||||
@ -666,10 +803,10 @@ export function TransactionView({
|
||||
return (
|
||||
<div>
|
||||
<QR text={text} />
|
||||
<Button onClick={copy}>
|
||||
<Button onClick={copy as SafeHandler<void>}>
|
||||
<i18n.Translate>copy</i18n.Translate>
|
||||
</Button>
|
||||
<Button onClick={toggle}>
|
||||
<Button onClick={toggle as SafeHandler<void>}>
|
||||
<i18n.Translate>hide qr</i18n.Translate>
|
||||
</Button>
|
||||
</div>
|
||||
@ -678,10 +815,10 @@ export function TransactionView({
|
||||
return (
|
||||
<div>
|
||||
<div>{text.substring(0, 64)}...</div>
|
||||
<Button onClick={copy}>
|
||||
<Button onClick={copy as SafeHandler<void>}>
|
||||
<i18n.Translate>copy</i18n.Translate>
|
||||
</Button>
|
||||
<Button onClick={toggle}>
|
||||
<Button onClick={toggle as SafeHandler<void>}>
|
||||
<i18n.Translate>show qr</i18n.Translate>
|
||||
</Button>
|
||||
</div>
|
||||
@ -691,7 +828,13 @@ export function TransactionView({
|
||||
if (transaction.type === TransactionType.PeerPullCredit) {
|
||||
const total = Amounts.parseOrThrow(transaction.amountEffective);
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
type={i18n.str`Credit`}
|
||||
@ -713,7 +856,8 @@ export function TransactionView({
|
||||
text={transaction.exchangeBaseUrl as TranslatedString}
|
||||
kind="neutral"
|
||||
/>
|
||||
{transaction.pending /** pending is not-pay */ && (
|
||||
{transaction.extendedStatus ===
|
||||
ExtendedStatus.Pending /** pending is not-pay */ && (
|
||||
<Part
|
||||
title={i18n.str`URI`}
|
||||
text={<ShowQrWithCopy text={transaction.talerUri} />}
|
||||
@ -738,7 +882,13 @@ export function TransactionView({
|
||||
if (transaction.type === TransactionType.PeerPullDebit) {
|
||||
const total = Amounts.parseOrThrow(transaction.amountEffective);
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
type={i18n.str`Debit`}
|
||||
@ -777,7 +927,13 @@ export function TransactionView({
|
||||
if (transaction.type === TransactionType.PeerPushDebit) {
|
||||
const total = Amounts.parseOrThrow(transaction.amountEffective);
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
type={i18n.str`Debit`}
|
||||
@ -824,7 +980,13 @@ export function TransactionView({
|
||||
if (transaction.type === TransactionType.PeerPushCredit) {
|
||||
const total = Amounts.parseOrThrow(transaction.amountEffective);
|
||||
return (
|
||||
<TransactionTemplate>
|
||||
<TransactionTemplate
|
||||
transaction={transaction}
|
||||
onDelete={onDelete}
|
||||
onRetry={onRetry}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Header
|
||||
timestamp={transaction.timestamp}
|
||||
type={i18n.str`Credit`}
|
||||
|
Loading…
Reference in New Issue
Block a user