diff options
author | Sebastian <sebasjm@gmail.com> | 2023-02-08 17:41:19 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2023-02-08 17:41:19 -0300 |
commit | a8c5a9696c1735a178158cbc9ac4f9bb4b6f013d (patch) | |
tree | fc24dbf06b548925dbc065a49060473fdd220c94 /packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx | |
parent | 9b0d887a1bc292f652352c1dba4ed4243a88bbbe (diff) | |
download | wallet-core-a8c5a9696c1735a178158cbc9ac4f9bb4b6f013d.tar.gz wallet-core-a8c5a9696c1735a178158cbc9ac4f9bb4b6f013d.tar.bz2 wallet-core-a8c5a9696c1735a178158cbc9ac4f9bb4b6f013d.zip |
impl accout management and refactor
Diffstat (limited to 'packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx')
-rw-r--r-- | packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx | 466 |
1 files changed, 258 insertions, 208 deletions
diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx index b87b77c83..4e5c621e2 100644 --- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx @@ -15,24 +15,29 @@ */ import { Logger } from "@gnu-taler/taler-util"; +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { Fragment, h, VNode } from "preact"; -import { StateUpdater, useMemo, useState } from "preact/hooks"; +import { useMemo, useState } from "preact/hooks"; import { useBackendContext } from "../context/backend.js"; -import { PageStateType, usePageContext } from "../context/pageState.js"; -import { - InternationalizationAPI, - useTranslationContext, -} from "@gnu-taler/web-util/lib/index.browser"; -import { BackendState } from "../hooks/backend.js"; -import { prepareHeaders } from "../utils.js"; +import { usePageContext } from "../context/pageState.js"; +import { useAccessAPI } from "../hooks/access.js"; +import { undefinedIfEmpty } from "../utils.js"; +import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js"; const logger = new Logger("WithdrawalConfirmationQuestion"); +interface Props { + account: string; + withdrawalId: string; +} /** * Additional authentication required to complete the operation. * Not providing a back button, only abort. */ -export function WithdrawalConfirmationQuestion(): VNode { +export function WithdrawalConfirmationQuestion({ + account, + withdrawalId, +}: Props): VNode { const { pageState, pageStateSetter } = usePageContext(); const backend = useBackendContext(); const { i18n } = useTranslationContext(); @@ -42,10 +47,20 @@ export function WithdrawalConfirmationQuestion(): VNode { a: Math.floor(Math.random() * 10), b: Math.floor(Math.random() * 10), }; - }, [pageState.withdrawalId]); + }, []); + const { confirmWithdrawal, abortWithdrawal } = useAccessAPI(); const [captchaAnswer, setCaptchaAnswer] = useState<string | undefined>(); - + const answer = parseInt(captchaAnswer ?? "", 10); + const errors = undefinedIfEmpty({ + answer: !captchaAnswer + ? i18n.str`Answer the question before continue` + : Number.isNaN(answer) + ? i18n.str`The answer should be a number` + : answer !== captchaNumbers.a + captchaNumbers.b + ? i18n.str`The answer "${answer}" to "${captchaNumbers.a} + ${captchaNumbers.b}" is wrong.` + : undefined, + }); return ( <Fragment> <h1 class="nav">{i18n.str`Confirm Withdrawal`}</h1> @@ -82,33 +97,49 @@ export function WithdrawalConfirmationQuestion(): VNode { setCaptchaAnswer(e.currentTarget.value); }} /> + <ShowInputErrorLabel + message={errors?.answer} + isDirty={captchaAnswer !== undefined} + /> </p> <p> <button type="submit" class="pure-button pure-button-primary btn-confirm" + disabled={!!errors} onClick={async (e) => { e.preventDefault(); - if ( - captchaAnswer == - (captchaNumbers.a + captchaNumbers.b).toString() - ) { - await confirmWithdrawalCall( - backend.state, - pageState.withdrawalId, - pageStateSetter, - i18n, - ); - return; + try { + await confirmWithdrawal(withdrawalId); + pageStateSetter((prevState) => { + const { talerWithdrawUri, ...rest } = prevState; + return { + ...rest, + info: i18n.str`Withdrawal confirmed!`, + }; + }); + } catch (error) { + pageStateSetter((prevState) => ({ + ...prevState, + error: { + title: i18n.str`Could not confirm the withdrawal`, + description: (error as any).error.description, + debug: JSON.stringify(error), + }, + })); } - pageStateSetter((prevState: PageStateType) => ({ - ...prevState, - - error: { - title: i18n.str`The answer "${captchaAnswer}" to "${captchaNumbers.a} + ${captchaNumbers.b}" is wrong.`, - }, - })); - setCaptchaAnswer(undefined); + // if ( + // captchaAnswer == + // (captchaNumbers.a + captchaNumbers.b).toString() + // ) { + // await confirmWithdrawalCall( + // backend.state, + // pageState.withdrawalId, + // pageStateSetter, + // i18n, + // ); + // return; + // } }} > {i18n.str`Confirm`} @@ -118,12 +149,31 @@ export function WithdrawalConfirmationQuestion(): VNode { class="pure-button pure-button-secondary btn-cancel" onClick={async (e) => { e.preventDefault(); - await abortWithdrawalCall( - backend.state, - pageState.withdrawalId, - pageStateSetter, - i18n, - ); + try { + await abortWithdrawal(withdrawalId); + pageStateSetter((prevState) => { + const { talerWithdrawUri, ...rest } = prevState; + return { + ...rest, + info: i18n.str`Withdrawal confirmed!`, + }; + }); + } catch (error) { + pageStateSetter((prevState) => ({ + ...prevState, + error: { + title: i18n.str`Could not confirm the withdrawal`, + description: (error as any).error.description, + debug: JSON.stringify(error), + }, + })); + } + // await abortWithdrawalCall( + // backend.state, + // pageState.withdrawalId, + // pageStateSetter, + // i18n, + // ); }} > {i18n.str`Cancel`} @@ -156,188 +206,188 @@ export function WithdrawalConfirmationQuestion(): VNode { * 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<PageStateType>, - i18n: InternationalizationAPI, -): Promise<void> { - if (backendState.status === "loggedOut") { - logger.error("No credentials found."); - pageStateSetter((prevState) => ({ - ...prevState, +// async function confirmWithdrawalCall( +// backendState: BackendState, +// withdrawalId: string | undefined, +// pageStateSetter: StateUpdater<PageStateType>, +// i18n: InternationalizationAPI, +// ): Promise<void> { +// 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 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"); - * */ +// 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, +// // 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`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, +// 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!`, - }; - }); -} +// 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<PageStateType>, - i18n: InternationalizationAPI, -): Promise<void> { - if (backendState.status === "loggedOut") { - logger.error("No credentials found."); - pageStateSetter((prevState) => ({ - ...prevState, +// /** +// * Abort a withdrawal operation via the Access API's /abort. +// */ +// async function abortWithdrawalCall( +// backendState: BackendState, +// withdrawalId: string | undefined, +// pageStateSetter: StateUpdater<PageStateType>, +// i18n: InternationalizationAPI, +// ): Promise<void> { +// 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 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"); - * */ +// 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, +// // 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`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, +// 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!`, - }; - }); -} +// info: i18n.str`Withdrawal aborted!`, +// }; +// }); +// } |