/*
This file is part of GNU Taler
(C) 2022 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
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
GNU Taler; see the file COPYING. If not, see
*/
import {
Amounts,
NotificationType,
WalletBalance,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { BalanceTable } from "../components/BalanceTable.js";
import { ErrorAlertView } from "../components/CurrentAlerts.js";
import { Loading } from "../components/Loading.js";
import { MultiActionButton } from "../components/MultiActionButton.js";
import {
ErrorAlert,
alertFromError,
useAlertContext,
} from "../context/alert.js";
import { useBackendContext } from "../context/backend.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { ButtonHandler } from "../mui/handlers.js";
import { StateViewMap, compose } from "../utils/index.js";
import { AddNewActionView } from "../wallet/AddNewActionView.js";
import { NoBalanceHelp } from "./NoBalanceHelp.js";
export interface Props {
goToWalletDeposit: (currency: string) => Promise;
goToWalletHistory: (currency: string) => Promise;
goToWalletManualWithdraw: () => Promise;
}
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: ErrorAlert;
}
export interface Action {
status: "action";
error: undefined;
cancel: ButtonHandler;
}
export interface Balances {
status: "balance";
error: undefined;
balances: WalletBalance[];
addAction: ButtonHandler;
goToWalletDeposit: (currency: string) => Promise;
goToWalletHistory: (currency: string) => Promise;
goToWalletManualWithdraw: ButtonHandler;
}
}
function useComponentState({
goToWalletDeposit,
goToWalletHistory,
goToWalletManualWithdraw,
}: Props): State {
const api = useBackendContext();
const { i18n } = useTranslationContext();
const { pushAlertOnError } = useAlertContext();
const [addingAction, setAddingAction] = useState(false);
const state = useAsyncAsHook(() =>
api.wallet.call(WalletApiOperation.GetBalances, {}),
);
useEffect(() =>
api.listener.onUpdateNotification(
[NotificationType.TransactionStateTransition],
state?.retry,
),
);
if (!state) {
return {
status: "loading",
error: undefined,
};
}
if (state.hasError) {
return {
status: "error",
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 = {
loading: Loading,
error: ErrorAlertView,
action: ActionView,
balance: BalanceView,
};
export const BalancePage = compose(
"BalancePage",
(p: Props) => useComponentState(p),
viewMapping,
);
function ActionView({ cancel }: State.Action): VNode {
return ;
}
export function BalanceView(state: State.Balances): VNode {
const { i18n } = useTranslationContext();
const currencyWithNonZeroAmount = state.balances
.filter((b) => !Amounts.isZero(b.available))
.map((b) => {
b.flags
return b.available.split(":")[0]
});
if (state.balances.length === 0) {
return (
);
}
return (
);
}