diff options
Diffstat (limited to 'packages')
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, }, |