aboutsummaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-12-14 15:35:28 -0300
committerSebastian <sebasjm@gmail.com>2022-12-14 15:35:28 -0300
commit8d8d71807df6b775e5b0335eb1b2526a56d42ac6 (patch)
tree6b4a15698e8119d66995ead2e7e69e2fb8938450 /packages
parentd0dd7a155fcb63dc4d4859f51a681fc084ec4d7a (diff)
refactoring transaction component to standard component with test and examples
Diffstat (limited to 'packages')
-rwxr-xr-xpackages/demobank-ui/build.mjs25
-rw-r--r--packages/demobank-ui/src/components/EmptyComponentExample/index.ts13
-rw-r--r--packages/demobank-ui/src/components/EmptyComponentExample/state.ts4
-rw-r--r--packages/demobank-ui/src/components/EmptyComponentExample/stories.tsx4
-rw-r--r--packages/demobank-ui/src/components/EmptyComponentExample/views.tsx10
-rw-r--r--packages/demobank-ui/src/components/Transactions/index.ts71
-rw-r--r--packages/demobank-ui/src/components/Transactions/state.ts133
-rw-r--r--packages/demobank-ui/src/components/Transactions/stories.tsx45
-rw-r--r--packages/demobank-ui/src/components/Transactions/test.ts174
-rw-r--r--packages/demobank-ui/src/components/Transactions/views.tsx68
-rw-r--r--packages/demobank-ui/src/components/index.examples.ts17
-rw-r--r--packages/demobank-ui/src/endpoints.ts37
-rw-r--r--packages/demobank-ui/src/pages/AccountPage.tsx2
-rw-r--r--packages/demobank-ui/src/pages/PublicHistoriesPage.tsx2
-rw-r--r--packages/demobank-ui/src/pages/Transactions.tsx106
-rw-r--r--packages/demobank-ui/src/stories.tsx3
16 files changed, 587 insertions, 127 deletions
diff --git a/packages/demobank-ui/build.mjs b/packages/demobank-ui/build.mjs
index c93b4eb67..f30fe5490 100755
--- a/packages/demobank-ui/build.mjs
+++ b/packages/demobank-ui/build.mjs
@@ -44,7 +44,29 @@ const preactCompatPlugin = {
},
};
-const entryPoints = ["src/index.tsx", "src/stories.tsx"];
+function getFilesInDirectory(startPath, regex) {
+ if (!fs.existsSync(startPath)) {
+ return;
+ }
+ const files = fs.readdirSync(startPath);
+ const result = files.flatMap(file => {
+ const filename = path.join(startPath, file);
+
+ const stat = fs.lstatSync(filename);
+ if (stat.isDirectory()) {
+ return getFilesInDirectory(filename, regex);
+ }
+ else if (regex.test(filename)) {
+ return filename
+ }
+ }).filter(x => !!x)
+
+ return result
+}
+
+const allTestFiles = getFilesInDirectory(path.join(BASE, 'src'), /.test.ts$/)
+
+const entryPoints = ["src/index.tsx", "src/stories.tsx", ...allTestFiles];
let GIT_ROOT = BASE;
while (!fs.existsSync(path.join(GIT_ROOT, ".git")) && GIT_ROOT !== "/") {
@@ -128,6 +150,7 @@ export const buildConfig = {
sourcemap: true,
jsxFactory: "h",
jsxFragment: "Fragment",
+ external: ["async_hooks"],
define: {
__VERSION__: `"${_package.version}"`,
__GIT_HASH__: `"${GIT_HASH}"`,
diff --git a/packages/demobank-ui/src/components/EmptyComponentExample/index.ts b/packages/demobank-ui/src/components/EmptyComponentExample/index.ts
index 4b7725264..d9f231019 100644
--- a/packages/demobank-ui/src/components/EmptyComponentExample/index.ts
+++ b/packages/demobank-ui/src/components/EmptyComponentExample/index.ts
@@ -15,9 +15,9 @@
*/
import { Loading } from "../../components/Loading.js";
-import { HookError } from "../../hooks/useAsyncAsHook.js";
-import { compose, StateViewMap } from "../../utils/index.js";
-import { wxApi } from "../../wxApi.js";
+import { HookError, utils } from "@gnu-taler/web-util/lib/index.browser";
+//import { compose, StateViewMap } from "../../utils/index.js";
+//import { wxApi } from "../../wxApi.js";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
@@ -47,14 +47,13 @@ export namespace State {
}
}
-const viewMapping: StateViewMap<State> = {
+const viewMapping: utils.StateViewMap<State> = {
loading: Loading,
"loading-error": LoadingUriView,
ready: ReadyView,
};
-export const ComponentName = compose(
- "ComponentName",
- (p: Props) => useComponentState(p, wxApi),
+export const ComponentName = utils.compose(
+ (p: Props) => useComponentState(p),
viewMapping,
);
diff --git a/packages/demobank-ui/src/components/EmptyComponentExample/state.ts b/packages/demobank-ui/src/components/EmptyComponentExample/state.ts
index d194b3f97..e147a7ccf 100644
--- a/packages/demobank-ui/src/components/EmptyComponentExample/state.ts
+++ b/packages/demobank-ui/src/components/EmptyComponentExample/state.ts
@@ -14,10 +14,10 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { wxApi } from "../../wxApi.js";
+// import { wxApi } from "../../wxApi.js";
import { Props, State } from "./index.js";
-export function useComponentState({ p }: Props, api: typeof wxApi): State {
+export function useComponentState({ p }: Props): State {
return {
status: "ready",
error: undefined,
diff --git a/packages/demobank-ui/src/components/EmptyComponentExample/stories.tsx b/packages/demobank-ui/src/components/EmptyComponentExample/stories.tsx
index 696e424c4..e157e6e6f 100644
--- a/packages/demobank-ui/src/components/EmptyComponentExample/stories.tsx
+++ b/packages/demobank-ui/src/components/EmptyComponentExample/stories.tsx
@@ -19,11 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { createExample } from "../../test-utils.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
import { ReadyView } from "./views.js";
export default {
title: "example",
};
-export const Ready = createExample(ReadyView, {});
+export const Ready = tests.createExample(ReadyView, {});
diff --git a/packages/demobank-ui/src/components/EmptyComponentExample/views.tsx b/packages/demobank-ui/src/components/EmptyComponentExample/views.tsx
index 5784a7db5..e125ff415 100644
--- a/packages/demobank-ui/src/components/EmptyComponentExample/views.tsx
+++ b/packages/demobank-ui/src/components/EmptyComponentExample/views.tsx
@@ -15,18 +15,16 @@
*/
import { h, VNode } from "preact";
-import { LoadingError } from "../../components/LoadingError.js";
-import { useTranslationContext } from "../../context/translation.js";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { State } from "./index.js";
export function LoadingUriView({ error }: State.LoadingUriError): VNode {
const { i18n } = useTranslationContext();
return (
- <LoadingError
- title={<i18n.Translate>Could not load</i18n.Translate>}
- error={error}
- />
+ <div>
+ <i18n.Translate>Could not load</i18n.Translate>
+ </div>
);
}
diff --git a/packages/demobank-ui/src/components/Transactions/index.ts b/packages/demobank-ui/src/components/Transactions/index.ts
new file mode 100644
index 000000000..618fcfb71
--- /dev/null
+++ b/packages/demobank-ui/src/components/Transactions/index.ts
@@ -0,0 +1,71 @@
+/*
+ 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 { Loading } from "../Loading.js";
+import { HookError, utils } from "@gnu-taler/web-util/lib/index.browser";
+// import { compose, StateViewMap } from "../../utils/index.js";
+// import { wxApi } from "../../wxApi.js";
+import { useComponentState } from "./state.js";
+import { LoadingUriView, ReadyView } from "./views.js";
+import { AbsoluteTime, AmountJson } from "@gnu-taler/taler-util";
+
+export interface Props {
+ pageNumber: number;
+ accountLabel: string;
+ balanceValue?: string;
+}
+
+export type State = State.Loading | State.LoadingUriError | State.Ready;
+
+export namespace State {
+ export interface Loading {
+ status: "loading";
+ error: undefined;
+ }
+
+ export interface LoadingUriError {
+ status: "loading-error";
+ error: HookError;
+ }
+
+ export interface BaseInfo {
+ error: undefined;
+ }
+ export interface Ready extends BaseInfo {
+ status: "ready";
+ error: undefined;
+ transactions: Transaction[];
+ }
+}
+
+export interface Transaction {
+ negative: boolean;
+ counterpart: string;
+ when: AbsoluteTime;
+ amount: AmountJson;
+ subject: string;
+}
+
+const viewMapping: utils.StateViewMap<State> = {
+ loading: Loading,
+ "loading-error": LoadingUriView,
+ ready: ReadyView,
+};
+
+export const Transactions = utils.compose(
+ (p: Props) => useComponentState(p),
+ viewMapping,
+);
diff --git a/packages/demobank-ui/src/components/Transactions/state.ts b/packages/demobank-ui/src/components/Transactions/state.ts
new file mode 100644
index 000000000..ac76e31e2
--- /dev/null
+++ b/packages/demobank-ui/src/components/Transactions/state.ts
@@ -0,0 +1,133 @@
+/*
+ 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 { AbsoluteTime, Amounts } from "@gnu-taler/taler-util";
+import { parse } from "date-fns";
+import { useEffect } from "preact/hooks";
+import useSWR from "swr";
+import { Props, State } from "./index.js";
+
+export function useComponentState({ accountLabel, pageNumber, balanceValue }: Props): State {
+ const { data, error, mutate } = useSWR(
+ `access-api/accounts/${accountLabel}/transactions?page=${pageNumber}`,
+ );
+
+ useEffect(() => {
+ if (balanceValue) {
+ mutate();
+ }
+ }, [balanceValue ?? ""]);
+
+ if (error) {
+ switch (error.status) {
+ case 404:
+ return {
+ status: "loading-error",
+ error: {
+ hasError: true,
+ operational: false,
+ message: `Transactions page ${pageNumber} was not found.`
+ }
+ }
+ case 401:
+ return {
+ status: "loading-error",
+ error: {
+ hasError: true,
+ operational: false,
+ message: "Wrong credentials given."
+ }
+ }
+ default:
+ return {
+ status: "loading-error",
+ error: {
+ hasError: true,
+ operational: false,
+ message: `Transaction page ${pageNumber} could not be retrieved.`
+ } as any
+ }
+ }
+ }
+
+ if (!data) {
+ return {
+ status: "loading",
+ error: undefined
+ }
+ }
+
+
+ const transactions = data.transactions.map((item: unknown) => {
+ if (!item || typeof item !== "object" ||
+ !("direction" in item) ||
+ !("creditorIban" in item) ||
+ !("debtorIban" in item) ||
+ !("date" in item) ||
+ !("subject" in item) ||
+ !("currency" in item) ||
+ !("amount" in item)
+ ) {
+ //not valid
+ return;
+ }
+ const anyItem = item as any;
+ if (
+ !(typeof anyItem.creditorIban === 'string') ||
+ !(typeof anyItem.debtorIban === 'string') ||
+ !(typeof anyItem.date === 'string') ||
+ !(typeof anyItem.subject === 'string') ||
+ !(typeof anyItem.currency === 'string') ||
+ !(typeof anyItem.amount === 'string')
+ ) {
+ return;
+ }
+
+ const negative = anyItem.direction === "DBIT";
+ const counterpart = negative ? anyItem.creditorIban : anyItem.debtorIban;
+ // Pattern:
+ //
+ // DD/MM YYYY subject -5 EUR
+ // DD/MM YYYY subject 5 EUR
+ const dateRegex = /^([0-9]{4})-([0-9]{2})-([0-9]{1,2})/;
+ const dateParse = dateRegex.exec(anyItem.date);
+ const dateStr =
+ dateParse !== null
+ ? `${dateParse[3]}/${dateParse[2]} ${dateParse[1]}`
+ : undefined;
+
+ const date = parse(dateStr ?? "", "dd/MM yyyy", new Date())
+
+ const when: AbsoluteTime = {
+ t_ms: date.getTime()
+ }
+ const amount = Amounts.parseOrThrow(`${anyItem.currency}:${anyItem.amount}`);
+ const subject = anyItem.subject;
+ return {
+ negative,
+ counterpart,
+ when,
+ amount,
+ subject,
+ }
+ });
+
+ return {
+ status: "ready",
+ error: undefined,
+ transactions,
+ };
+}
diff --git a/packages/demobank-ui/src/components/Transactions/stories.tsx b/packages/demobank-ui/src/components/Transactions/stories.tsx
new file mode 100644
index 000000000..77fdde092
--- /dev/null
+++ b/packages/demobank-ui/src/components/Transactions/stories.tsx
@@ -0,0 +1,45 @@
+/*
+ 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/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { ReadyView } from "./views.js";
+
+export default {
+ title: "transaction list",
+};
+
+export const Ready = tests.createExample(ReadyView, {
+ transactions: [
+ {
+ amount: {
+ currency: "USD",
+ fraction: 0,
+ value: 1,
+ },
+ counterpart: "ASD",
+ negative: false,
+ subject: "Some",
+ when: {
+ t_ms: new Date().getTime(),
+ },
+ },
+ ],
+});
diff --git a/packages/demobank-ui/src/components/Transactions/test.ts b/packages/demobank-ui/src/components/Transactions/test.ts
new file mode 100644
index 000000000..b746f6bb7
--- /dev/null
+++ b/packages/demobank-ui/src/components/Transactions/test.ts
@@ -0,0 +1,174 @@
+/*
+ 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/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { SwrMockEnvironment } from "@gnu-taler/web-util/lib/tests/swr";
+import { expect } from "chai";
+import { TRANSACTION_API_EXAMPLE } from "../../endpoints.js";
+import { Props } from "./index.js";
+import { useComponentState } from "./state.js";
+
+
+describe("Transaction states", () => {
+
+ it("should query backend and render transactions", async () => {
+
+ const env = new SwrMockEnvironment();
+
+ const props: Props = {
+ accountLabel: "myAccount",
+ pageNumber: 0
+ }
+
+ env.addRequestExpectation(TRANSACTION_API_EXAMPLE.LIST_FIRST_PAGE, {
+ response: {
+ "transactions": [
+ {
+ "creditorIban": "DE159593",
+ "creditorBic": "SANDBOXX",
+ "creditorName": "exchange company",
+ "debtorIban": "DE118695",
+ "debtorBic": "SANDBOXX",
+ "debtorName": "Name unknown",
+ "amount": "1",
+ "currency": "KUDOS",
+ "subject": "Taler Withdrawal N588V8XE9TR49HKAXFQ20P0EQ0EYW2AC9NNANV8ZP5P59N6N0410",
+ "date": "2022-12-12Z",
+ "uid": "8PPFR9EM",
+ "direction": "DBIT",
+ "pmtInfId": null,
+ "msgId": null
+ },
+ {
+ "creditorIban": "DE159593",
+ "creditorBic": "SANDBOXX",
+ "creditorName": "exchange company",
+ "debtorIban": "DE118695",
+ "debtorBic": "SANDBOXX",
+ "debtorName": "Name unknown",
+ "amount": "5.00",
+ "currency": "KUDOS",
+ "subject": "HNEWWT679TQC5P1BVXJS48FX9NW18FWM6PTK2N80Z8GVT0ACGNK0",
+ "date": "2022-12-07Z",
+ "uid": "7FZJC3RJ",
+ "direction": "DBIT",
+ "pmtInfId": null,
+ "msgId": null
+ },
+ {
+ "creditorIban": "DE118695",
+ "creditorBic": "SANDBOXX",
+ "creditorName": "Name unknown",
+ "debtorIban": "DE579516",
+ "debtorBic": "SANDBOXX",
+ "debtorName": "The Bank",
+ "amount": "100",
+ "currency": "KUDOS",
+ "subject": "Sign-up bonus",
+ "date": "2022-12-07Z",
+ "uid": "I31A06J8",
+ "direction": "CRDT",
+ "pmtInfId": null,
+ "msgId": null
+ }
+ ]
+ }
+ });
+
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ ({ status, error }) => {
+
+ expect(status).equals("ready");
+ expect(error).undefined;
+ },
+ ], env.buildTestingContext())
+
+ expect(hookBehavior).deep.eq({ result: "ok" })
+
+ expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" })
+ });
+
+ it("should show error message on not found", async () => {
+
+ const env = new SwrMockEnvironment();
+
+ const props: Props = {
+ accountLabel: "myAccount",
+ pageNumber: 0
+ }
+
+ env.addRequestExpectation(TRANSACTION_API_EXAMPLE.LIST_NOT_FOUND, {});
+
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ ({ status, error }) => {
+ expect(status).equals("loading-error");
+ expect(error).deep.eq({
+ hasError: true,
+ operational: false,
+ message: "Transactions page 0 was not found."
+ });
+ },
+ ], env.buildTestingContext())
+
+ expect(hookBehavior).deep.eq({ result: "ok" })
+ expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" })
+ });
+
+ it("should show error message on server error", async () => {
+
+ const env = new SwrMockEnvironment(false);
+
+ const props: Props = {
+ accountLabel: "myAccount",
+ pageNumber: 0
+ }
+
+ env.addRequestExpectation(TRANSACTION_API_EXAMPLE.LIST_ERROR, {});
+
+ const hookBehavior = await tests.hookBehaveLikeThis(useComponentState, props, [
+ ({ status, error }) => {
+ expect(status).equals("loading");
+ expect(error).undefined;
+ },
+ ({ status, error }) => {
+ expect(status).equals("loading-error");
+ expect(error).deep.equal({
+ hasError: true,
+ operational: false,
+ message: "Transaction page 0 could not be retrieved."
+ });
+ },
+ ], env.buildTestingContext())
+
+ expect(hookBehavior).deep.eq({ result: "ok" })
+ expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" })
+ });
+});
+
diff --git a/packages/demobank-ui/src/components/Transactions/views.tsx b/packages/demobank-ui/src/components/Transactions/views.tsx
new file mode 100644
index 000000000..b3683b743
--- /dev/null
+++ b/packages/demobank-ui/src/components/Transactions/views.tsx
@@ -0,0 +1,68 @@
+/*
+ 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 { h, VNode } from "preact";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { State } from "./index.js";
+import { format } from "date-fns";
+import { Amounts } from "@gnu-taler/taler-util";
+
+export function LoadingUriView({ error }: State.LoadingUriError): VNode {
+ const { i18n } = useTranslationContext();
+
+ return (
+ <div>
+ <i18n.Translate>Could not load</i18n.Translate>
+ </div>
+ );
+}
+
+export function ReadyView({ transactions }: State.Ready): VNode {
+ const { i18n } = useTranslationContext();
+ return (
+ <div class="results">
+ <table class="pure-table pure-table-striped">
+ <thead>
+ <tr>
+ <th>{i18n.str`Date`}</th>
+ <th>{i18n.str`Amount`}</th>
+ <th>{i18n.str`Counterpart`}</th>
+ <th>{i18n.str`Subject`}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {transactions.map((item, idx) => {
+ return (
+ <tr key={idx}>
+ <td>
+ {item.when.t_ms === "never"
+ ? "never"
+ : format(item.when.t_ms, "dd/MM/yyyy")}
+ </td>
+ <td>
+ {item.negative ? "-" : ""}
+ {Amounts.stringifyValue(item.amount)} {item.amount.currency}
+ </td>
+ <td>{item.counterpart}</td>
+ <td>{item.subject}</td>
+ </tr>
+ );
+ })}
+ </tbody>
+ </table>
+ </div>
+ );
+}
diff --git a/packages/demobank-ui/src/components/index.examples.ts b/packages/demobank-ui/src/components/index.examples.ts
new file mode 100644
index 000000000..a741b413d
--- /dev/null
+++ b/packages/demobank-ui/src/components/index.examples.ts
@@ -0,0 +1,17 @@
+/*
+ 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/>
+ */
+
+export * as tx from "./Transactions/stories.js"; \ No newline at end of file
diff --git a/packages/demobank-ui/src/endpoints.ts b/packages/demobank-ui/src/endpoints.ts
new file mode 100644
index 000000000..0130e94f8
--- /dev/null
+++ b/packages/demobank-ui/src/endpoints.ts
@@ -0,0 +1,37 @@
+/*
+ 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/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+export const TRANSACTION_API_EXAMPLE = {
+ LIST_FIRST_PAGE: {
+ method: "get" as const,
+ url: "access-api/accounts/myAccount/transactions?page=0",
+ },
+ LIST_ERROR: {
+ method: "get" as const,
+ url: "access-api/accounts/myAccount/transactions?page=0",
+ code: 500
+ },
+ LIST_NOT_FOUND: {
+ method: "get" as const,
+ url: "access-api/accounts/myAccount/transactions?page=0",
+ code: 404
+ }
+} \ No newline at end of file
diff --git a/packages/demobank-ui/src/pages/AccountPage.tsx b/packages/demobank-ui/src/pages/AccountPage.tsx
index 7ec4d36fb..5dd820b53 100644
--- a/packages/demobank-ui/src/pages/AccountPage.tsx
+++ b/packages/demobank-ui/src/pages/AccountPage.tsx
@@ -27,7 +27,7 @@ import { getIbanFromPayto, prepareHeaders } from "../utils.js";
import { BankFrame } from "./BankFrame.js";
import { LoginForm } from "./LoginForm.js";
import { PaymentOptions } from "./PaymentOptions.js";
-import { Transactions } from "./Transactions.js";
+import { Transactions } from "../components/Transactions/index.js";
import { WithdrawalQRCode } from "./WithdrawalQRCode.js";
export function AccountPage(): VNode {
diff --git a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
index be9f4aee1..7bf5c41c7 100644
--- a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
+++ b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
@@ -24,7 +24,7 @@ import { PageStateType, usePageContext } from "../context/pageState.js";
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { getBankBackendBaseUrl } from "../utils.js";
import { BankFrame } from "./BankFrame.js";
-import { Transactions } from "./Transactions.js";
+import { Transactions } from "../components/Transactions/index.js";
const logger = new Logger("PublicHistoriesPage");
diff --git a/packages/demobank-ui/src/pages/Transactions.tsx b/packages/demobank-ui/src/pages/Transactions.tsx
deleted file mode 100644
index ca88abd4d..000000000
--- a/packages/demobank-ui/src/pages/Transactions.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- 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 { h, VNode } from "preact";
-import { useEffect } from "preact/hooks";
-import useSWR from "swr";
-import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
-
-const logger = new Logger("Transactions");
-/**
- * Show one page of transactions.
- */
-export function Transactions({
- pageNumber,
- accountLabel,
- balanceValue,
-}: {
- pageNumber: number;
- accountLabel: string;
- balanceValue?: string;
-}): VNode {
- const { i18n } = useTranslationContext();
- const { data, error, mutate } = useSWR(
- `access-api/accounts/${accountLabel}/transactions?page=${pageNumber}`,
- );
- useEffect(() => {
- if (balanceValue) {
- mutate();
- }
- }, [balanceValue ?? ""]);
- if (typeof error !== "undefined") {
- logger.error("transactions not found error", error);
- switch (error.status) {
- case 404: {
- return <p>Transactions page {pageNumber} was not found.</p>;
- }
- case 401: {
- return <p>Wrong credentials given.</p>;
- }
- default: {
- return <p>Transaction page {pageNumber} could not be retrieved.</p>;
- }
- }
- }
- if (!data) {
- logger.trace(`History data of ${accountLabel} not arrived`);
- return <p>Transactions page loading...</p>;
- }
- logger.trace(`History data of ${accountLabel}`, data);
- return (
- <div class="results">
- <table class="pure-table pure-table-striped">
- <thead>
- <tr>
- <th>{i18n.str`Date`}</th>
- <th>{i18n.str`Amount`}</th>
- <th>{i18n.str`Counterpart`}</th>
- <th>{i18n.str`Subject`}</th>
- </tr>
- </thead>
- <tbody>
- {data.transactions.map((item: any, idx: number) => {
- const sign = item.direction == "DBIT" ? "-" : "";
- const counterpart =
- item.direction == "DBIT" ? item.creditorIban : item.debtorIban;
- // Pattern:
- //
- // DD/MM YYYY subject -5 EUR
- // DD/MM YYYY subject 5 EUR
- const dateRegex = /^([0-9]{4})-([0-9]{2})-([0-9]{1,2})/;
- const dateParse = dateRegex.exec(item.date);
- const date =
- dateParse !== null
- ? `${dateParse[3]}/${dateParse[2]} ${dateParse[1]}`
- : "date not found";
- return (
- <tr key={idx}>
- <td>{date}</td>
- <td>
- {sign}
- {item.amount} {item.currency}
- </td>
- <td>{counterpart}</td>
- <td>{item.subject}</td>
- </tr>
- );
- })}
- </tbody>
- </table>
- </div>
- );
-}
diff --git a/packages/demobank-ui/src/stories.tsx b/packages/demobank-ui/src/stories.tsx
index 611d63879..a8ebcd867 100644
--- a/packages/demobank-ui/src/stories.tsx
+++ b/packages/demobank-ui/src/stories.tsx
@@ -21,6 +21,7 @@
import { strings } from "./i18n/strings.js";
import * as pages from "./pages/index.stories.js";
+import * as components from "./components/index.examples.js";
import { renderStories } from "@gnu-taler/web-util/lib/index.browser";
@@ -32,7 +33,7 @@ function SortStories(a: any, b: any): number {
function main(): void {
renderStories(
- { pages },
+ { pages, components },
{
strings,
},