wallet-core/packages/taler-wallet-webextension/src/popup/BalancePage.tsx

188 lines
5.3 KiB
TypeScript
Raw Normal View History

2021-07-14 20:21:40 +02:00
/*
2022-06-06 17:05:26 +02:00
This file is part of GNU Taler
(C) 2022 Taler Systems S.A.
2021-07-14 20:21:40 +02:00
2022-06-06 17:05:26 +02:00
GNU Taler is free software; you can redistribute it and/or modify it under the
2021-07-14 20:21:40 +02:00
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
2022-06-06 17:05:26 +02:00
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
2021-07-14 20:21:40 +02:00
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
2022-06-06 17:05:26 +02:00
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
2021-07-14 20:21:40 +02:00
*/
import { Amounts, Balance, NotificationType } from "@gnu-taler/taler-util";
2022-10-25 17:23:08 +02:00
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { Fragment, h, VNode } from "preact";
2022-04-26 03:37:41 +02:00
import { useEffect, useState } from "preact/hooks";
2022-03-29 04:41:07 +02:00
import { BalanceTable } from "../components/BalanceTable.js";
2023-01-09 12:38:48 +01:00
import { ErrorAlertView } from "../components/CurrentAlerts.js";
2022-03-29 04:41:07 +02:00
import { Loading } from "../components/Loading.js";
import { MultiActionButton } from "../components/MultiActionButton.js";
import {
alertFromError,
ErrorAlert,
useAlertContext,
} from "../context/alert.js";
import { useBackendContext } from "../context/backend.js";
2022-03-29 04:41:07 +02:00
import { useTranslationContext } from "../context/translation.js";
2023-01-09 12:38:48 +01:00
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
2022-06-01 20:47:47 +02:00
import { Button } from "../mui/Button.js";
import { ButtonHandler } from "../mui/handlers.js";
import { compose, StateViewMap } from "../utils/index.js";
2022-03-29 04:41:07 +02:00
import { AddNewActionView } from "../wallet/AddNewActionView.js";
import { NoBalanceHelp } from "./NoBalanceHelp.js";
2022-03-17 19:00:34 +01:00
export interface Props {
2022-06-01 20:47:47 +02:00
goToWalletDeposit: (currency: string) => Promise<void>;
goToWalletHistory: (currency: string) => Promise<void>;
goToWalletManualWithdraw: () => Promise<void>;
2021-12-23 19:17:36 +01:00
}
export type State = State.Loading | State.Error | State.Action | State.Balances;
export namespace State {
export interface Loading {
status: "loading";
error: undefined;
}
export interface Error {
status: "error";
2023-01-09 12:38:48 +01:00
error: ErrorAlert;
}
export interface Action {
status: "action";
error: undefined;
cancel: ButtonHandler;
}
export interface Balances {
status: "balance";
error: undefined;
balances: Balance[];
addAction: ButtonHandler;
goToWalletDeposit: (currency: string) => Promise<void>;
goToWalletHistory: (currency: string) => Promise<void>;
goToWalletManualWithdraw: ButtonHandler;
}
}
function useComponentState({
goToWalletDeposit,
goToWalletHistory,
goToWalletManualWithdraw,
}: Props): State {
const api = useBackendContext();
2023-01-09 12:38:48 +01:00
const { i18n } = useTranslationContext();
const { pushAlertOnError } = useAlertContext();
const [addingAction, setAddingAction] = useState(false);
2022-10-25 17:23:08 +02:00
const state = useAsyncAsHook(() =>
api.wallet.call(WalletApiOperation.GetBalances, {}),
);
2022-04-26 03:37:41 +02:00
2022-10-25 17:23:08 +02:00
useEffect(() =>
api.listener.onUpdateNotification(
2022-06-09 19:16:28 +02:00
[NotificationType.WithdrawGroupFinished],
2022-10-25 17:23:08 +02:00
state?.retry,
),
);
2022-04-26 03:37:41 +02:00
if (!state) {
return {
status: "loading",
error: undefined,
};
}
if (state.hasError) {
return {
status: "error",
2023-01-09 12:38:48 +01:00
error: alertFromError(i18n.str`Could not load the balance`, state),
};
}
if (addingAction) {
return {
status: "action",
error: undefined,
cancel: {
onClick: pushAlertOnError(async () => setAddingAction(false)),
},
};
}
return {
status: "balance",
error: undefined,
balances: state.response.balances,
addAction: {
onClick: pushAlertOnError(async () => setAddingAction(true)),
},
goToWalletManualWithdraw: {
onClick: pushAlertOnError(goToWalletManualWithdraw),
},
goToWalletDeposit,
goToWalletHistory,
};
}
const viewMapping: StateViewMap<State> = {
loading: Loading,
2023-01-09 12:38:48 +01:00
error: ErrorAlertView,
action: ActionView,
balance: BalanceView,
};
export const BalancePage = compose(
"BalancePage",
(p: Props) => useComponentState(p),
viewMapping,
);
function ActionView({ cancel }: State.Action): VNode {
return <AddNewActionView onCancel={cancel.onClick!} />;
2021-07-14 20:21:40 +02:00
}
export function BalanceView(state: State.Balances): VNode {
const { i18n } = useTranslationContext();
const currencyWithNonZeroAmount = state.balances
.filter((b) => !Amounts.isZero(b.available))
.map((b) => b.available.split(":")[0]);
2021-10-11 20:59:55 +02:00
if (state.balances.length === 0) {
return (
<NoBalanceHelp
goToWalletManualWithdraw={state.goToWalletManualWithdraw}
/>
2021-11-15 15:18:58 +01:00
);
2021-10-11 20:59:55 +02:00
}
2021-11-15 15:18:58 +01:00
return (
<Fragment>
<section>
2021-12-23 19:17:36 +01:00
<BalanceTable
balances={state.balances}
goToWalletHistory={state.goToWalletHistory}
2021-12-23 19:17:36 +01:00
/>
</section>
2021-12-23 19:17:36 +01:00
<footer style={{ justifyContent: "space-between" }}>
<Button
variant="contained"
onClick={state.goToWalletManualWithdraw.onClick}
>
2022-08-16 02:18:39 +02:00
<i18n.Translate>Add</i18n.Translate>
2022-06-01 20:47:47 +02:00
</Button>
{currencyWithNonZeroAmount.length > 0 && (
<MultiActionButton
2023-01-09 12:38:48 +01:00
label={(s) => i18n.str`Send ${s}`}
actions={currencyWithNonZeroAmount}
onClick={(c) => state.goToWalletDeposit(c)}
/>
)}
2021-11-15 15:18:58 +01:00
</footer>
</Fragment>
2021-11-15 15:18:58 +01:00
);
2021-07-14 20:21:40 +02:00
}