diff options
author | Sebastian <sebasjm@gmail.com> | 2023-11-03 19:01:21 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2023-11-03 19:01:21 -0300 |
commit | 954557e841d2d9a978b1b012f0fddc44c37add8a (patch) | |
tree | 0bdfeb66472ccead477ad528a794e35d55649cc3 /packages | |
parent | 11b99b9256d13e16aff460db6f014390ded4670b (diff) | |
download | wallet-core-954557e841d2d9a978b1b012f0fddc44c37add8a.tar.xz |
add error messages for new error cases
Diffstat (limited to 'packages')
17 files changed, 149 insertions, 65 deletions
diff --git a/packages/demobank-ui/src/components/Cashouts/index.ts b/packages/demobank-ui/src/components/Cashouts/index.ts index ae020cef6..09839e753 100644 --- a/packages/demobank-ui/src/components/Cashouts/index.ts +++ b/packages/demobank-ui/src/components/Cashouts/index.ts @@ -18,16 +18,16 @@ import { HttpError, utils } from "@gnu-taler/web-util/browser"; import { Loading } from "../Loading.js"; // import { compose, StateViewMap } from "../../utils/index.js"; // import { wxApi } from "../../wxApi.js"; -import { AbsoluteTime, AmountJson, TalerCorebankApi, TalerError } from "@gnu-taler/taler-util"; +import { AbsoluteTime, AmountJson, TalerCoreBankErrorsByMethod, TalerCorebankApi, TalerError } from "@gnu-taler/taler-util"; import { useComponentState } from "./state.js"; -import { LoadingUriView, ReadyView } from "./views.js"; +import { FailedView, LoadingUriView, ReadyView } from "./views.js"; export interface Props { account: string; onSelected: (id: string) => void; } -export type State = State.Loading | State.LoadingUriError | State.Ready; +export type State = State.Loading | State.Failed | State.LoadingUriError | State.Ready; export namespace State { export interface Loading { @@ -40,6 +40,11 @@ export namespace State { error: TalerError; } + export interface Failed { + status: "failed"; + error: TalerCoreBankErrorsByMethod<"getAccountCashouts">; + } + export interface BaseInfo { error: undefined; } @@ -62,6 +67,7 @@ export interface Transaction { const viewMapping: utils.StateViewMap<State> = { loading: Loading, "loading-error": LoadingUriView, + "failed": FailedView, ready: ReadyView, }; diff --git a/packages/demobank-ui/src/components/Cashouts/state.ts b/packages/demobank-ui/src/components/Cashouts/state.ts index 47ad0a297..814755541 100644 --- a/packages/demobank-ui/src/components/Cashouts/state.ts +++ b/packages/demobank-ui/src/components/Cashouts/state.ts @@ -32,6 +32,12 @@ export function useComponentState({ account, onSelected }: Props): State { error: result, }; } + if (result.type === "fail") { + return { + status: "failed", + error: result + } + } return { status: "ready", diff --git a/packages/demobank-ui/src/components/Cashouts/views.tsx b/packages/demobank-ui/src/components/Cashouts/views.tsx index 32fe0aa9e..89f173b0d 100644 --- a/packages/demobank-ui/src/components/Cashouts/views.tsx +++ b/packages/demobank-ui/src/components/Cashouts/views.tsx @@ -20,6 +20,8 @@ import { State } from "./index.js"; import { format } from "date-fns"; import { Amounts } from "@gnu-taler/taler-util"; import { RenderAmount } from "../../pages/PaytoWireTransferForm.js"; +import { assertUnreachable } from "../Routing.js"; +import { Attention } from "../Attention.js"; export function LoadingUriView({ error }: State.LoadingUriError): VNode { const { i18n } = useTranslationContext(); @@ -30,6 +32,24 @@ export function LoadingUriView({ error }: State.LoadingUriError): VNode { </div> ); } +export function FailedView({ error }: State.Failed) { + const { i18n } = useTranslationContext(); + switch (error.case) { + case "cashout-not-supported": return <Attention type="danger" + title={i18n.str`Cashout not supported.`}> + <div class="mt-2 text-sm text-red-700"> + {error.detail.hint} + </div> + </Attention> + case "account-not-found": return <Attention type="danger" + title={i18n.str`Account not found.`}> + <div class="mt-2 text-sm text-red-700"> + {error.detail.hint} + </div> + </Attention> + default: assertUnreachable(error) + } +} export function ReadyView({ cashouts, onSelected }: State.Ready): VNode { const { i18n } = useTranslationContext(); diff --git a/packages/demobank-ui/src/hooks/circuit.ts b/packages/demobank-ui/src/hooks/circuit.ts index e7a28bd98..845f37822 100644 --- a/packages/demobank-ui/src/hooks/circuit.ts +++ b/packages/demobank-ui/src/hooks/circuit.ts @@ -18,7 +18,7 @@ import { useState } from "preact/hooks"; import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils.js"; import { useBackendState } from "./backend.js"; -import { AccessToken, AmountJson, AmountString, Amounts, OperationOk, TalerCoreBankResultByMethod, TalerCorebankApi, TalerError, TalerHttpError } from "@gnu-taler/taler-util"; +import { AccessToken, AmountJson, AmountString, Amounts, OperationOk, TalerCoreBankErrorsByMethod, TalerCoreBankResultByMethod, TalerCorebankApi, TalerError, TalerHttpError } from "@gnu-taler/taler-util"; import _useSWR, { SWRHook } from "swr"; import { useBankCoreApiContext } from "../context/config.js"; import { assertUnreachable } from "../pages/WithdrawalOperationPage.js"; @@ -105,7 +105,7 @@ export function useBusinessAccounts() { function fetcher([token, offset]: [AccessToken, string]) { //FIXME: add account name filter - return api.getAccounts(token,{}, { + return api.getAccounts(token, {}, { limit: MAX_RESULT_SIZE, offset, order: "asc" @@ -164,10 +164,7 @@ export function useCashouts(account: string) { async function fetcher([username, token]: [string, AccessToken]) { const list = await api.getAccountCashouts({ username, token }) if (list.type !== "ok") { - if (list.case === "cashout-not-supported") { - throw Error("cashout is not supported") - } - assertUnreachable(list.case) + return list; } const all: Array<CashoutWithId | undefined> = await Promise.all(list.body.cashouts.map(c => { return api.getCashoutById({ username, token }, c.cashout_id).then(r => { @@ -180,7 +177,7 @@ export function useCashouts(account: string) { return { type: "ok" as const, body: { cashouts } } } - const { data, error } = useSWR<OperationOk<{ cashouts: CashoutWithId[] }>, TalerHttpError>( + const { data, error } = useSWR<OperationOk<{ cashouts: CashoutWithId[] }> | TalerCoreBankErrorsByMethod<"getAccountCashouts">, TalerHttpError>( !config.have_cashout ? false : [account, token, "getAccountCashouts"], fetcher, { refreshInterval: 0, refreshWhenHidden: false, @@ -269,6 +266,7 @@ export function useLastMonitorInfo(time: Date, timeframe: TalerCorebankApi.Monit const current: TalerCoreBankResultByMethod<"getMonitor"> = { type: "ok" as const, body: { + type: "with-cashout" as const, cashinCount: 1, cashinExternalVolume: "LOCAL:1234" as AmountString, cashoutCount: 2, @@ -281,6 +279,7 @@ export function useLastMonitorInfo(time: Date, timeframe: TalerCorebankApi.Monit const previous = { type: "ok" as const, body: { + type: "with-cashout" as const, cashinCount: 1, cashinExternalVolume: "LOCAL:2345" as AmountString, cashoutCount: 2, diff --git a/packages/demobank-ui/src/pages/AccountPage/state.ts b/packages/demobank-ui/src/pages/AccountPage/state.ts index 6da066d77..d28aba7bf 100644 --- a/packages/demobank-ui/src/pages/AccountPage/state.ts +++ b/packages/demobank-ui/src/pages/AccountPage/state.ts @@ -48,11 +48,6 @@ export function useComponentState({ account, goToConfirmOperation }: Props): Sta status: "login", reason: "not-found", } - case "no-rights": return { - //users are forbiden to see others account - status: "login", - reason: "not-found", - } default: { assertUnreachable(result) } diff --git a/packages/demobank-ui/src/pages/OperationState/views.tsx b/packages/demobank-ui/src/pages/OperationState/views.tsx index ea38525b9..e623b0dc2 100644 --- a/packages/demobank-ui/src/pages/OperationState/views.tsx +++ b/packages/demobank-ui/src/pages/OperationState/views.tsx @@ -129,6 +129,12 @@ export function NeedConfirmationView({ error, onAbort: doAbort, onConfirm: doCon description: hasError.detail.hint as TranslatedString, debug: hasError.detail, }); + case "insufficient-funds": return notify({ + type: "error", + title: i18n.str`Your balance is not enough.`, + description: hasError.detail.hint as TranslatedString, + debug: hasError.detail, + }); default: assertUnreachable(hasError) } }) diff --git a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx index 97e38d75e..31592039f 100644 --- a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx +++ b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx @@ -160,12 +160,30 @@ export function PaytoWireTransferForm({ description: res.detail.hint as TranslatedString, debug: res.detail, }) - case "account-not-found": return notify({ + case "creditor-not-found": return notify({ type: "error", title: i18n.str`The destination account "${puri}" was not found.`, description: res.detail.hint as TranslatedString, debug: res.detail, }) + case "creditor-same": return notify({ + type: "error", + title: i18n.str`The origin and the destination of the transfer can't be the same.`, + description: res.detail.hint as TranslatedString, + debug: res.detail, + }) + case "insufficient-funds": return notify({ + type: "error", + title: i18n.str`Your balance is not enough.`, + description: res.detail.hint as TranslatedString, + debug: res.detail, + }) + case "not-found": return notify({ + type: "error", + title: i18n.str`The origin account "${puri}" was not found.`, + description: res.detail.hint as TranslatedString, + debug: res.detail, + }) default: assertUnreachable(res) } } diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx b/packages/demobank-ui/src/pages/RegistrationPage.tsx index fdf2c0e9d..c2eca25e8 100644 --- a/packages/demobank-ui/src/pages/RegistrationPage.tsx +++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx @@ -99,15 +99,15 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on const creationResponse = await api.createAccount("" as AccessToken, { name: name ?? "", username, password }); if (creationResponse.type === "fail") { switch (creationResponse.case) { - case "invalid-input": return notify({ + case "invalid-phone-or-email": return notify({ type: "error", - title: i18n.str`Some of the input fields are invalid.`, + title: i18n.str`Server replied with invalid phone or email.`, description: creationResponse.detail.hint as TranslatedString, debug: creationResponse.detail, }) - case "unable-to-create": return notify({ + case "insufficient-funds": return notify({ type: "error", - title: i18n.str`Unable to create that account.`, + title: i18n.str`Registration is disabled because the bank ran out of bonus credit.`, description: creationResponse.detail.hint as TranslatedString, debug: creationResponse.detail, }) @@ -117,9 +117,21 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on description: creationResponse.detail.hint as TranslatedString, debug: creationResponse.detail, }) - case "already-exist": return notify({ + case "payto-already-exists": return notify({ type: "error", - title: i18n.str`That username is already taken`, + title: i18n.str`That account id is already taken.`, + description: creationResponse.detail.hint as TranslatedString, + debug: creationResponse.detail, + }) + case "username-already-exists": return notify({ + type: "error", + title: i18n.str`That username is already taken.`, + description: creationResponse.detail.hint as TranslatedString, + debug: creationResponse.detail, + }) + case "username-reserved": return notify({ + type: "error", + title: i18n.str`That username can't be used because is reserved.`, description: creationResponse.detail.hint as TranslatedString, debug: creationResponse.detail, }) diff --git a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx index eb8ea8f20..c07802273 100644 --- a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx +++ b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx @@ -45,7 +45,6 @@ export function ShowAccountDetails({ switch (result.case) { case "not-found": return <LoginForm reason="not-found" /> case "unauthorized": return <LoginForm reason="forbidden" /> - case "no-rights": return <LoginForm reason="forbidden" /> default: assertUnreachable(result) } } @@ -95,7 +94,7 @@ export function ShowAccountDetails({ return ( <Fragment> - <ShowLocalNotification notification={notification} /> + <ShowLocalNotification notification={notification} /> {accountIsTheCurrentUser ? <ProfileNavigation current="details" /> : diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx index 89538e305..b548c0d16 100644 --- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx @@ -119,6 +119,12 @@ export function WithdrawalConfirmationQuestion({ description: resp.detail.hint as TranslatedString, debug: resp.detail, }) + case "insufficient-funds": return notify({ + type: "error", + title: i18n.str`Your balance is not enough for the operation.`, + description: resp.detail.hint as TranslatedString, + debug: resp.detail, + }) default: assertUnreachable(resp) } } @@ -161,7 +167,7 @@ export function WithdrawalConfirmationQuestion({ return ( <Fragment> - <ShowLocalNotification notification={notification} /> + <ShowLocalNotification notification={notification} /> <div class="bg-white shadow sm:rounded-lg"> <div class="px-4 py-5 sm:p-6"> diff --git a/packages/demobank-ui/src/pages/admin/Account.tsx b/packages/demobank-ui/src/pages/admin/Account.tsx index 7109b082f..19189bec4 100644 --- a/packages/demobank-ui/src/pages/admin/Account.tsx +++ b/packages/demobank-ui/src/pages/admin/Account.tsx @@ -23,9 +23,8 @@ export function WireTransfer({ toAccount, onRegister, onCancel, onSuccess }: { o } if (result.type === "fail") { switch (result.case) { - case "unauthorized": return <LoginForm reason="forbidden" /> + case "unauthorized": return <LoginForm reason="forbidden" /> case "not-found": return <LoginForm reason="not-found" /> - case "no-rights": return <LoginForm reason="not-found" /> default: assertUnreachable(result) } } diff --git a/packages/demobank-ui/src/pages/admin/AccountList.tsx b/packages/demobank-ui/src/pages/admin/AccountList.tsx index 056035750..be5194e6d 100644 --- a/packages/demobank-ui/src/pages/admin/AccountList.tsx +++ b/packages/demobank-ui/src/pages/admin/AccountList.tsx @@ -30,9 +30,8 @@ export function AccountList({ onRemoveAccount, onShowAccountDetails, onUpdateAcc } if (result.data.type === "fail") { switch (result.data.case) { - case "unauthorized": return <Fragment/> - case "no-rights": return <Fragment/> - default: assertUnreachable(result.data) + case "unauthorized": return <Fragment /> + default: assertUnreachable(result.data.case) } } diff --git a/packages/demobank-ui/src/pages/admin/AdminHome.tsx b/packages/demobank-ui/src/pages/admin/AdminHome.tsx index 1e3d3d748..a30cae547 100644 --- a/packages/demobank-ui/src/pages/admin/AdminHome.tsx +++ b/packages/demobank-ui/src/pages/admin/AdminHome.tsx @@ -124,25 +124,28 @@ function Metrics(): VNode { </div> <dl class="mt-5 grid grid-cols-1 divide-y divide-gray-200 overflow-hidden rounded-lg bg-white shadow-lg md:grid-cols-3 md:divide-x md:divide-y-0"> - <div class="px-4 py-5 sm:p-6"> - <dt class="text-base font-normal text-gray-900"> - <i18n.Translate>Cashin</i18n.Translate> - </dt> - <MetricValue - current={resp.current.body.cashinExternalVolume} - previous={resp.previous.body.cashinExternalVolume} - /> - </div> - - <div class="px-4 py-5 sm:p-6"> - <dt class="text-base font-normal text-gray-900"> - <i18n.Translate>Cashout</i18n.Translate> - </dt> - <MetricValue - current={resp.current.body.cashoutExternalVolume} - previous={resp.previous.body.cashoutExternalVolume} - /> - </div> + {resp.current.body.type !== "with-cashout" || resp.previous.body.type !== "with-cashout" ? undefined : + <Fragment> + <div class="px-4 py-5 sm:p-6"> + <dt class="text-base font-normal text-gray-900"> + <i18n.Translate>Cashin</i18n.Translate> + </dt> + <MetricValue + current={resp.current.body.cashinExternalVolume} + previous={resp.previous.body.cashinExternalVolume} + /> + </div> + <div class="px-4 py-5 sm:p-6"> + <dt class="text-base font-normal text-gray-900"> + <i18n.Translate>Cashout</i18n.Translate> + </dt> + <MetricValue + current={resp.current.body.cashoutExternalVolume} + previous={resp.previous.body.cashoutExternalVolume} + /> + </div> + </Fragment> + } <div class="px-4 py-5 sm:p-6"> <dt class="text-base font-normal text-gray-900"> <i18n.Translate>Payout</i18n.Translate> diff --git a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx index f2c1d5456..3f4364c16 100644 --- a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx +++ b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx @@ -49,27 +49,39 @@ export function CreateNewAccount({ onCreateSuccess(); } else { switch (resp.case) { - case "invalid-input": return notify({ + case "invalid-phone-or-email": return notify({ type: "error", - title: i18n.str`Server replied that input data was invalid`, + title: i18n.str`Server replied with invalid phone or email`, description: resp.detail.hint as TranslatedString, debug: resp.detail, }) - case "unable-to-create": return notify({ + case "unauthorized": return notify({ type: "error", - title: i18n.str`The account name is registered.`, + title: i18n.str`The rights to perform the operation are not sufficient`, description: resp.detail.hint as TranslatedString, debug: resp.detail, }) - case "unauthorized": return notify({ + case "username-already-exists": return notify({ type: "error", - title: i18n.str`The rights to perform the operation are not sufficient`, + title: i18n.str`Account username is already taken`, + description: resp.detail.hint as TranslatedString, + debug: resp.detail, + }) + case "payto-already-exists": return notify({ + type: "error", + title: i18n.str`Account id is already taken`, + description: resp.detail.hint as TranslatedString, + debug: resp.detail, + }) + case "insufficient-funds": return notify({ + type: "error", + title: i18n.str`Bank ran out of bonus credit.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, }) - case "already-exist": return notify({ + case "username-reserved": return notify({ type: "error", - title: i18n.str`Account name is already taken`, + title: i18n.str`Account username can't be used because is reserved`, description: resp.detail.hint as TranslatedString, debug: resp.detail, }) diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx index 1a5255595..fa9693941 100644 --- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx +++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx @@ -45,7 +45,6 @@ export function RemoveAccount({ switch (result.case) { case "unauthorized": return <LoginForm reason="forbidden" /> case "not-found": return <LoginForm reason="not-found" /> - case "no-rights": return <LoginForm reason="not-found" /> default: assertUnreachable(result) } } @@ -82,9 +81,9 @@ export function RemoveAccount({ description: resp.detail.hint as TranslatedString, debug: resp.detail, }) - case "unable-to-delete": return notify({ + case "username-reserved": return notify({ type: "error", - title: i18n.str`The administrator specified a institutional username.`, + title: i18n.str`Can't delete a reserved username.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, }) diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx b/packages/demobank-ui/src/pages/business/CreateCashout.tsx index 8d90e9205..5c284be24 100644 --- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx +++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx @@ -100,7 +100,6 @@ export function CreateCashout({ switch (resultAccount.case) { case "unauthorized": return <LoginForm reason="forbidden" /> case "not-found": return <LoginForm reason="not-found" /> - case "no-rights": return <LoginForm reason="not-found" /> default: assertUnreachable(resultAccount) } } @@ -178,7 +177,7 @@ export function CreateCashout({ return ( <div> - <ShowLocalNotification notification={notification} /> + <ShowLocalNotification notification={notification} /> <h1>New cashout</h1> <form class="pure-form"> <fieldset> @@ -393,9 +392,15 @@ export function CreateCashout({ description: resp.detail.hint as TranslatedString, debug: resp.detail, }); - case "cashout-or-tan-not-supported": return notify({ + case "account-not-found": return notify({ type: "error", - title: i18n.str`The bank does not support the TAN channel for this operation`, + title: i18n.str`Account not found`, + description: resp.detail.hint as TranslatedString, + debug: resp.detail, + }); + case "cashout-not-supported": return notify({ + type: "error", + title: i18n.str`The bank does not support cashout`, description: resp.detail.hint as TranslatedString, debug: resp.detail, }); diff --git a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx index 7e7ed21cb..a8b57b90c 100644 --- a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx +++ b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx @@ -65,7 +65,7 @@ export function ShowCashoutDetails({ } if (result.type === "fail") { switch (result.case) { - case "already-aborted": return <Attention type="warning" title={i18n.str`This cashout has already been aborted.`}> + case "not-found": return <Attention type="warning" title={i18n.str`This cashout not found. Maybe already aborted.`}> </Attention> case "cashout-not-supported": return <Attention type="warning" title={i18n.str`Cashouts are not supported`}> </Attention> |