diff options
Diffstat (limited to 'packages/demobank-ui/src/pages/BusinessAccount.tsx')
-rw-r--r-- | packages/demobank-ui/src/pages/BusinessAccount.tsx | 257 |
1 files changed, 189 insertions, 68 deletions
diff --git a/packages/demobank-ui/src/pages/BusinessAccount.tsx b/packages/demobank-ui/src/pages/BusinessAccount.tsx index 23a03cc9b..6278fe08b 100644 --- a/packages/demobank-ui/src/pages/BusinessAccount.tsx +++ b/packages/demobank-ui/src/pages/BusinessAccount.tsx @@ -20,6 +20,7 @@ import { TranslatedString, } from "@gnu-taler/taler-util"; import { + ErrorType, HttpResponsePaginated, RequestError, useTranslationContext, @@ -44,7 +45,9 @@ import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js"; interface Props { onClose: () => void; onRegister: () => void; - onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode; + onLoadNotOk: <T>( + error: HttpResponsePaginated<T, SandboxBackend.SandboxError>, + ) => VNode; } export function BusinessAccount({ onClose, @@ -79,6 +82,9 @@ export function BusinessAccount({ setNewcashout(false); }} onComplete={(id) => { + showInfoMessage( + i18n.str`Cashout created. You need to confirm the operation to complete the transaction.`, + ); setNewcashout(false); setShowCashoutDetails(id); }} @@ -156,7 +162,9 @@ interface PropsCashout { account: string; onComplete: (id: string) => void; onCancel: () => void; - onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode; + onLoadNotOk: <T>( + error: HttpResponsePaginated<T, SandboxBackend.SandboxError>, + ) => VNode; } type FormType = { @@ -180,7 +188,7 @@ function CreateCashout({ const result = useAccountDetails(account); const [error, saveError] = useState<ErrorMessage | undefined>(); - const [form, setForm] = useState<Partial<FormType>>({}); + const [form, setForm] = useState<Partial<FormType>>({ isDebit: true }); const { createCashout } = useCircuitAccountAPI(); if (!result.ok) return onLoadNotOk(result); @@ -277,10 +285,14 @@ function CreateCashout({ type="text" readonly class="currency-indicator" - size={balance.currency.length} - maxLength={balance.currency.length} + size={ + !form.isDebit ? fiatCurrency.length : balance.currency.length + } + maxLength={ + !form.isDebit ? fiatCurrency.length : balance.currency.length + } tabIndex={-1} - value={balance.currency} + value={!form.isDebit ? fiatCurrency : balance.currency} /> <input @@ -389,16 +401,16 @@ function CreateCashout({ {Amounts.isZero(sellFee) ? undefined : ( <Fragment> <fieldset> - <label>{i18n.str`Transfer before fee`}</label> + <label>{i18n.str`Amount after conversion`}</label> <div style={{ width: "max-content" }}> <input type="text" readonly class="currency-indicator" - size={balance.currency.length} - maxLength={balance.currency.length} + size={fiatCurrency.length} + maxLength={fiatCurrency.length} tabIndex={-1} - value={balance.currency} + value={fiatCurrency} /> <input @@ -417,10 +429,10 @@ function CreateCashout({ type="text" readonly class="currency-indicator" - size={balance.currency.length} - maxLength={balance.currency.length} + size={fiatCurrency.length} + maxLength={fiatCurrency.length} tabIndex={-1} - value={balance.currency} + value={fiatCurrency} /> <input @@ -442,10 +454,10 @@ function CreateCashout({ type="text" readonly class="currency-indicator" - size={balance.currency.length} - maxLength={balance.currency.length} + size={fiatCurrency.length} + maxLength={fiatCurrency.length} tabIndex={-1} - value={balance.currency} + value={fiatCurrency} /> <input @@ -543,34 +555,69 @@ function CreateCashout({ onComplete(res.data.uuid); } catch (error) { if (error instanceof RequestError) { - const errorData: SandboxBackend.SandboxError = - error.info.error; - if (error.info.status === HttpStatusCode.PreconditionFailed) { - saveError({ - title: i18n.str`The account does not have sufficient funds`, - description: errorData.error.description, - debug: JSON.stringify(error.info), - }); - } else if ( - error.info.status === HttpStatusCode.ServiceUnavailable - ) { - saveError({ - title: i18n.str`The bank does not support the TAN channel for this operation`, - description: errorData.error.description, - debug: JSON.stringify(error.info), - }); - } else if (error.info.status === HttpStatusCode.Conflict) { - saveError({ - title: i18n.str`No contact information for this channel`, - description: errorData.error.description, - debug: JSON.stringify(error.info), - }); - } else { - saveError({ - title: i18n.str`New cashout gave response error`, - description: errorData.error.description, - debug: JSON.stringify(error.info), - }); + const e = error as RequestError<SandboxBackend.SandboxError>; + switch (e.cause.type) { + case ErrorType.TIMEOUT: { + saveError({ + title: i18n.str`Request timeout, try again later.`, + }); + break; + } + case ErrorType.CLIENT: { + const errorData = e.cause.error; + + if ( + e.cause.status === HttpStatusCode.PreconditionFailed + ) { + saveError({ + title: i18n.str`The account does not have sufficient funds`, + description: errorData.error.description, + debug: JSON.stringify(error.info), + }); + } else if (e.cause.status === HttpStatusCode.Conflict) { + saveError({ + title: i18n.str`No contact information for this channel`, + description: errorData.error.description, + debug: JSON.stringify(error.info), + }); + } else { + saveError({ + title: i18n.str`New cashout gave response error`, + description: errorData.error.description, + debug: JSON.stringify(error.info), + }); + } + break; + } + case ErrorType.SERVER: { + const errorData = e.cause.error; + if ( + e.cause.status === HttpStatusCode.ServiceUnavailable + ) { + saveError({ + title: i18n.str`The bank does not support the TAN channel for this operation`, + description: errorData.error.description, + debug: JSON.stringify(error.info), + }); + } else { + saveError({ + title: i18n.str`Creating cashout returned with a server error`, + description: errorData.error.description, + debug: JSON.stringify(error.cause), + }); + } + break; + } + case ErrorType.UNEXPECTED: { + saveError({ + title: i18n.str`Unexpected error trying to create cashout.`, + debug: JSON.stringify(error.cause), + }); + break; + } + default: { + assertUnreachable(e.cause); + } } } else if (error instanceof Error) { saveError({ @@ -592,7 +639,9 @@ function CreateCashout({ interface ShowCashoutProps { id: string; onCancel: () => void; - onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode; + onLoadNotOk: <T>( + error: HttpResponsePaginated<T, SandboxBackend.SandboxError>, + ) => VNode; } export function ShowCashoutDetails({ id, @@ -699,22 +748,59 @@ export function ShowCashoutDetails({ onCancel(); } catch (error) { if (error instanceof RequestError) { - const errorData: SandboxBackend.SandboxError = - error.info.error; - if ( - error.info.status === HttpStatusCode.PreconditionFailed - ) { - saveError({ - title: i18n.str`Cashout was already aborted`, - description: errorData.error.description, - debug: JSON.stringify(error.info), - }); - } else { - saveError({ - title: i18n.str`Aborting cashout gave response error`, - description: errorData.error.description, - debug: JSON.stringify(error.info), - }); + const e = + error as RequestError<SandboxBackend.SandboxError>; + switch (e.cause.type) { + case ErrorType.TIMEOUT: { + saveError({ + title: i18n.str`Request timeout, try again later.`, + }); + break; + } + case ErrorType.CLIENT: { + const errorData = e.cause.error; + if ( + e.cause.status === HttpStatusCode.PreconditionFailed + ) { + saveError({ + title: i18n.str`Cashout was already aborted`, + description: errorData.error.description, + debug: JSON.stringify(error.info), + }); + } else { + saveError({ + title: i18n.str`Aborting cashout gave response error`, + description: errorData.error.description, + debug: JSON.stringify(error.info), + }); + } + + saveError({ + title: i18n.str`Aborting cashout gave response error`, + description: errorData.error.description, + debug: JSON.stringify(error.cause), + }); + break; + } + case ErrorType.SERVER: { + const errorData = e.cause.error; + saveError({ + title: i18n.str`Aborting cashout returned with a server error`, + description: errorData.error.description, + debug: JSON.stringify(error.cause), + }); + break; + } + case ErrorType.UNEXPECTED: { + saveError({ + title: i18n.str`Unexpected error trying to abort cashout.`, + debug: JSON.stringify(error.cause), + }); + break; + } + default: { + assertUnreachable(e.cause); + } } } else if (error instanceof Error) { saveError({ @@ -741,13 +827,44 @@ export function ShowCashoutDetails({ }); } catch (error) { if (error instanceof RequestError) { - const errorData: SandboxBackend.SandboxError = - error.info.error; - saveError({ - title: i18n.str`Confirmation of cashout gave response error`, - description: errorData.error.description, - debug: JSON.stringify(error.info), - }); + const e = + error as RequestError<SandboxBackend.SandboxError>; + switch (e.cause.type) { + case ErrorType.TIMEOUT: { + saveError({ + title: i18n.str`Request timeout, try again later.`, + }); + break; + } + case ErrorType.CLIENT: { + const errorData = e.cause.error; + saveError({ + title: i18n.str`Confirmation of cashout gave response error`, + description: errorData.error.description, + debug: JSON.stringify(error.cause), + }); + break; + } + case ErrorType.SERVER: { + const errorData = e.cause.error; + saveError({ + title: i18n.str`Confirmation of cashout gave response error`, + description: errorData.error.description, + debug: JSON.stringify(error.cause), + }); + break; + } + case ErrorType.UNEXPECTED: { + saveError({ + title: i18n.str`Unexpected error trying to cashout.`, + debug: JSON.stringify(error.cause), + }); + break; + } + default: { + assertUnreachable(e.cause); + } + } } else if (error instanceof Error) { saveError({ title: i18n.str`Confirmation failed, please report`, @@ -767,3 +884,7 @@ export function ShowCashoutDetails({ </div> ); } + +export function assertUnreachable(x: never): never { + throw new Error("Didn't expect to get here"); +} |