From 9922192b0dba2e479b5af3e29c1d44b98e4d29d7 Mon Sep 17 00:00:00 2001
From: Sebastian <sebasjm@gmail.com>
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 <http://www.gnu.org/licenses/>
  */
 
-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({
     </Fragment>
   );
 }
-
-/**
- * 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<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 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<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 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

