aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-webextension/src/popup/BalancePage.tsx')
-rw-r--r--packages/taler-wallet-webextension/src/popup/BalancePage.tsx152
1 files changed, 104 insertions, 48 deletions
diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
index cdf507cb5..3275a0a07 100644
--- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
@@ -23,8 +23,10 @@ import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import { MultiActionButton } from "../components/MultiActionButton.js";
import { useTranslationContext } from "../context/translation.js";
-import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
+import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
+import { ButtonHandler } from "../mui/handlers.js";
+import { compose, StateViewMap } from "../utils/index.js";
import { AddNewActionView } from "../wallet/AddNewActionView.js";
import * as wxApi from "../wxApi.js";
import { NoBalanceHelp } from "./NoBalanceHelp.js";
@@ -34,17 +36,46 @@ export interface Props {
goToWalletHistory: (currency: string) => Promise<void>;
goToWalletManualWithdraw: () => Promise<void>;
}
-export function BalancePage({
- goToWalletManualWithdraw,
- goToWalletDeposit,
- goToWalletHistory,
-}: Props): VNode {
- const { i18n } = useTranslationContext();
+
+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";
+ error: HookError;
+ }
+
+ 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,
+ api: typeof wxApi,
+): State {
const [addingAction, setAddingAction] = useState(false);
- const state = useAsyncAsHook(wxApi.getBalance);
+ const state = useAsyncAsHook(api.getBalance);
useEffect(() => {
- return wxApi.onUpdateNotification(
+ return api.onUpdateNotification(
[NotificationType.WithdrawGroupFinished],
() => {
state?.retry();
@@ -52,58 +83,80 @@ export function BalancePage({
);
});
- const balances = !state || state.hasError ? [] : state.response.balances;
-
if (!state) {
- return <Loading />;
+ return {
+ status: "loading",
+ error: undefined,
+ };
}
-
if (state.hasError) {
- return (
- <LoadingError
- title={<i18n.Translate>Could not load balance page</i18n.Translate>}
- error={state}
- />
- );
+ return {
+ status: "error",
+ error: state,
+ };
}
-
if (addingAction) {
- return <AddNewActionView onCancel={async () => setAddingAction(false)} />;
+ return {
+ status: "action",
+ error: undefined,
+ cancel: {
+ onClick: async () => setAddingAction(false),
+ },
+ };
}
+ return {
+ status: "balance",
+ error: undefined,
+ balances: state.response.balances,
+ addAction: {
+ onClick: async () => setAddingAction(true),
+ },
+ goToWalletManualWithdraw: {
+ onClick: goToWalletManualWithdraw,
+ },
+ goToWalletDeposit,
+ goToWalletHistory,
+ };
+}
+
+const viewMapping: StateViewMap<State> = {
+ loading: Loading,
+ error: ErrorView,
+ action: ActionView,
+ balance: BalanceView,
+};
+export const BalancePage = compose(
+ "BalancePage",
+ (p: Props) => useComponentState(p, wxApi),
+ viewMapping,
+);
+
+function ErrorView({ error }: State.Error): VNode {
+ const { i18n } = useTranslationContext();
return (
- <BalanceView
- balances={balances}
- goToWalletManualWithdraw={goToWalletManualWithdraw}
- goToWalletDeposit={goToWalletDeposit}
- goToWalletHistory={goToWalletHistory}
- goToAddAction={async () => setAddingAction(true)}
+ <LoadingError
+ title={<i18n.Translate>Could not load balance page</i18n.Translate>}
+ error={error}
/>
);
}
-export interface BalanceViewProps {
- balances: Balance[];
- goToWalletManualWithdraw: () => Promise<void>;
- goToAddAction: () => Promise<void>;
- goToWalletDeposit: (currency: string) => Promise<void>;
- goToWalletHistory: (currency: string) => Promise<void>;
+
+function ActionView({ cancel }: State.Action): VNode {
+ return <AddNewActionView onCancel={cancel.onClick!} />;
}
-export function BalanceView({
- balances,
- goToWalletManualWithdraw,
- goToWalletDeposit,
- goToWalletHistory,
- goToAddAction,
-}: BalanceViewProps): VNode {
+export function BalanceView(state: State.Balances): VNode {
const { i18n } = useTranslationContext();
- const currencyWithNonZeroAmount = balances
+ const currencyWithNonZeroAmount = state.balances
.filter((b) => !Amounts.isZero(b.available))
.map((b) => b.available.split(":")[0]);
- if (balances.length === 0) {
+ if (state.balances.length === 0) {
return (
- <NoBalanceHelp goToWalletManualWithdraw={goToWalletManualWithdraw} />
+ <NoBalanceHelp
+ goToWalletManualWithdraw={state.goToWalletManualWithdraw}
+ />
);
}
@@ -111,23 +164,26 @@ export function BalanceView({
<Fragment>
<section>
<BalanceTable
- balances={balances}
- goToWalletHistory={goToWalletHistory}
+ balances={state.balances}
+ goToWalletHistory={state.goToWalletHistory}
/>
</section>
<footer style={{ justifyContent: "space-between" }}>
- <Button variant="contained" onClick={goToWalletManualWithdraw}>
+ <Button
+ variant="contained"
+ onClick={state.goToWalletManualWithdraw.onClick}
+ >
<i18n.Translate>Withdraw</i18n.Translate>
</Button>
{currencyWithNonZeroAmount.length > 0 && (
<MultiActionButton
label={(s) => <i18n.Translate>Deposit {s}</i18n.Translate>}
actions={currencyWithNonZeroAmount}
- onClick={(c) => goToWalletDeposit(c)}
+ onClick={(c) => state.goToWalletDeposit(c)}
/>
)}
<JustInDevMode>
- <Button onClick={goToAddAction}>
+ <Button onClick={state.addAction.onClick}>
<i18n.Translate>Enter URI</i18n.Translate>
</Button>
</JustInDevMode>