wallet-core/packages/demobank-ui/src/pages/AccountPage.tsx

153 lines
4.8 KiB
TypeScript
Raw Normal View History

2022-12-07 16:38:50 +01:00
/*
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 <http://www.gnu.org/licenses/>
*/
2023-02-08 21:41:19 +01:00
import { Amounts, parsePaytoUri } from "@gnu-taler/taler-util";
import {
HttpResponsePaginated,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Cashouts } from "../components/Cashouts/index.js";
import { Transactions } from "../components/Transactions/index.js";
2023-02-08 21:41:19 +01:00
import { useAccountDetails } from "../hooks/access.js";
import { PaymentOptions } from "./PaymentOptions.js";
2022-12-07 16:38:50 +01:00
2023-02-08 21:41:19 +01:00
interface Props {
account: string;
onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
2022-12-07 16:38:50 +01:00
}
/**
2023-02-08 21:41:19 +01:00
* Query account information and show QR code if there is pending withdrawal
2022-12-07 16:38:50 +01:00
*/
2023-02-08 21:41:19 +01:00
export function AccountPage({ account, onLoadNotOk }: Props): VNode {
const result = useAccountDetails(account);
2022-12-07 16:38:50 +01:00
const { i18n } = useTranslationContext();
2023-02-08 21:41:19 +01:00
if (!result.ok) {
return onLoadNotOk(result);
2022-12-07 16:38:50 +01:00
}
2023-02-08 21:41:19 +01:00
const { data } = result;
const balance = Amounts.parse(data.balance.amount);
const errorParsingBalance = !balance;
const payto = parsePaytoUri(data.paytoUri);
if (!payto || !payto.isKnown || payto.targetType !== "iban") {
2022-12-07 16:38:50 +01:00
return (
2023-02-08 21:41:19 +01:00
<div>Payto from server is not valid &quot;{data.paytoUri}&quot;</div>
2022-12-07 16:38:50 +01:00
);
}
2023-02-08 21:41:19 +01:00
const accountNumber = payto.iban;
const balanceIsDebit = data.balance.credit_debit_indicator == "debit";
2022-12-07 16:38:50 +01:00
return (
2023-02-08 21:41:19 +01:00
<Fragment>
2022-12-07 16:38:50 +01:00
<div>
<h1 class="nav welcome-text">
<i18n.Translate>
Welcome,
2023-02-08 21:41:19 +01:00
{accountNumber ? `${account} (${accountNumber})` : account}!
2022-12-07 16:38:50 +01:00
</i18n.Translate>
</h1>
</div>
{errorParsingBalance ? (
<div class="informational informational-fail" style={{ marginTop: 8 }}>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<p>
<b>Server Error: invalid balance</b>
</p>
</div>
<p>Your account is in an invalid state.</p>
</div>
) : (
<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}
2023-02-08 21:41:19 +01:00
<span class="value">{`${Amounts.stringifyValue(
balance,
)}`}</span>
&nbsp;
<span class="currency">{`${balance.currency}`}</span>
</div>
)}
2022-12-07 16:38:50 +01:00
</div>
</section>
<section id="payments">
<div class="payments">
<h2>{i18n.str`Payments`}</h2>
2023-02-08 21:41:19 +01:00
<PaymentOptions currency={balance.currency} />
2022-12-07 16:38:50 +01:00
</div>
</section>
</Fragment>
)}
2023-02-08 21:41:19 +01:00
<section style={{ marginTop: "2em" }}>
<Moves account={account} />
2022-12-07 16:38:50 +01:00
</section>
2023-02-08 21:41:19 +01:00
</Fragment>
2022-12-07 16:38:50 +01:00
);
}
2023-02-08 21:41:19 +01:00
function Moves({ account }: { account: string }): VNode {
const [tab, setTab] = useState<"transactions" | "cashouts">("transactions");
const { i18n } = useTranslationContext();
return (
<article>
<div class="payments">
<div class="tab">
<button
class={tab === "transactions" ? "tablinks active" : "tablinks"}
onClick={(): void => {
setTab("transactions");
}}
>
{i18n.str`Transactions`}
</button>
<button
class={tab === "cashouts" ? "tablinks active" : "tablinks"}
onClick={(): void => {
setTab("cashouts");
}}
>
{i18n.str`Cashouts`}
</button>
</div>
{tab === "transactions" && (
<div class="active">
<h3>{i18n.str`Latest transactions`}</h3>
<Transactions account={account} />
</div>
)}
{tab === "cashouts" && (
<div class="active">
<h3>{i18n.str`Latest cashouts`}</h3>
<Cashouts account={account} />
</div>
)}
</div>
</article>
);
}