wallet-core/packages/demobank-ui/src/pages/BankFrame.tsx
2023-02-10 09:52:02 -03:00

240 lines
6.9 KiB
TypeScript

/*
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/>
*/
import { Logger } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { ComponentChildren, Fragment, h, VNode } from "preact";
import talerLogo from "../assets/logo-white.svg";
import { LangSelectorLikePy as LangSelector } from "../components/LangSelector.js";
import { useBackendContext } from "../context/backend.js";
import {
ErrorMessage,
PageStateType,
usePageContext,
} from "../context/pageState.js";
import { useBusinessAccountDetails } from "../hooks/circuit.js";
import { bankUiSettings } from "../settings.js";
const logger = new Logger("BankFrame");
function MaybeBusinessButton({
account,
onClick,
}: {
account: string;
onClick: () => void;
}): VNode {
const { i18n } = useTranslationContext();
const result = useBusinessAccountDetails(account);
if (!result.ok) return <Fragment />;
return (
<div class="some-space">
<a
href="#"
class="pure-button pure-button-primary"
onClick={(e) => {
e.preventDefault();
onClick();
}}
>{i18n.str`Business Profile`}</a>
</div>
);
}
export function BankFrame({
children,
goToBusinessAccount,
}: {
children: ComponentChildren;
goToBusinessAccount?: () => void;
}): VNode {
const { i18n } = useTranslationContext();
const backend = useBackendContext();
const { pageState, pageStateSetter } = usePageContext();
logger.trace("state", pageState);
const demo_sites = [];
for (const i in bankUiSettings.demoSites)
demo_sites.push(
<a href={bankUiSettings.demoSites[i][1]}>
{bankUiSettings.demoSites[i][0]}
</a>,
);
return (
<Fragment>
<header
class="demobar"
style="display: flex; flex-direction: row; justify-content: space-between;"
>
<a href="#main" class="skip">{i18n.str`Skip to main content`}</a>
<div style="max-width: 50em; margin-left: 2em;">
<h1>
<span class="it">
<a href="/">{bankUiSettings.bankName}</a>
</span>
</h1>
{maybeDemoContent(
<p>
<i18n.Translate>
This part of the demo shows how a bank that supports Taler
directly would work. In addition to using your own bank account,
you can also see the transaction history of some{" "}
<a href="/public-accounts">Public Accounts</a>.
</i18n.Translate>
</p>,
)}
</div>
<a href="https://taler.net/">
<img
src={talerLogo}
alt={i18n.str`Taler logo`}
height="100"
width="224"
style="margin: 2em 2em"
/>
</a>
</header>
<div style="display:flex; flex-direction: column;" class="navcontainer">
<nav class="demolist">
{maybeDemoContent(<Fragment>{demo_sites}</Fragment>)}
<div class="right">
<LangSelector />
</div>
</nav>
</div>
<section id="main" class="content">
{pageState.error && (
<ErrorBanner
error={pageState.error}
onClear={() => {
pageStateSetter((prev) => ({ ...prev, error: undefined }));
}}
/>
)}
<StatusBanner />
{backend.state.status === "loggedIn" ? (
<div class="top-right">
{goToBusinessAccount ? (
<MaybeBusinessButton
account={backend.state.username}
onClick={goToBusinessAccount}
/>
) : undefined}
<div class="some-space">
<a
href="#"
class="pure-button logout-button"
onClick={() => {
pageStateSetter((prevState: PageStateType) => {
const { talerWithdrawUri, withdrawalId, ...rest } =
prevState;
backend.logOut();
return {
...rest,
withdrawalInProgress: false,
error: undefined,
info: undefined,
isRawPayto: false,
};
});
}}
>{i18n.str`Logout`}</a>
</div>
</div>
) : null}
{children}
</section>
<section id="footer" class="footer">
<div class="footer">
<hr />
<div>
<p>
You can learn more about GNU Taler on our{" "}
<a href="https://taler.net">main website</a>.
</p>
</div>
<div style="flex-grow:1" />
<p>Copyright &copy; 2014&mdash;2022 Taler Systems SA</p>
</div>
</section>
</Fragment>
);
}
function maybeDemoContent(content: VNode): VNode {
if (bankUiSettings.showDemoNav) {
return content;
}
return <Fragment />;
}
export function ErrorBanner({
error,
onClear,
}: {
error: ErrorMessage;
onClear: () => void;
}): VNode | null {
return (
<div class="informational informational-fail" style={{ marginTop: 8 }}>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<p>
<b>{error.title}</b>
</p>
<div>
<input
type="button"
class="pure-button"
value="Clear"
onClick={(e) => {
e.preventDefault();
onClear();
}}
/>
</div>
</div>
<p>{error.description}</p>
</div>
);
}
function StatusBanner(): VNode | null {
const { pageState, pageStateSetter } = usePageContext();
if (!pageState.info) return null;
const rval = (
<div class="informational informational-ok" style={{ marginTop: 8 }}>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<p>
<b>{pageState.info}</b>
</p>
<div>
<input
type="button"
class="pure-button"
value="Clear"
onClick={async () => {
pageStateSetter((prev) => ({ ...prev, info: undefined }));
}}
/>
</div>
</div>
</div>
);
return rval;
}