aboutsummaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/components/Cashouts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/demobank-ui/src/components/Cashouts')
-rw-r--r--packages/demobank-ui/src/components/Cashouts/index.ts69
-rw-r--r--packages/demobank-ui/src/components/Cashouts/state.ts44
-rw-r--r--packages/demobank-ui/src/components/Cashouts/stories.tsx45
-rw-r--r--packages/demobank-ui/src/components/Cashouts/test.ts179
-rw-r--r--packages/demobank-ui/src/components/Cashouts/views.tsx66
5 files changed, 403 insertions, 0 deletions
diff --git a/packages/demobank-ui/src/components/Cashouts/index.ts b/packages/demobank-ui/src/components/Cashouts/index.ts
new file mode 100644
index 000000000..db39ba7e4
--- /dev/null
+++ b/packages/demobank-ui/src/components/Cashouts/index.ts
@@ -0,0 +1,69 @@
+/*
+ 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 { HttpError, utils } from "@gnu-taler/web-util/lib/index.browser";
+import { Loading } from "../Loading.js";
+// import { compose, StateViewMap } from "../../utils/index.js";
+// import { wxApi } from "../../wxApi.js";
+import { AbsoluteTime, AmountJson } from "@gnu-taler/taler-util";
+import { useComponentState } from "./state.js";
+import { LoadingUriView, ReadyView } from "./views.js";
+
+export interface Props {
+ account: 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: HttpError<SandboxBackend.SandboxError>;
+ }
+
+ export interface BaseInfo {
+ error: undefined;
+ }
+ export interface Ready extends BaseInfo {
+ status: "ready";
+ error: undefined;
+ cashouts: SandboxBackend.Circuit.CashoutStatusResponse[];
+ }
+}
+
+export interface Transaction {
+ negative: boolean;
+ counterpart: string;
+ when: AbsoluteTime;
+ amount: AmountJson | undefined;
+ subject: string;
+}
+
+const viewMapping: utils.StateViewMap<State> = {
+ loading: Loading,
+ "loading-error": LoadingUriView,
+ ready: ReadyView,
+};
+
+export const Cashouts = utils.compose(
+ (p: Props) => useComponentState(p),
+ viewMapping,
+);
diff --git a/packages/demobank-ui/src/components/Cashouts/state.ts b/packages/demobank-ui/src/components/Cashouts/state.ts
new file mode 100644
index 000000000..7e420940f
--- /dev/null
+++ b/packages/demobank-ui/src/components/Cashouts/state.ts
@@ -0,0 +1,44 @@
+/*
+ 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 { useCashouts } from "../../hooks/circuit.js";
+import { Props, State, Transaction } from "./index.js";
+
+export function useComponentState({
+ account,
+}: Props): State {
+ const result = useCashouts()
+ if (result.loading) {
+ return {
+ status: "loading",
+ error: undefined
+ }
+ }
+ if (!result.ok) {
+ return {
+ status: "loading-error",
+ error: result
+ }
+ }
+
+
+ return {
+ status: "ready",
+ error: undefined,
+ cashout: result.data,
+ };
+}
diff --git a/packages/demobank-ui/src/components/Cashouts/stories.tsx b/packages/demobank-ui/src/components/Cashouts/stories.tsx
new file mode 100644
index 000000000..77fdde092
--- /dev/null
+++ b/packages/demobank-ui/src/components/Cashouts/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/Cashouts/test.ts b/packages/demobank-ui/src/components/Cashouts/test.ts
new file mode 100644
index 000000000..3f2d5fb68
--- /dev/null
+++ b/packages/demobank-ui/src/components/Cashouts/test.ts
@@ -0,0 +1,179 @@
+/*
+ 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 = {
+ account: "myAccount",
+ };
+
+ 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 = {
+ account: "myAccount",
+ };
+
+ 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 = {
+ account: "myAccount",
+ };
+
+ 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/Cashouts/views.tsx b/packages/demobank-ui/src/components/Cashouts/views.tsx
new file mode 100644
index 000000000..30803d4d1
--- /dev/null
+++ b/packages/demobank-ui/src/components/Cashouts/views.tsx
@@ -0,0 +1,66 @@
+/*
+ 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({ cashouts }: State.Ready): VNode {
+ const { i18n } = useTranslationContext();
+ return (
+ <div class="results">
+ <table class="pure-table pure-table-striped">
+ <thead>
+ <tr>
+ <th>{i18n.str`Created`}</th>
+ <th>{i18n.str`Confirmed`}</th>
+ <th>{i18n.str`Counterpart`}</th>
+ <th>{i18n.str`Subject`}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {cashouts.map((item, idx) => {
+ return (
+ <tr key={idx}>
+ <td>{format(item.creation_time, "dd/MM/yyyy HH:mm:ss")}</td>
+ <td>
+ {item.confirmation_time
+ ? format(item.confirmation_time, "dd/MM/yyyy HH:mm:ss")
+ : "-"}
+ </td>
+ <td>{Amounts.stringifyValue(item.amount_credit)}</td>
+ <td>{item.counterpart}</td>
+ <td>{item.subject}</td>
+ </tr>
+ );
+ })}
+ </tbody>
+ </table>
+ </div>
+ );
+}