summaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/pages/AdminPage.tsx
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-04-07 17:30:01 -0300
committerSebastian <sebasjm@gmail.com>2023-04-07 17:30:01 -0300
commita3aa7d95d09c83794067c47df4a455c0e3f21806 (patch)
tree00837196305227fe6f7cbc7289f96b256d5de089 /packages/demobank-ui/src/pages/AdminPage.tsx
parent43ae414a55b84b1125c5e4377c6d485ca6c748e2 (diff)
downloadwallet-core-a3aa7d95d09c83794067c47df4a455c0e3f21806.tar.gz
wallet-core-a3aa7d95d09c83794067c47df4a455c0e3f21806.tar.bz2
wallet-core-a3aa7d95d09c83794067c47df4a455c0e3f21806.zip
anon withdrawal confirmation, and fix error with infinity loop
Diffstat (limited to 'packages/demobank-ui/src/pages/AdminPage.tsx')
-rw-r--r--packages/demobank-ui/src/pages/AdminPage.tsx179
1 files changed, 81 insertions, 98 deletions
diff --git a/packages/demobank-ui/src/pages/AdminPage.tsx b/packages/demobank-ui/src/pages/AdminPage.tsx
index 92464a43e..b867d0103 100644
--- a/packages/demobank-ui/src/pages/AdminPage.tsx
+++ b/packages/demobank-ui/src/pages/AdminPage.tsx
@@ -14,13 +14,9 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+import { Amounts, HttpStatusCode, parsePaytoUri } from "@gnu-taler/taler-util";
import {
- Amounts,
- HttpStatusCode,
- parsePaytoUri,
- TranslatedString,
-} from "@gnu-taler/taler-util";
-import {
+ ErrorType,
HttpResponsePaginated,
RequestError,
useTranslationContext,
@@ -29,11 +25,7 @@ import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Cashouts } from "../components/Cashouts/index.js";
import { useBackendContext } from "../context/backend.js";
-import {
- ErrorMessage,
- PageStateType,
- usePageContext,
-} from "../context/pageState.js";
+import { ErrorMessage, notifyInfo } from "../context/pageState.js";
import { useAccountDetails } from "../hooks/access.js";
import {
useAdminAccountAPI,
@@ -50,6 +42,7 @@ import {
} from "../utils.js";
import { ErrorBannerFloat } from "./BankFrame.js";
import { ShowCashoutDetails } from "./BusinessAccount.js";
+import { handleNotOkResult } from "./HomePage.js";
import { PaytoWireTransferForm } from "./PaytoWireTransferForm.js";
import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js";
@@ -69,14 +62,12 @@ function randomPassword(): string {
}
interface Props {
- onLoadNotOk: <T>(
- error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
- ) => VNode;
+ onRegister: () => void;
}
/**
* Query account information and show QR code if there is pending withdrawal
*/
-export function AdminPage({ onLoadNotOk }: Props): VNode {
+export function AdminPage({ onRegister }: Props): VNode {
const [account, setAccount] = useState<string | undefined>();
const [showDetails, setShowDetails] = useState<string | undefined>();
const [showCashouts, setShowCashouts] = useState<string | undefined>();
@@ -87,24 +78,13 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
>();
const [createAccount, setCreateAccount] = useState(false);
- const { pageStateSetter } = usePageContext();
-
- function showInfoMessage(info: TranslatedString): void {
- pageStateSetter((prev) => ({
- ...prev,
- info,
- }));
- }
- function saveError(error: PageStateType["error"]): void {
- pageStateSetter((prev) => ({ ...prev, error }));
- }
const result = useBusinessAccounts({ account });
const { i18n } = useTranslationContext();
if (result.loading) return <div />;
if (!result.ok) {
- return onLoadNotOk(result);
+ return handleNotOkResult(i18n, onRegister)(result);
}
const { customers } = result.data;
@@ -113,7 +93,7 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
return (
<ShowCashoutDetails
id={showCashoutDetails}
- onLoadNotOk={onLoadNotOk}
+ onLoadNotOk={handleNotOkResult(i18n, onRegister)}
onCancel={() => {
setShowCashoutDetails(undefined);
}}
@@ -155,13 +135,13 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
return (
<ShowAccountDetails
account={showDetails}
- onLoadNotOk={onLoadNotOk}
+ onLoadNotOk={handleNotOkResult(i18n, onRegister)}
onChangePassword={() => {
setUpdatePassword(showDetails);
setShowDetails(undefined);
}}
onUpdateSuccess={() => {
- showInfoMessage(i18n.str`Account updated`);
+ notifyInfo(i18n.str`Account updated`);
setShowDetails(undefined);
}}
onClear={() => {
@@ -174,9 +154,9 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
return (
<RemoveAccount
account={removeAccount}
- onLoadNotOk={onLoadNotOk}
+ onLoadNotOk={handleNotOkResult(i18n, onRegister)}
onUpdateSuccess={() => {
- showInfoMessage(i18n.str`Account removed`);
+ notifyInfo(i18n.str`Account removed`);
setRemoveAccount(undefined);
}}
onClear={() => {
@@ -189,9 +169,9 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
return (
<UpdateAccountPassword
account={updatePassword}
- onLoadNotOk={onLoadNotOk}
+ onLoadNotOk={handleNotOkResult(i18n, onRegister)}
onUpdateSuccess={() => {
- showInfoMessage(i18n.str`Password changed`);
+ notifyInfo(i18n.str`Password changed`);
setUpdatePassword(undefined);
}}
onClear={() => {
@@ -205,7 +185,7 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
<CreateNewAccount
onClose={() => setCreateAccount(false)}
onCreateSuccess={(password) => {
- showInfoMessage(
+ notifyInfo(
i18n.str`Account created with password "${password}". The user must change the password on the next login.`,
);
setCreateAccount(false);
@@ -214,59 +194,6 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
);
}
- function AdminAccount(): VNode {
- const r = useBackendContext();
- const account = r.state.status === "loggedIn" ? r.state.username : "admin";
- const result = useAccountDetails(account);
-
- if (!result.ok) {
- return onLoadNotOk(result);
- }
- const { data } = result;
- const balance = Amounts.parseOrThrow(data.balance.amount);
- const debitThreshold = Amounts.parseOrThrow(result.data.debitThreshold);
- const balanceIsDebit =
- result.data.balance.credit_debit_indicator == "debit";
- const limit = balanceIsDebit
- ? Amounts.sub(debitThreshold, balance).amount
- : Amounts.add(balance, debitThreshold).amount;
- if (!balance) return <Fragment />;
- return (
- <Fragment>
- <section id="assets">
- <div class="asset-summary">
- <h2>{i18n.str`Bank account balance`}</h2>
- {!balance ? (
- <div class="large-amount" style={{ color: "gray" }}>
- Waiting server response...
- </div>
- ) : (
- <div class="large-amount amount">
- {balanceIsDebit ? <b>-</b> : null}
- <span class="value">{`${Amounts.stringifyValue(
- balance,
- )}`}</span>
- &nbsp;
- <span class="currency">{`${balance.currency}`}</span>
- </div>
- )}
- </div>
- </section>
- <PaytoWireTransferForm
- focus
- limit={limit}
- onSuccess={() => {
- pageStateSetter((prevState: PageStateType) => ({
- ...prevState,
- info: i18n.str`Wire transfer created!`,
- }));
- }}
- onError={saveError}
- />
- </Fragment>
- );
- }
-
return (
<Fragment>
<div>
@@ -293,7 +220,7 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
</div>
</p>
- <AdminAccount />
+ <AdminAccount onRegister={onRegister} />
<section
id="main"
style={{ width: 600, marginLeft: "auto", marginRight: "auto" }}
@@ -393,6 +320,53 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
);
}
+function AdminAccount({ onRegister }: { onRegister: () => void }): VNode {
+ const { i18n } = useTranslationContext();
+ const r = useBackendContext();
+ const account = r.state.status === "loggedIn" ? r.state.username : "admin";
+ const result = useAccountDetails(account);
+
+ if (!result.ok) {
+ return handleNotOkResult(i18n, onRegister)(result);
+ }
+ const { data } = result;
+ const balance = Amounts.parseOrThrow(data.balance.amount);
+ const debitThreshold = Amounts.parseOrThrow(result.data.debitThreshold);
+ const balanceIsDebit = result.data.balance.credit_debit_indicator == "debit";
+ const limit = balanceIsDebit
+ ? Amounts.sub(debitThreshold, balance).amount
+ : Amounts.add(balance, debitThreshold).amount;
+ if (!balance) return <Fragment />;
+ return (
+ <Fragment>
+ <section id="assets">
+ <div class="asset-summary">
+ <h2>{i18n.str`Bank account balance`}</h2>
+ {!balance ? (
+ <div class="large-amount" style={{ color: "gray" }}>
+ Waiting server response...
+ </div>
+ ) : (
+ <div class="large-amount amount">
+ {balanceIsDebit ? <b>-</b> : null}
+ <span class="value">{`${Amounts.stringifyValue(balance)}`}</span>
+ &nbsp;
+ <span class="currency">{`${balance.currency}`}</span>
+ </div>
+ )}
+ </div>
+ </section>
+ <PaytoWireTransferForm
+ focus
+ limit={limit}
+ onSuccess={() => {
+ notifyInfo(i18n.str`Wire transfer created!`);
+ }}
+ />
+ </Fragment>
+ );
+}
+
const IBAN_REGEX = /^[A-Z][A-Z0-9]*$/;
const EMAIL_REGEX =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
@@ -442,10 +416,13 @@ export function UpdateAccountPassword({
const [repeat, setRepeat] = useState<string | undefined>();
const [error, saveError] = useState<ErrorMessage | undefined>();
- if (result.clientError) {
- if (result.isNotfound) return <div>account not found</div>;
- }
if (!result.ok) {
+ if (result.loading || result.type === ErrorType.TIMEOUT) {
+ return onLoadNotOk(result);
+ }
+ if (result.status === HttpStatusCode.NotFound) {
+ return <div>account not found</div>;
+ }
return onLoadNotOk(result);
}
@@ -679,10 +656,13 @@ export function ShowAccountDetails({
>();
const [error, saveError] = useState<ErrorMessage | undefined>();
- if (result.clientError) {
- if (result.isNotfound) return <div>account not found</div>;
- }
if (!result.ok) {
+ if (result.loading || result.type === ErrorType.TIMEOUT) {
+ return onLoadNotOk(result);
+ }
+ if (result.status === HttpStatusCode.NotFound) {
+ return <div>account not found</div>;
+ }
return onLoadNotOk(result);
}
@@ -804,10 +784,13 @@ function RemoveAccount({
const { deleteAccount } = useAdminAccountAPI();
const [error, saveError] = useState<ErrorMessage | undefined>();
- if (result.clientError) {
- if (result.isNotfound) return <div>account not found</div>;
- }
if (!result.ok) {
+ if (result.loading || result.type === ErrorType.TIMEOUT) {
+ return onLoadNotOk(result);
+ }
+ if (result.status === HttpStatusCode.NotFound) {
+ return <div>account not found</div>;
+ }
return onLoadNotOk(result);
}