From 9922192b0dba2e479b5af3e29c1d44b98e4d29d7 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 28 Feb 2023 19:03:43 -0300 Subject: fix #7729 --- .../src/pages/WithdrawalConfirmationQuestion.tsx | 306 ++++----------------- 1 file changed, 53 insertions(+), 253 deletions(-) (limited to 'packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx') diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx index 4e5c621e2..d7ed215be 100644 --- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx @@ -14,32 +14,36 @@ GNU Taler; see the file COPYING. If not, see */ -import { Logger } from "@gnu-taler/taler-util"; -import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; +import { HttpStatusCode, Logger } from "@gnu-taler/taler-util"; +import { + RequestError, + useTranslationContext, +} from "@gnu-taler/web-util/lib/index.browser"; import { Fragment, h, VNode } from "preact"; import { useMemo, useState } from "preact/hooks"; -import { useBackendContext } from "../context/backend.js"; -import { usePageContext } from "../context/pageState.js"; +import { PageStateType, usePageContext } from "../context/pageState.js"; import { useAccessAPI } from "../hooks/access.js"; -import { undefinedIfEmpty } from "../utils.js"; +import { buildRequestErrorMessage, undefinedIfEmpty } from "../utils.js"; import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js"; const logger = new Logger("WithdrawalConfirmationQuestion"); interface Props { - account: string; withdrawalId: string; + onError: (e: PageStateType["error"]) => void; + onConfirmed: () => void; + onAborted: () => void; } /** * Additional authentication required to complete the operation. * Not providing a back button, only abort. */ export function WithdrawalConfirmationQuestion({ - account, + onError, + onConfirmed, + onAborted, withdrawalId, }: Props): VNode { - const { pageState, pageStateSetter } = usePageContext(); - const backend = useBackendContext(); const { i18n } = useTranslationContext(); const captchaNumbers = useMemo(() => { @@ -111,35 +115,29 @@ export function WithdrawalConfirmationQuestion({ e.preventDefault(); try { await confirmWithdrawal(withdrawalId); - pageStateSetter((prevState) => { - const { talerWithdrawUri, ...rest } = prevState; - return { - ...rest, - info: i18n.str`Withdrawal confirmed!`, - }; - }); + onConfirmed(); } catch (error) { - pageStateSetter((prevState) => ({ - ...prevState, - error: { - title: i18n.str`Could not confirm the withdrawal`, - description: (error as any).error.description, - debug: JSON.stringify(error), - }, - })); + if (error instanceof RequestError) { + onError( + buildRequestErrorMessage(i18n, error.cause, { + onClientError: (status) => + status === HttpStatusCode.Conflict + ? i18n.str`The withdrawal has been aborted previously and can't be confirmed` + : status === HttpStatusCode.UnprocessableEntity + ? i18n.str`The withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before` + : undefined, + }), + ); + } else { + onError({ + title: i18n.str`Operation failed, please report`, + description: + error instanceof Error + ? error.message + : JSON.stringify(error), + }); + } } - // if ( - // captchaAnswer == - // (captchaNumbers.a + captchaNumbers.b).toString() - // ) { - // await confirmWithdrawalCall( - // backend.state, - // pageState.withdrawalId, - // pageStateSetter, - // i18n, - // ); - // return; - // } }} > {i18n.str`Confirm`} @@ -151,29 +149,27 @@ export function WithdrawalConfirmationQuestion({ e.preventDefault(); try { await abortWithdrawal(withdrawalId); - pageStateSetter((prevState) => { - const { talerWithdrawUri, ...rest } = prevState; - return { - ...rest, - info: i18n.str`Withdrawal confirmed!`, - }; - }); + onAborted(); } catch (error) { - pageStateSetter((prevState) => ({ - ...prevState, - error: { - title: i18n.str`Could not confirm the withdrawal`, - description: (error as any).error.description, - debug: JSON.stringify(error), - }, - })); + if (error instanceof RequestError) { + onError( + buildRequestErrorMessage(i18n, error.cause, { + onClientError: (status) => + status === HttpStatusCode.Conflict + ? i18n.str`The reserve operation has been confirmed previously and can't be aborted` + : undefined, + }), + ); + } else { + onError({ + title: i18n.str`Operation failed, please report`, + description: + error instanceof Error + ? error.message + : JSON.stringify(error), + }); + } } - // await abortWithdrawalCall( - // backend.state, - // pageState.withdrawalId, - // pageStateSetter, - // i18n, - // ); }} > {i18n.str`Cancel`} @@ -195,199 +191,3 @@ export function WithdrawalConfirmationQuestion({ ); } - -/** - * This function confirms a withdrawal operation AFTER - * the wallet has given the exchange's payment details - * to the bank (via the Integration API). Such details - * can be given by scanning a QR code or by passing the - * raw taler://withdraw-URI to the CLI wallet. - * - * This function will set the confirmation status in the - * 'page state' and let the related components refresh. - */ -// async function confirmWithdrawalCall( -// backendState: BackendState, -// withdrawalId: string | undefined, -// pageStateSetter: StateUpdater, -// i18n: InternationalizationAPI, -// ): Promise { -// if (backendState.status === "loggedOut") { -// logger.error("No credentials found."); -// pageStateSetter((prevState) => ({ -// ...prevState, - -// error: { -// title: i18n.str`No credentials found.`, -// }, -// })); -// return; -// } -// if (typeof withdrawalId === "undefined") { -// logger.error("No withdrawal ID found."); -// pageStateSetter((prevState) => ({ -// ...prevState, - -// error: { -// title: i18n.str`No withdrawal ID found.`, -// }, -// })); -// return; -// } -// let res: Response; -// try { -// const { username, password } = backendState; -// const headers = prepareHeaders(username, password); -// /** -// * NOTE: tests show that when a same object is being -// * POSTed, caching might prevent same requests from being -// * made. Hence, trying to POST twice the same amount might -// * get silently ignored. -// * -// * headers.append("cache-control", "no-store"); -// * headers.append("cache-control", "no-cache"); -// * headers.append("pragma", "no-cache"); -// * */ - -// // Backend URL must have been stored _with_ a final slash. -// const url = new URL( -// `access-api/accounts/${backendState.username}/withdrawals/${withdrawalId}/confirm`, -// backendState.url, -// ); -// res = await fetch(url.href, { -// method: "POST", -// headers, -// }); -// } catch (error) { -// logger.error("Could not POST withdrawal confirmation to the bank", error); -// pageStateSetter((prevState) => ({ -// ...prevState, - -// error: { -// title: i18n.str`Could not confirm the withdrawal`, -// description: (error as any).error.description, -// debug: JSON.stringify(error), -// }, -// })); -// return; -// } -// if (!res || !res.ok) { -// const response = await res.json(); -// // assume not ok if res is null -// logger.error( -// `Withdrawal confirmation gave response error (${res.status})`, -// res.statusText, -// ); -// pageStateSetter((prevState) => ({ -// ...prevState, - -// error: { -// title: i18n.str`Withdrawal confirmation gave response error`, -// debug: JSON.stringify(response), -// }, -// })); -// return; -// } -// logger.trace("Withdrawal operation confirmed!"); -// pageStateSetter((prevState) => { -// const { talerWithdrawUri, ...rest } = prevState; -// return { -// ...rest, - -// info: i18n.str`Withdrawal confirmed!`, -// }; -// }); -// } - -// /** -// * Abort a withdrawal operation via the Access API's /abort. -// */ -// async function abortWithdrawalCall( -// backendState: BackendState, -// withdrawalId: string | undefined, -// pageStateSetter: StateUpdater, -// i18n: InternationalizationAPI, -// ): Promise { -// if (backendState.status === "loggedOut") { -// logger.error("No credentials found."); -// pageStateSetter((prevState) => ({ -// ...prevState, - -// error: { -// title: i18n.str`No credentials found.`, -// }, -// })); -// return; -// } -// if (typeof withdrawalId === "undefined") { -// logger.error("No withdrawal ID found."); -// pageStateSetter((prevState) => ({ -// ...prevState, - -// error: { -// title: i18n.str`No withdrawal ID found.`, -// }, -// })); -// return; -// } -// let res: Response; -// try { -// const { username, password } = backendState; -// const headers = prepareHeaders(username, password); -// /** -// * NOTE: tests show that when a same object is being -// * POSTed, caching might prevent same requests from being -// * made. Hence, trying to POST twice the same amount might -// * get silently ignored. Needs more observation! -// * -// * headers.append("cache-control", "no-store"); -// * headers.append("cache-control", "no-cache"); -// * headers.append("pragma", "no-cache"); -// * */ - -// // Backend URL must have been stored _with_ a final slash. -// const url = new URL( -// `access-api/accounts/${backendState.username}/withdrawals/${withdrawalId}/abort`, -// backendState.url, -// ); -// res = await fetch(url.href, { method: "POST", headers }); -// } catch (error) { -// logger.error("Could not abort the withdrawal", error); -// pageStateSetter((prevState) => ({ -// ...prevState, - -// error: { -// title: i18n.str`Could not abort the withdrawal.`, -// description: (error as any).error.description, -// debug: JSON.stringify(error), -// }, -// })); -// return; -// } -// if (!res.ok) { -// const response = await res.json(); -// logger.error( -// `Withdrawal abort gave response error (${res.status})`, -// res.statusText, -// ); -// pageStateSetter((prevState) => ({ -// ...prevState, - -// error: { -// title: i18n.str`Withdrawal abortion failed.`, -// description: response.error.description, -// debug: JSON.stringify(response), -// }, -// })); -// return; -// } -// logger.trace("Withdrawal operation aborted!"); -// pageStateSetter((prevState) => { -// const { ...rest } = prevState; -// return { -// ...rest, - -// info: i18n.str`Withdrawal aborted!`, -// }; -// }); -// } -- cgit v1.2.3