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