aboutsummaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/hooks/circuit.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/demobank-ui/src/hooks/circuit.ts')
-rw-r--r--packages/demobank-ui/src/hooks/circuit.ts317
1 files changed, 317 insertions, 0 deletions
diff --git a/packages/demobank-ui/src/hooks/circuit.ts b/packages/demobank-ui/src/hooks/circuit.ts
new file mode 100644
index 000000000..6e9ada601
--- /dev/null
+++ b/packages/demobank-ui/src/hooks/circuit.ts
@@ -0,0 +1,317 @@
+/*
+ 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,
+ HttpResponse,
+ HttpResponseOk,
+ HttpResponsePaginated,
+ RequestError
+} from "@gnu-taler/web-util/lib/index.browser";
+import { useEffect, useMemo, useState } from "preact/hooks";
+import useSWR from "swr";
+import { useBackendContext } from "../context/backend.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils.js";
+import { useAuthenticatedBackend } from "./backend.js";
+
+export function useAdminAccountAPI(): AdminAccountAPI {
+ const { request } = useAuthenticatedBackend();
+ const { state } = useBackendContext()
+ if (state.status === "loggedOut") {
+ throw Error("access-api can't be used when the user is not logged In")
+ }
+
+ const createAccount = async (
+ data: SandboxBackend.Circuit.CircuitAccountRequest,
+ ): Promise<HttpResponseOk<void>> => {
+ const res = await request<void>(`circuit-api/accounts`, {
+ method: "POST",
+ data,
+ contentType: "json"
+ });
+ return res;
+ };
+
+ const updateAccount = async (
+ account: string,
+ data: SandboxBackend.Circuit.CircuitAccountReconfiguration,
+ ): Promise<HttpResponseOk<void>> => {
+ const res = await request<void>(`circuit-api/accounts/${account}`, {
+ method: "PATCH",
+ data,
+ contentType: "json"
+ });
+ return res;
+ };
+ const deleteAccount = async (
+ account: string,
+ ): Promise<HttpResponseOk<void>> => {
+ const res = await request<void>(`circuit-api/accounts/${account}`, {
+ method: "DELETE",
+ contentType: "json"
+ });
+ return res;
+ };
+ const changePassword = async (
+ account: string,
+ data: SandboxBackend.Circuit.AccountPasswordChange,
+ ): Promise<HttpResponseOk<void>> => {
+ const res = await request<void>(`circuit-api/accounts/${account}/auth`, {
+ method: "PATCH",
+ data,
+ contentType: "json"
+ });
+ return res;
+ };
+
+ return { createAccount, deleteAccount, updateAccount, changePassword };
+}
+
+export function useCircuitAccountAPI(): CircuitAccountAPI {
+ const { request } = useAuthenticatedBackend();
+ const { state } = useBackendContext()
+ if (state.status === "loggedOut") {
+ throw Error("access-api can't be used when the user is not logged In")
+ }
+ const account = state.username;
+
+ const updateAccount = async (
+ data: SandboxBackend.Circuit.CircuitAccountReconfiguration,
+ ): Promise<HttpResponseOk<void>> => {
+ const res = await request<void>(`circuit-api/accounts/${account}`, {
+ method: "PATCH",
+ data,
+ contentType: "json"
+ });
+ return res;
+ };
+ const changePassword = async (
+ data: SandboxBackend.Circuit.AccountPasswordChange,
+ ): Promise<HttpResponseOk<void>> => {
+ const res = await request<void>(`circuit-api/accounts/${account}/auth`, {
+ method: "PATCH",
+ data,
+ contentType: "json"
+ });
+ return res;
+ };
+
+ return { updateAccount, changePassword };
+}
+
+export interface AdminAccountAPI {
+ createAccount: (
+ data: SandboxBackend.Circuit.CircuitAccountRequest,
+ ) => Promise<HttpResponseOk<void>>;
+ deleteAccount: (account: string) => Promise<HttpResponseOk<void>>;
+
+ updateAccount: (
+ account: string,
+ data: SandboxBackend.Circuit.CircuitAccountReconfiguration
+ ) => Promise<HttpResponseOk<void>>;
+ changePassword: (
+ account: string,
+ data: SandboxBackend.Circuit.AccountPasswordChange
+ ) => Promise<HttpResponseOk<void>>;
+}
+
+export interface CircuitAccountAPI {
+ updateAccount: (
+ data: SandboxBackend.Circuit.CircuitAccountReconfiguration
+ ) => Promise<HttpResponseOk<void>>;
+ changePassword: (
+ data: SandboxBackend.Circuit.AccountPasswordChange
+ ) => Promise<HttpResponseOk<void>>;
+}
+
+
+export interface InstanceTemplateFilter {
+ //FIXME: add filter to the template list
+ position?: string;
+}
+
+
+export function useMyAccountDetails(): HttpResponse<SandboxBackend.Circuit.CircuitAccountData, SandboxBackend.SandboxError> {
+ const { fetcher } = useAuthenticatedBackend();
+ const { state } = useBackendContext()
+ if (state.status === "loggedOut") {
+ throw Error("can't access my-account-details when logged out")
+ }
+ const { data, error } = useSWR<
+ HttpResponseOk<SandboxBackend.Circuit.CircuitAccountData>,
+ HttpError<SandboxBackend.SandboxError>
+ >([`accounts/${state.username}`], fetcher, {
+ refreshInterval: 0,
+ refreshWhenHidden: false,
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false,
+ refreshWhenOffline: false,
+ errorRetryCount: 0,
+ errorRetryInterval: 1,
+ shouldRetryOnError: false,
+ keepPreviousData: true,
+ });
+
+ if (data) return data;
+ if (error) return error;
+ return { loading: true };
+}
+
+export function useAccountDetails(account: string): HttpResponse<SandboxBackend.Circuit.CircuitAccountData, SandboxBackend.SandboxError> {
+ const { fetcher } = useAuthenticatedBackend();
+
+ const { data, error } = useSWR<
+ HttpResponseOk<SandboxBackend.Circuit.CircuitAccountData>,
+ RequestError<SandboxBackend.SandboxError>
+ >([`circuit-api/accounts/${account}`], fetcher, {
+ refreshInterval: 0,
+ refreshWhenHidden: false,
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false,
+ refreshWhenOffline: false,
+ errorRetryCount: 0,
+ errorRetryInterval: 1,
+ shouldRetryOnError: false,
+ keepPreviousData: true,
+ });
+
+ // if (isValidating) return { loading: true, data: data?.data };
+ if (data) return data;
+ if (error) return error.info;
+ return { loading: true };
+}
+
+interface PaginationFilter {
+ account?: string,
+ page?: number,
+}
+
+export function useAccounts(
+ args?: PaginationFilter,
+): HttpResponsePaginated<SandboxBackend.Circuit.CircuitAccounts, SandboxBackend.SandboxError> {
+ const { sandboxAccountsFetcher } = useAuthenticatedBackend();
+ const [page, setPage] = useState(0);
+
+ const {
+ data: afterData,
+ error: afterError,
+ // isValidating: loadingAfter,
+ } = useSWR<
+ HttpResponseOk<SandboxBackend.Circuit.CircuitAccounts>,
+ RequestError<SandboxBackend.SandboxError>
+ >([`circuit-api/accounts`, args?.page, PAGE_SIZE, args?.account], sandboxAccountsFetcher, {
+ refreshInterval: 0,
+ refreshWhenHidden: false,
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false,
+ refreshWhenOffline: false,
+ errorRetryCount: 0,
+ errorRetryInterval: 1,
+ shouldRetryOnError: false,
+ keepPreviousData: true,
+ });
+
+ // const [lastAfter, setLastAfter] = useState<
+ // HttpResponse<SandboxBackend.Circuit.CircuitAccounts, SandboxBackend.SandboxError>
+ // >({ loading: true });
+
+ // useEffect(() => {
+ // if (afterData) setLastAfter(afterData);
+ // }, [afterData]);
+
+ // if the query returns less that we ask, then we have reach the end or beginning
+ const isReachingEnd =
+ afterData && afterData.data?.customers?.length < PAGE_SIZE;
+ const isReachingStart = false;
+
+ const pagination = {
+ isReachingEnd,
+ isReachingStart,
+ loadMore: () => {
+ if (!afterData || isReachingEnd) return;
+ if (afterData.data?.customers?.length < MAX_RESULT_SIZE) {
+ setPage(page + 1);
+ }
+ },
+ loadMorePrev: () => {
+ null
+ },
+ };
+
+ const result = useMemo(() => {
+ const customers = !afterData ? [] : (afterData)?.data?.customers ?? [];
+ return { ok: true as const, data: { customers }, ...pagination }
+ }, [afterData?.data])
+
+ if (afterError) return afterError.info;
+ if (afterData) {
+ return result
+ }
+
+ // if (loadingAfter)
+ // return { loading: true, data: { customers } };
+ // if (afterData) {
+ // return { ok: true, data: { customers }, ...pagination };
+ // }
+ return { loading: true };
+}
+
+export function useCashouts(): HttpResponse<
+ (SandboxBackend.Circuit.CashoutStatusResponse & WithId)[],
+ SandboxBackend.SandboxError
+> {
+ const { fetcher, multiFetcher } = useAuthenticatedBackend();
+
+ const { data: list, error: listError } = useSWR<
+ HttpResponseOk<SandboxBackend.Circuit.Cashouts>,
+ RequestError<SandboxBackend.SandboxError>
+ >([`circuit-api/cashouts`], fetcher, {
+ refreshInterval: 0,
+ refreshWhenHidden: false,
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false,
+ refreshWhenOffline: false,
+ });
+
+ const paths = (list?.data.cashouts || []).map(
+ (cashoutId) => `circuit-api/cashouts/${cashoutId}`,
+ );
+ const { data: cashouts, error: productError } = useSWR<
+ HttpResponseOk<SandboxBackend.Circuit.CashoutStatusResponse>[],
+ RequestError<SandboxBackend.SandboxError>
+ >([paths], multiFetcher, {
+ refreshInterval: 0,
+ refreshWhenHidden: false,
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false,
+ refreshWhenOffline: false,
+ });
+
+ if (listError) return listError.info;
+ if (productError) return productError.info;
+
+ if (cashouts) {
+ const dataWithId = cashouts.map((d) => {
+ //take the id from the queried url
+ return {
+ ...d.data,
+ id: d.info?.url.replace(/.*\/cashouts\//, "") || "",
+ };
+ });
+ return { ok: true, data: dataWithId };
+ }
+ return { loading: true };
+}