[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant-backoffice] branch master updated: Hello World euFin ban
From: |
gnunet |
Subject: |
[taler-merchant-backoffice] branch master updated: Hello World euFin bank. |
Date: |
Tue, 07 Dec 2021 14:24:30 +0100 |
This is an automated email from the git hooks/post-receive script.
ms pushed a commit to branch master
in repository merchant-backoffice.
The following commit(s) were added to refs/heads/master by this push:
new bce0789 Hello World euFin bank.
bce0789 is described below
commit bce078986a8c7b1f53c69a78aa9053ac271165be
Author: ms <ms@taler.net>
AuthorDate: Tue Dec 7 14:20:50 2021 +0100
Hello World euFin bank.
---
.../components/{FlieButton.tsx => FileButton.tsx} | 0
packages/bank/src/components/app.tsx | 5 +-
packages/bank/src/components/menu/SideBar.tsx | 2 +-
packages/bank/src/index.ts | 2 +-
packages/bank/src/pages/home/index.tsx | 300 ++++++++++++++++++++-
5 files changed, 301 insertions(+), 8 deletions(-)
diff --git a/packages/bank/src/components/FlieButton.tsx
b/packages/bank/src/components/FileButton.tsx
similarity index 100%
rename from packages/bank/src/components/FlieButton.tsx
rename to packages/bank/src/components/FileButton.tsx
diff --git a/packages/bank/src/components/app.tsx
b/packages/bank/src/components/app.tsx
index f466849..5739f3a 100644
--- a/packages/bank/src/components/app.tsx
+++ b/packages/bank/src/components/app.tsx
@@ -6,10 +6,7 @@ import { Menu } from "./menu";
const App: FunctionalComponent = () => {
return (
<TranslationProvider>
- <div id="app" class="has-navbar-fixed-top">
- <Menu title="Bank" />
- <BankHome />
- </div>
+ <BankHome />
</TranslationProvider>
);
};
diff --git a/packages/bank/src/components/menu/SideBar.tsx
b/packages/bank/src/components/menu/SideBar.tsx
index d3a8d0a..d7833df 100644
--- a/packages/bank/src/components/menu/SideBar.tsx
+++ b/packages/bank/src/components/menu/SideBar.tsx
@@ -37,7 +37,7 @@ export function Sidebar({ mobile }: Props): VNode {
<div class="aside-tools">
<div class="aside-tools-label">
<div>
- <b>GNU Taler Bank</b>
+ <b>euFin bank</b>
</div>
<div
class="is-size-7 has-text-right"
diff --git a/packages/bank/src/index.ts b/packages/bank/src/index.ts
index 4bd7b28..45b2601 100644
--- a/packages/bank/src/index.ts
+++ b/packages/bank/src/index.ts
@@ -1,4 +1,4 @@
import App from "./components/app";
-import "./scss/main.scss";
+// import "./scss/main.scss";
export default App;
diff --git a/packages/bank/src/pages/home/index.tsx
b/packages/bank/src/pages/home/index.tsx
index 4833c3e..3cf78b3 100644
--- a/packages/bank/src/pages/home/index.tsx
+++ b/packages/bank/src/pages/home/index.tsx
@@ -1,5 +1,301 @@
-import { h } from "preact";
+import { h, Fragment } from "preact";
+import {useState} from "preact/hooks";
+import axios from "axios";
+
+/**********************************************
+ * Type definitions for states and API calls. *
+ *********************************************/
+
+/**
+ * Has the information to reach and
+ * authenticate at the bank's backend.
+ */
+interface BackendStateType {
+ url: string;
+ username: string | undefined;
+ password: string | undefined;
+}
+
+/**
+ * Request body of /register.
+ */
+interface RegistrationRequestType {
+ username: string;
+ password: string;
+}
+
+/**
+ * Track page state.
+ */
+interface PageStateType {
+ isLoggedIn: boolean;
+ hasProblem: boolean;
+}
+
+/**
+ * Bank account specific information.
+ */
+interface AccountStateType {
+ balance: string | undefined;
+ /* FIXME: Need history here. */
+
+ /**
+ * Error message to diplay when one of the
+ * account state entries failed to arrive.
+ */
+ error: string | undefined;
+}
+
+/*******************
+ * State managers. *
+ ******************/
+
+/**
+ * Return getters and setters for
+ * login credentials and backend's
+ * base URL.
+ */
+function useBackendState(
+ state: BackendStateType = {
+ url: window.location.href, // Should never change.
+ username: undefined,
+ password: undefined,
+}): [
+ BackendStateType,
+ (newState: BackendStateType) => void |
+ ((fn: (oldState: BackendStateType) => void) => void)
+] {
+ return useState<BackendStateType>(state);
+}
+
+function useAccountState<AccountStateType>(
+ state: AccountStateType = {
+ balance: undefined,
+ error: undefined
+}): [
+ AccountStateType, (fn: (state: AccountStateType) => void) => void
+] {
+ return useState<AccountStateType>(state);
+}
+
+function usePageState(
+ state: PageStateType = {
+ isLoggedIn: false,
+ hasProblem: false,
+}): [
+ PageStateType, (newState: PageStateType) => any |
+ ((fn: (state: PageStateType) => void) => void)
+] {
+ return useState<PageStateType>(state);
+}
+
+/************
+ * Helpers. *
+ ***********/
+
+async function post(url: string, data: any): Promise<number> {
+ // Mock 200 OK responses, at this moment.
+ return new Promise(
+ // (res, rej) => {setTimeout(() => {res(404);});}
+ (res, rej) => {setTimeout(() => {res(200);});}
+ );
+}
+
+async function get(url: string): Promise<number> {
+ // Mock 200 OK responses, at this moment.
+ return new Promise(
+ (res, rej) => {setTimeout(() => {res(404);});}
+ // (res, rej) => {setTimeout(() => {res(200);});}
+ );
+}
+
+/******************
+ * HTTP wrappers. *
+ *****************/
+
+/**
+ * Wrappers for HTTP requests specific to individual API calls.
+ * Each wrapper will (1) manage HTTP requests and responses,
+ * and (2) update the state accordingly.
+ *
+ * Their signature is:
+ * RequestType x ResponseType x use*State() => void
+ *
+ * For example, a 'wrap()' function can look like:
+ *
+ * wrap(url: string,
+ * req: WrapTypeReq,
+ * state: StateType // Will only have setters used.
+ * ) {
+ *
+ * let cb: (resp: WrapTypeRes) => void = {
+ * // implementation here.
+ * // ..
+ * state.setter(...)
+ * };
+ *
+ * post(url, req, (resp) => cb(resp))
+ * }
+ *
+ ***/
+
+
+/**
+ * This function requests GET /accounts/{account_name}.
+ *
+ * It's only a information retriever, without any effect
+ * on the state.
+ */
+async function accountInfoCall(
+ backendState: BackendStateType,
+ accountStateSetter: (fn: (state: AccountStateType) => void) => void
+) {
+ const url = new URL(`accounts/${backendState.username}`, backendState.url);
+ const handleResp = (respStatus: number) => {
+ switch (respStatus) {
+ case 200: {
+ accountStateSetter(state => ({...state, balance: "1 EUR"}));
+ break;
+ }
+ default: {
+ accountStateSetter(state => ({...state, error: "Missing
information."}));
+ }
+ }
+ };
+ const resp = await get(url)
+ handleResp(resp)
+}
+
+/**
+ * This function requests /register.
+ *
+ * This function is responsible to change two states:
+ * the backend's (to store the login credentials) and
+ * the page's (to indicate a successful login or a problem).
+ */
+async function registrationCall(
+ url: string,
+ req: RegistrationRequestType,
+ // On success, that will update the username and password to the state.
+ backendStateSetter: (fn: (state: BackendStateType) => void) => void,
+ // Communicate the request outcome to the page.
+ pageStateSetter: (fn: (state: PageStateType) => void) => void,
+) {
+ console.log("Try to register", req);
+ var handleResp = (respStatus: number) => {
+ switch (respStatus) {
+ case 200: {
+ pageStateSetter(state => ({...state, isLoggedIn: true}));
+ backendStateSetter(state => ({
+ ...state,
+ username: req.username,
+ password: req.password,
+ }));
+ break;
+ }
+ default: {
+ pageStateSetter(state => ({...state, hasProblem: true}));
+ }
+ }
+ }
+ var resp = await post(url, req);
+ handleResp(resp);
+}
+
+/**************************
+ * Functional components. *
+ *************************/
+
+/**
+ * Show only the account's balance.
+ */
+export function Account(props: {balance: string}) {
+ return <p>Your balance is {props.balance}</p>;
+}
+
+/**
+ * If the user is logged in, it displays
+ * the balance, otherwise it offers to login.
+ */
export function BankHome() {
- return <section class="section">hello bank</section>;
+ var [backendState, backendStateSetter] = useBackendState<BackendStateType>();
+ var [pageState, pageStateSetter] = usePageState<PageStateType>();
+ var [accountState, accountStateSetter] = useAccountState<AccountStateType>();
+
+ // Prepare/check registration request.
+ var registrationData: {}; // Untyped collector of user input.
+ let prepareRegistrationRequest = (): RegistrationRequestType => {
+
+ console.log("Preparing registration request", registrationData);
+ if (!("username" in registrationData)) {
+ pageStateSetter({...pageState, hasProblem: true});
+ return;
+ }
+ if (!("password" in registrationData)) {
+ pageStateSetter({...pageState, hasProblem: true});
+ return;
+ }
+ const u: string = registrationData["username"]
+ const p: string = registrationData["password"]
+ // Here, input is valid.
+ return {username: u, password: p};
+ }
+
+ if (pageState.hasProblem) {
+ return <p>Page has a problem.</p>;
+ }
+
+ if (pageState.isLoggedIn) {
+ if (typeof accountState.error !== "undefined") {
+ console.log(accountState);
+ return <p>The page could not load correctly: {accountState.error}</p>;
+ }
+ if (typeof accountState.balance === "undefined") {
+ // Need one: request and trigger new state!
+ accountInfoCall(backendState, accountStateSetter);
+ return;
+ }
+
+ return <Fragment>
+ <p>Welcome {backendState.username}!</p>
+ <Account balance={accountState.balance} />
+ </Fragment>;
+
+ /**
+ * FIXME: need to offer a Taler withdraw button here.
+ */
+
+ /**
+ * FIXME: need to offer the withdraw confirmation page,
+ * after the wallet has 'selected' an exchange and a reserve.
+ *
+ * The selection can be detected by asking the withdrawal
+ * status to the bank's backend.
+ */
+ }
+
+ // Proceede collecting registration data.
+ return <div>
+ <input type="text"
+ placeholder="username"
+ onInput={(e): void => {
+ registrationData = {...registrationData, username:
e.currentTarget.value};
+ }}
+ / >
+ <input type="text"
+ placeholder="password"
+ onInput={(e): void => {
+ registrationData = {...registrationData, password:
e.currentTarget.value};
+ }}
+ / >
+
+ <button
+ onClick={() => {registrationCall(
+ backendState.url,
+ prepareRegistrationRequest(),
+ backendStateSetter,
+ pageStateSetter,
+ )}}>Submit</button>
+ </div>
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-merchant-backoffice] branch master updated: Hello World euFin bank.,
gnunet <=