From 8407a1d52e3a89f9c005f9820586d2d0a123c177 Mon Sep 17 00:00:00 2001
From: Sebastian <sebasjm@gmail.com>
Date: Mon, 4 Dec 2023 09:43:03 -0300
Subject: api sync, withdrawal info without password, account creation WIP

---
 .../src/pages/WithdrawalConfirmationQuestion.tsx   | 153 ++++++++++++---------
 1 file changed, 90 insertions(+), 63 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 e21c0917b..f8913f0ec 100644
--- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
@@ -25,13 +25,14 @@ import {
   WithdrawUriResult
 } from "@gnu-taler/taler-util";
 import {
+  Attention,
   ErrorLoading,
   Loading,
   notifyInfo,
   useLocalNotification,
   useTranslationContext
 } from "@gnu-taler/web-util/browser";
-import { Fragment, VNode, h } from "preact";
+import { ComponentChildren, Fragment, VNode, h } from "preact";
 import { useMemo, useState } from "preact/hooks";
 import { mutate } from "swr";
 import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
@@ -45,6 +46,7 @@ import { useBackendState } from "../hooks/backend.js";
 import { useWithdrawalDetails } from "../hooks/access.js";
 import { OperationState } from "./OperationState/index.js";
 import { OperationNotFound } from "./WithdrawalQRCode.js";
+import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js";
 
 const logger = new Logger("WithdrawalConfirmationQuestion");
 
@@ -54,6 +56,7 @@ interface Props {
   details: {
     account: PaytoUri,
     reserve: string,
+    username: string,
     amount: AmountJson,
   }
 }
@@ -75,15 +78,16 @@ export function WithdrawalConfirmationQuestion({
     return <Loading />
   }
   if (withdrawalInfo instanceof TalerError) {
-    return <ErrorLoading error={withdrawalInfo} />
+    return <ErrorLoadingWithDebug error={withdrawalInfo} />
   }
   if (withdrawalInfo.type === "fail") {
-    switch(withdrawalInfo.case) {
-      case "not-found": return <OperationNotFound onClose={onAborted}  />
-      default: assertUnreachable(withdrawalInfo.case)
+    switch (withdrawalInfo.case) {
+      case "not-found": return <OperationNotFound onClose={onAborted} />
+      case "invalid-id": return <OperationNotFound onClose={onAborted} />
+      default: assertUnreachable(withdrawalInfo)
     }
   }
-  
+
   const captchaNumbers = useMemo(() => {
     return {
       a: Math.floor(Math.random() * 10),
@@ -200,67 +204,70 @@ export function WithdrawalConfirmationQuestion({
           </h3>
           <div class="mt-3 text-sm leading-6">
 
-            <div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-10 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg">
-              <div class="px-4 sm:px-0">
-                <h2 class="text-base font-semibold text-gray-900"><i18n.Translate>Answer the next question to authorize the wire transfer.</i18n.Translate></h2>
-              </div>
-              <form
-                class="bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2"
-                autoCapitalize="none"
-                autoCorrect="off"
-                onSubmit={e => {
-                  e.preventDefault()
-                }}
-              >
-                <div class="px-4 py-6 sm:p-8">
-                  <label for="withdraw-amount">{i18n.str`What is`}&nbsp;
-                    <em>
-                      {captchaNumbers.a}&nbsp;+&nbsp;{captchaNumbers.b}
-                    </em>
-                    ?
-                  </label>
-                  <div class="mt-2">
-                    <div class="relative rounded-md shadow-sm">
-                      <input
-                        type="text"
-                        // class="block w-full rounded-md border-0 py-1.5 pl-16 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
-                        aria-describedby="answer"
-                        autoFocus
-                        class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
-                        value={captchaAnswer ?? ""}
-                        required
+            <ShouldBeSameUser username={details.username}>
+              <div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-10 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg">
+                <div class="px-4 sm:px-0">
+                  <h2 class="text-base font-semibold text-gray-900"><i18n.Translate>Answer the next question to authorize the wire transfer.</i18n.Translate></h2>
+                </div>
+                <form
+                  class="bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2"
+                  autoCapitalize="none"
+                  autoCorrect="off"
+                  onSubmit={e => {
+                    e.preventDefault()
+                  }}
+                >
+                  <div class="px-4 py-6 sm:p-8">
+                    <label for="withdraw-amount">{i18n.str`What is`}&nbsp;
+                      <em>
+                        {captchaNumbers.a}&nbsp;+&nbsp;{captchaNumbers.b}
+                      </em>
+                      ?
+                    </label>
+
+                    <div class="mt-2">
+                      <div class="relative rounded-md shadow-sm">
+                        <input
+                          type="text"
+                          // class="block w-full rounded-md border-0 py-1.5 pl-16 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
+                          aria-describedby="answer"
+                          autoFocus
+                          class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
+                          value={captchaAnswer ?? ""}
+                          required
 
-                        name="answer"
-                        id="answer"
-                        autocomplete="off"
-                        onChange={(e): void => {
-                          setCaptchaAnswer(e.currentTarget.value)
-                        }}
-                      />
+                          name="answer"
+                          id="answer"
+                          autocomplete="off"
+                          onChange={(e): void => {
+                            setCaptchaAnswer(e.currentTarget.value)
+                          }}
+                        />
+                      </div>
+                      <ShowInputErrorLabel message={errors?.answer} isDirty={captchaAnswer !== undefined} />
                     </div>
-                    <ShowInputErrorLabel message={errors?.answer} isDirty={captchaAnswer !== undefined} />
                   </div>
-                </div>
 
-                <div class="flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
-                  <button type="button" class="text-sm font-semibold leading-6 text-gray-900"
-                    onClick={doCancel}
-                  >
-                    <i18n.Translate>Cancel</i18n.Translate></button>
-                  <button type="submit"
-                    class="disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
-                    disabled={!!errors}
-                    onClick={(e) => {
-                      e.preventDefault()
-                      doTransfer()
-                    }}
-                  >
-                    <i18n.Translate>Transfer</i18n.Translate>
-                  </button>
-                </div>
+                  <div class="flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
+                    <button type="button" class="text-sm font-semibold leading-6 text-gray-900"
+                      onClick={doCancel}
+                    >
+                      <i18n.Translate>Cancel</i18n.Translate></button>
+                    <button type="submit"
+                      class="disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+                      disabled={!!errors}
+                      onClick={(e) => {
+                        e.preventDefault()
+                        doTransfer()
+                      }}
+                    >
+                      <i18n.Translate>Transfer</i18n.Translate>
+                    </button>
+                  </div>
 
-              </form>
-            </div>
+                </form>
+              </div>
+            </ShouldBeSameUser>
           </div>
           <div class="px-4 mt-4 ">
             <div class="w-full">
@@ -325,6 +332,26 @@ export function WithdrawalConfirmationQuestion({
         </div>
       </div>
 
-    </Fragment>
+    </Fragment >
   );
 }
+
+export function ShouldBeSameUser({ username, children }: { username: string, children: ComponentChildren }): VNode {
+  const { state: credentials } = useBackendState();
+  const { i18n } = useTranslationContext()
+  if (credentials.status === "loggedOut") {
+    return <Attention type="info" title={i18n.str`Authentication required`}>
+      <p>You should login as "{username}"</p>
+    </Attention>
+  }
+  if (credentials.username !== username) {
+    return <Attention type="warning" title={i18n.str`This operation was created with other username`}>
+      <p>
+        You can switch to account "{username}" and complete the operation.
+      </p>
+    </Attention>
+  }
+  return <Fragment>
+    {children}
+  </Fragment>
+}
\ No newline at end of file
-- 
cgit v1.2.3

