diff options
| author | Sebastian <sebasjm@gmail.com> | 2023-02-10 09:51:37 -0300 | 
|---|---|---|
| committer | Sebastian <sebasjm@gmail.com> | 2023-02-10 09:52:02 -0300 | 
| commit | ba8b40c9150586982e42e76d364d76202627bd6f (patch) | |
| tree | ebeed7551aad62a03954945de72320b6c1bc1f01 /packages/demobank-ui/src/hooks | |
| parent | 53af8b486fd8a538c1f54a2ce66ed5f74b2b46ed (diff) | |
business account
Diffstat (limited to 'packages/demobank-ui/src/hooks')
| -rw-r--r-- | packages/demobank-ui/src/hooks/access.ts | 210 | ||||
| -rw-r--r-- | packages/demobank-ui/src/hooks/backend.ts | 125 | ||||
| -rw-r--r-- | packages/demobank-ui/src/hooks/circuit.ts | 151 | 
3 files changed, 309 insertions, 177 deletions
diff --git a/packages/demobank-ui/src/hooks/access.ts b/packages/demobank-ui/src/hooks/access.ts index 4d4574dac..9c162acfe 100644 --- a/packages/demobank-ui/src/hooks/access.ts +++ b/packages/demobank-ui/src/hooks/access.ts @@ -14,91 +14,113 @@   GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>   */ -import useSWR from "swr"; -import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils.js"; -import { useEffect, useState } from "preact/hooks";  import { -  HttpError,    HttpResponse,    HttpResponseOk,    HttpResponsePaginated, +  RequestError,  } from "@gnu-taler/web-util/lib/index.browser"; -import { useAuthenticatedBackend, useMatchMutate, usePublicBackend } from "./backend.js"; +import { useEffect, 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, +  useMatchMutate, +  usePublicBackend, +} from "./backend.js";  export function useAccessAPI(): AccessAPI {    const mutateAll = useMatchMutate();    const { request } = useAuthenticatedBackend(); -  const { state } = useBackendContext() +  const { state } = useBackendContext();    if (state.status === "loggedOut") { -    throw Error("access-api can't be used when the user is not logged In") +    throw Error("access-api can't be used when the user is not logged In");    } -  const account = state.username +  const account = state.username;    const createWithdrawal = async (      data: SandboxBackend.Access.BankAccountCreateWithdrawalRequest, -  ): Promise<HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>> => { -    const res = await request<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>(`access-api/accounts/${account}/withdrawals`, { -      method: "POST", -      data, -      contentType: "json" -    }); +  ): Promise< +    HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse> +  > => { +    const res = +      await request<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>( +        `access-api/accounts/${account}/withdrawals`, +        { +          method: "POST", +          data, +          contentType: "json", +        }, +      );      return res;    }; -  const abortWithdrawal = async ( -    id: string, -  ): Promise<HttpResponseOk<void>> => { -    const res = await request<void>(`access-api/accounts/${account}/withdrawals/${id}`, { -      method: "POST", -      contentType: "json" -    }); +  const abortWithdrawal = async (id: string): Promise<HttpResponseOk<void>> => { +    const res = await request<void>( +      `access-api/accounts/${account}/withdrawals/${id}`, +      { +        method: "POST", +        contentType: "json", +      }, +    );      await mutateAll(/.*accounts\/.*\/withdrawals\/.*/);      return res;    };    const confirmWithdrawal = async (      id: string,    ): Promise<HttpResponseOk<void>> => { -    const res = await request<void>(`access-api/accounts/${account}/withdrawals/${id}`, { -      method: "POST", -      contentType: "json" -    }); +    const res = await request<void>( +      `access-api/accounts/${account}/withdrawals/${id}`, +      { +        method: "POST", +        contentType: "json", +      }, +    );      await mutateAll(/.*accounts\/.*\/withdrawals\/.*/);      return res;    };    const createTransaction = async ( -    data: SandboxBackend.Access.CreateBankAccountTransactionCreate +    data: SandboxBackend.Access.CreateBankAccountTransactionCreate,    ): Promise<HttpResponseOk<void>> => { -    const res = await request<void>(`access-api/accounts/${account}/transactions`, { -      method: "POST", -      data, -      contentType: "json" -    }); +    const res = await request<void>( +      `access-api/accounts/${account}/transactions`, +      { +        method: "POST", +        data, +        contentType: "json", +      }, +    );      await mutateAll(/.*accounts\/.*\/transactions.*/);      return res;    }; -  const deleteAccount = async ( -  ): Promise<HttpResponseOk<void>> => { +  const deleteAccount = async (): Promise<HttpResponseOk<void>> => {      const res = await request<void>(`access-api/accounts/${account}`, {        method: "DELETE", -      contentType: "json" +      contentType: "json",      });      await mutateAll(/.*accounts\/.*/);      return res;    }; -  return { abortWithdrawal, confirmWithdrawal, createWithdrawal, createTransaction, deleteAccount }; +  return { +    abortWithdrawal, +    confirmWithdrawal, +    createWithdrawal, +    createTransaction, +    deleteAccount, +  };  }  export function useTestingAPI(): TestingAPI {    const mutateAll = useMatchMutate();    const { request: noAuthRequest } = usePublicBackend();    const register = async ( -    data: SandboxBackend.Access.BankRegistrationRequest +    data: SandboxBackend.Access.BankRegistrationRequest,    ): Promise<HttpResponseOk<void>> => {      const res = await noAuthRequest<void>(`access-api/testing/register`, {        method: "POST",        data, -      contentType: "json" +      contentType: "json",      });      await mutateAll(/.*accounts\/.*/);      return res; @@ -107,25 +129,22 @@ export function useTestingAPI(): TestingAPI {    return { register };  } -  export interface TestingAPI {    register: ( -    data: SandboxBackend.Access.BankRegistrationRequest +    data: SandboxBackend.Access.BankRegistrationRequest,    ) => Promise<HttpResponseOk<void>>;  }  export interface AccessAPI {    createWithdrawal: (      data: SandboxBackend.Access.BankAccountCreateWithdrawalRequest, -  ) => Promise<HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>>; -  abortWithdrawal: ( -    wid: string, -  ) => Promise<HttpResponseOk<void>>; -  confirmWithdrawal: ( -    wid: string -  ) => Promise<HttpResponseOk<void>>; +  ) => Promise< +    HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse> +  >; +  abortWithdrawal: (wid: string) => Promise<HttpResponseOk<void>>; +  confirmWithdrawal: (wid: string) => Promise<HttpResponseOk<void>>;    createTransaction: ( -    data: SandboxBackend.Access.CreateBankAccountTransactionCreate +    data: SandboxBackend.Access.CreateBankAccountTransactionCreate,    ) => Promise<HttpResponseOk<void>>;    deleteAccount: () => Promise<HttpResponseOk<void>>;  } @@ -135,13 +154,17 @@ export interface InstanceTemplateFilter {    position?: string;  } - -export function useAccountDetails(account: string): HttpResponse<SandboxBackend.Access.BankAccountBalanceResponse, SandboxBackend.SandboxError> { +export function useAccountDetails( +  account: string, +): HttpResponse< +  SandboxBackend.Access.BankAccountBalanceResponse, +  SandboxBackend.SandboxError +> {    const { fetcher } = useAuthenticatedBackend();    const { data, error } = useSWR<      HttpResponseOk<SandboxBackend.Access.BankAccountBalanceResponse>, -    HttpError<SandboxBackend.SandboxError> +    RequestError<SandboxBackend.SandboxError>    >([`access-api/accounts/${account}`], fetcher, {      refreshInterval: 0,      refreshWhenHidden: false, @@ -155,17 +178,23 @@ export function useAccountDetails(account: string): HttpResponse<SandboxBackend.    });    if (data) return data; -  if (error) return error; +  if (error) return error.info;    return { loading: true };  }  // FIXME: should poll -export function useWithdrawalDetails(account: string, wid: string): HttpResponse<SandboxBackend.Access.BankAccountGetWithdrawalResponse, SandboxBackend.SandboxError> { +export function useWithdrawalDetails( +  account: string, +  wid: string, +): HttpResponse< +  SandboxBackend.Access.BankAccountGetWithdrawalResponse, +  SandboxBackend.SandboxError +> {    const { fetcher } = useAuthenticatedBackend();    const { data, error } = useSWR<      HttpResponseOk<SandboxBackend.Access.BankAccountGetWithdrawalResponse>, -    HttpError<SandboxBackend.SandboxError> +    RequestError<SandboxBackend.SandboxError>    >([`access-api/accounts/${account}/withdrawals/${wid}`], fetcher, {      refreshInterval: 1000,      refreshWhenHidden: false, @@ -176,21 +205,26 @@ export function useWithdrawalDetails(account: string, wid: string): HttpResponse      errorRetryInterval: 1,      shouldRetryOnError: false,      keepPreviousData: true, -    });    // if (isValidating) return { loading: true, data: data?.data };    if (data) return data; -  if (error) return error; +  if (error) return error.info;    return { loading: true };  } -export function useTransactionDetails(account: string, tid: string): HttpResponse<SandboxBackend.Access.BankAccountTransactionInfo, SandboxBackend.SandboxError> { +export function useTransactionDetails( +  account: string, +  tid: string, +): HttpResponse< +  SandboxBackend.Access.BankAccountTransactionInfo, +  SandboxBackend.SandboxError +> {    const { fetcher } = useAuthenticatedBackend();    const { data, error } = useSWR<      HttpResponseOk<SandboxBackend.Access.BankAccountTransactionInfo>, -    HttpError<SandboxBackend.SandboxError> +    RequestError<SandboxBackend.SandboxError>    >([`access-api/accounts/${account}/transactions/${tid}`], fetcher, {      refreshInterval: 0,      refreshWhenHidden: false, @@ -205,17 +239,20 @@ export function useTransactionDetails(account: string, tid: string): HttpRespons    // if (isValidating) return { loading: true, data: data?.data };    if (data) return data; -  if (error) return error; +  if (error) return error.info;    return { loading: true };  }  interface PaginationFilter { -  page: number, +  page: number;  }  export function usePublicAccounts(    args?: PaginationFilter, -): HttpResponsePaginated<SandboxBackend.Access.PublicAccountsResponse, SandboxBackend.SandboxError> { +): HttpResponsePaginated< +  SandboxBackend.Access.PublicAccountsResponse, +  SandboxBackend.SandboxError +> {    const { paginatedFetcher } = usePublicBackend();    const [page, setPage] = useState(1); @@ -226,18 +263,21 @@ export function usePublicAccounts(      isValidating: loadingAfter,    } = useSWR<      HttpResponseOk<SandboxBackend.Access.PublicAccountsResponse>, -    HttpError<SandboxBackend.SandboxError> +    RequestError<SandboxBackend.SandboxError>    >([`public-accounts`, args?.page, PAGE_SIZE], paginatedFetcher);    const [lastAfter, setLastAfter] = useState< -    HttpResponse<SandboxBackend.Access.PublicAccountsResponse, SandboxBackend.SandboxError> +    HttpResponse< +      SandboxBackend.Access.PublicAccountsResponse, +      SandboxBackend.SandboxError +    >    >({ loading: true });    useEffect(() => {      if (afterData) setLastAfter(afterData);    }, [afterData]); -  if (afterError) return afterError; +  if (afterError) return afterError.info;    // if the query returns less that we ask, then we have reach the end or beginning    const isReachingEnd = @@ -254,30 +294,33 @@ export function usePublicAccounts(        }      },      loadMorePrev: () => { -      null +      null;      },    }; -  const publicAccounts = !afterData ? [] : (afterData || lastAfter).data.publicAccounts; -  if (loadingAfter) -    return { loading: true, data: { publicAccounts } }; +  const publicAccounts = !afterData +    ? [] +    : (afterData || lastAfter).data.publicAccounts; +  if (loadingAfter) return { loading: true, data: { publicAccounts } };    if (afterData) {      return { ok: true, data: { publicAccounts }, ...pagination };    }    return { loading: true };  } -  /**   * FIXME: mutate result when balance change (transaction ) - * @param account  - * @param args  - * @returns  + * @param account + * @param args + * @returns   */  export function useTransactions(    account: string,    args?: PaginationFilter, -): HttpResponsePaginated<SandboxBackend.Access.BankAccountTransactionsResponse, SandboxBackend.SandboxError> { +): HttpResponsePaginated< +  SandboxBackend.Access.BankAccountTransactionsResponse, +  SandboxBackend.SandboxError +> {    const { paginatedFetcher } = useAuthenticatedBackend();    const [page, setPage] = useState(1); @@ -288,18 +331,24 @@ export function useTransactions(      isValidating: loadingAfter,    } = useSWR<      HttpResponseOk<SandboxBackend.Access.BankAccountTransactionsResponse>, -    HttpError<SandboxBackend.SandboxError> -  >([`access-api/accounts/${account}/transactions`, args?.page, PAGE_SIZE], paginatedFetcher); +    RequestError<SandboxBackend.SandboxError> +  >( +    [`access-api/accounts/${account}/transactions`, args?.page, PAGE_SIZE], +    paginatedFetcher, +  );    const [lastAfter, setLastAfter] = useState< -    HttpResponse<SandboxBackend.Access.BankAccountTransactionsResponse, SandboxBackend.SandboxError> +    HttpResponse< +      SandboxBackend.Access.BankAccountTransactionsResponse, +      SandboxBackend.SandboxError +    >    >({ loading: true });    useEffect(() => {      if (afterData) setLastAfter(afterData);    }, [afterData]); -  if (afterError) return afterError; +  if (afterError) return afterError.info;    // if the query returns less that we ask, then we have reach the end or beginning    const isReachingEnd = @@ -316,13 +365,14 @@ export function useTransactions(        }      },      loadMorePrev: () => { -      null +      null;      },    }; -  const transactions = !afterData ? [] : (afterData || lastAfter).data.transactions; -  if (loadingAfter) -    return { loading: true, data: { transactions } }; +  const transactions = !afterData +    ? [] +    : (afterData || lastAfter).data.transactions; +  if (loadingAfter) return { loading: true, data: { transactions } };    if (afterData) {      return { ok: true, data: { transactions }, ...pagination };    } diff --git a/packages/demobank-ui/src/hooks/backend.ts b/packages/demobank-ui/src/hooks/backend.ts index f4f5ecfd0..e87bdd5fe 100644 --- a/packages/demobank-ui/src/hooks/backend.ts +++ b/packages/demobank-ui/src/hooks/backend.ts @@ -15,7 +15,10 @@   */  import { canonicalizeBaseUrl } from "@gnu-taler/taler-util"; -import { useLocalStorage } from "@gnu-taler/web-util/lib/index.browser"; +import { +  RequestError, +  useLocalStorage, +} from "@gnu-taler/web-util/lib/index.browser";  import {    HttpResponse,    HttpResponseOk, @@ -57,7 +60,7 @@ export function getInitialBackendBaseURL(): string {  export const defaultState: BackendState = {    status: "loggedOut", -  url: getInitialBackendBaseURL() +  url: getInitialBackendBaseURL(),  };  export interface BackendStateHandler { @@ -91,7 +94,12 @@ export function useBackendState(): BackendStateHandler {      },      logIn(info) {        //admin is defined by the username -      const nextState: BackendState = { status: "loggedIn", url: state.url, ...info, isUserAdministrator: info.username === "admin" }; +      const nextState: BackendState = { +        status: "loggedIn", +        url: state.url, +        ...info, +        isUserAdministrator: info.username === "admin", +      };        update(JSON.stringify(nextState));      },    }; @@ -103,24 +111,25 @@ interface useBackendType {      options?: RequestOptions,    ) => Promise<HttpResponseOk<T>>;    fetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>; -  multiFetcher: <T>(endpoint: string[]) => Promise<HttpResponseOk<T>[]>; -  paginatedFetcher: <T>(args: [string, number, number]) => Promise<HttpResponseOk<T>>; -  sandboxAccountsFetcher: <T>(args: [string, number, number, string]) => Promise<HttpResponseOk<T>>; +  multiFetcher: <T>(endpoint: string[][]) => Promise<HttpResponseOk<T>[]>; +  paginatedFetcher: <T>( +    args: [string, number, number], +  ) => Promise<HttpResponseOk<T>>; +  sandboxAccountsFetcher: <T>( +    args: [string, number, number, string], +  ) => Promise<HttpResponseOk<T>>;  } - -  export function usePublicBackend(): useBackendType {    const { state } = useBackendContext();    const { request: requestHandler } = useApiContext(); -  const baseUrl = state.url +  const baseUrl = state.url;    const request = useCallback(      function requestImpl<T>(        path: string,        options: RequestOptions = {},      ): Promise<HttpResponseOk<T>> { -        return requestHandler<T>(baseUrl, path, options);      },      [baseUrl], @@ -133,15 +142,21 @@ export function usePublicBackend(): useBackendType {      [baseUrl],    );    const paginatedFetcher = useCallback( -    function fetcherImpl<T>([endpoint, page, size]: [string, number, number]): Promise<HttpResponseOk<T>> { -      return requestHandler<T>(baseUrl, endpoint, { params: { page: page || 1, size } }); +    function fetcherImpl<T>([endpoint, page, size]: [ +      string, +      number, +      number, +    ]): Promise<HttpResponseOk<T>> { +      return requestHandler<T>(baseUrl, endpoint, { +        params: { page: page || 1, size }, +      });      },      [baseUrl],    );    const multiFetcher = useCallback( -    function multiFetcherImpl<T>( -      endpoints: string[], -    ): Promise<HttpResponseOk<T>[]> { +    function multiFetcherImpl<T>([endpoints]: string[][]): Promise< +      HttpResponseOk<T>[] +    > {        return Promise.all(          endpoints.map((endpoint) => requestHandler<T>(baseUrl, endpoint)),        ); @@ -149,27 +164,39 @@ export function usePublicBackend(): useBackendType {      [baseUrl],    );    const sandboxAccountsFetcher = useCallback( -    function fetcherImpl<T>([endpoint, page, size, account]: [string, number, number, string]): Promise<HttpResponseOk<T>> { -      return requestHandler<T>(baseUrl, endpoint, { params: { page: page || 1, size } }); +    function fetcherImpl<T>([endpoint, page, size, account]: [ +      string, +      number, +      number, +      string, +    ]): Promise<HttpResponseOk<T>> { +      return requestHandler<T>(baseUrl, endpoint, { +        params: { page: page || 1, size }, +      });      },      [baseUrl],    ); -  return { request, fetcher, paginatedFetcher, multiFetcher, sandboxAccountsFetcher }; +  return { +    request, +    fetcher, +    paginatedFetcher, +    multiFetcher, +    sandboxAccountsFetcher, +  };  }  export function useAuthenticatedBackend(): useBackendType {    const { state } = useBackendContext();    const { request: requestHandler } = useApiContext(); -  const creds = state.status === "loggedIn" ? state : undefined -  const baseUrl = state.url +  const creds = state.status === "loggedIn" ? state : undefined; +  const baseUrl = state.url;    const request = useCallback(      function requestImpl<T>(        path: string,        options: RequestOptions = {},      ): Promise<HttpResponseOk<T>> { -        return requestHandler<T>(baseUrl, path, { basicAuth: creds, ...options });      },      [baseUrl, creds], @@ -182,36 +209,66 @@ export function useAuthenticatedBackend(): useBackendType {      [baseUrl, creds],    );    const paginatedFetcher = useCallback( -    function fetcherImpl<T>([endpoint, page = 0, size]: [string, number, number]): Promise<HttpResponseOk<T>> { -      return requestHandler<T>(baseUrl, endpoint, { basicAuth: creds, params: { page, size } }); +    function fetcherImpl<T>([endpoint, page = 0, size]: [ +      string, +      number, +      number, +    ]): Promise<HttpResponseOk<T>> { +      return requestHandler<T>(baseUrl, endpoint, { +        basicAuth: creds, +        params: { page, size }, +      });      },      [baseUrl, creds],    );    const multiFetcher = useCallback( -    function multiFetcherImpl<T>( -      endpoints: string[], -    ): Promise<HttpResponseOk<T>[]> { +    function multiFetcherImpl<T>([endpoints]: string[][]): Promise< +      HttpResponseOk<T>[] +    > { +      console.log("list size", endpoints.length, endpoints);        return Promise.all( -        endpoints.map((endpoint) => requestHandler<T>(baseUrl, endpoint, { basicAuth: creds })), +        endpoints.map((endpoint) => +          requestHandler<T>(baseUrl, endpoint, { basicAuth: creds }), +        ),        );      },      [baseUrl, creds],    );    const sandboxAccountsFetcher = useCallback( -    function fetcherImpl<T>([endpoint, page, size, account]: [string, number, number, string]): Promise<HttpResponseOk<T>> { -      return requestHandler<T>(baseUrl, endpoint, { basicAuth: creds, params: { page: page || 1, size } }); +    function fetcherImpl<T>([endpoint, page, size, account]: [ +      string, +      number, +      number, +      string, +    ]): Promise<HttpResponseOk<T>> { +      return requestHandler<T>(baseUrl, endpoint, { +        basicAuth: creds, +        params: { page: page || 1, size }, +      });      },      [baseUrl],    ); -  return { request, fetcher, paginatedFetcher, multiFetcher, sandboxAccountsFetcher }; + +  return { +    request, +    fetcher, +    paginatedFetcher, +    multiFetcher, +    sandboxAccountsFetcher, +  };  } -export function useBackendConfig(): HttpResponse<SandboxBackend.Config, SandboxBackend.SandboxError> { +export function useBackendConfig(): HttpResponse< +  SandboxBackend.Config, +  SandboxBackend.SandboxError +> {    const { request } = usePublicBackend();    type Type = SandboxBackend.Config; -  const [result, setResult] = useState<HttpResponse<Type, SandboxBackend.SandboxError>>({ loading: true }); +  const [result, setResult] = useState< +    HttpResponse<Type, SandboxBackend.SandboxError> +  >({ loading: true });    useEffect(() => {      request<Type>(`/config`) @@ -238,10 +295,8 @@ export function useMatchMutate(): (      const allKeys = Array.from(cache.keys());      const keys = allKeys.filter((key) => re.test(key));      const mutations = keys.map((key) => { -      mutate(key, value, true); +      return mutate(key, value, true);      });      return Promise.all(mutations);    };  } - - diff --git a/packages/demobank-ui/src/hooks/circuit.ts b/packages/demobank-ui/src/hooks/circuit.ts index 6e9ada601..91922a6ba 100644 --- a/packages/demobank-ui/src/hooks/circuit.ts +++ b/packages/demobank-ui/src/hooks/circuit.ts @@ -15,23 +15,24 @@   */  import { -  HttpError,    HttpResponse,    HttpResponseOk,    HttpResponsePaginated, -  RequestError +  RequestError, +  useApiContext,  } 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"; +import { useAuthenticatedBackend, useMatchMutate } from "./backend.js";  export function useAdminAccountAPI(): AdminAccountAPI {    const { request } = useAuthenticatedBackend(); -  const { state } = useBackendContext() +  const mutateAll = useMatchMutate(); +  const { state } = useBackendContext();    if (state.status === "loggedOut") { -    throw Error("access-api can't be used when the user is not logged In") +    throw Error("access-api can't be used when the user is not logged In");    }    const createAccount = async ( @@ -40,8 +41,9 @@ export function useAdminAccountAPI(): AdminAccountAPI {      const res = await request<void>(`circuit-api/accounts`, {        method: "POST",        data, -      contentType: "json" +      contentType: "json",      }); +    await mutateAll(/.*circuit-api\/accounts.*/);      return res;    }; @@ -52,8 +54,9 @@ export function useAdminAccountAPI(): AdminAccountAPI {      const res = await request<void>(`circuit-api/accounts/${account}`, {        method: "PATCH",        data, -      contentType: "json" +      contentType: "json",      }); +    await mutateAll(/.*circuit-api\/accounts.*/);      return res;    };    const deleteAccount = async ( @@ -61,8 +64,9 @@ export function useAdminAccountAPI(): AdminAccountAPI {    ): Promise<HttpResponseOk<void>> => {      const res = await request<void>(`circuit-api/accounts/${account}`, {        method: "DELETE", -      contentType: "json" +      contentType: "json",      }); +    await mutateAll(/.*circuit-api\/accounts.*/);      return res;    };    const changePassword = async ( @@ -72,7 +76,7 @@ export function useAdminAccountAPI(): AdminAccountAPI {      const res = await request<void>(`circuit-api/accounts/${account}/auth`, {        method: "PATCH",        data, -      contentType: "json" +      contentType: "json",      });      return res;    }; @@ -82,9 +86,10 @@ export function useAdminAccountAPI(): AdminAccountAPI {  export function useCircuitAccountAPI(): CircuitAccountAPI {    const { request } = useAuthenticatedBackend(); -  const { state } = useBackendContext() +  const mutateAll = useMatchMutate(); +  const { state } = useBackendContext();    if (state.status === "loggedOut") { -    throw Error("access-api can't be used when the user is not logged In") +    throw Error("access-api can't be used when the user is not logged In");    }    const account = state.username; @@ -94,8 +99,9 @@ export function useCircuitAccountAPI(): CircuitAccountAPI {      const res = await request<void>(`circuit-api/accounts/${account}`, {        method: "PATCH",        data, -      contentType: "json" +      contentType: "json",      }); +    await mutateAll(/.*circuit-api\/accounts.*/);      return res;    };    const changePassword = async ( @@ -104,7 +110,7 @@ export function useCircuitAccountAPI(): CircuitAccountAPI {      const res = await request<void>(`circuit-api/accounts/${account}/auth`, {        method: "PATCH",        data, -      contentType: "json" +      contentType: "json",      });      return res;    }; @@ -120,57 +126,72 @@ export interface AdminAccountAPI {    updateAccount: (      account: string, -    data: SandboxBackend.Circuit.CircuitAccountReconfiguration +    data: SandboxBackend.Circuit.CircuitAccountReconfiguration,    ) => Promise<HttpResponseOk<void>>;    changePassword: (      account: string, -    data: SandboxBackend.Circuit.AccountPasswordChange +    data: SandboxBackend.Circuit.AccountPasswordChange,    ) => Promise<HttpResponseOk<void>>;  }  export interface CircuitAccountAPI {    updateAccount: ( -    data: SandboxBackend.Circuit.CircuitAccountReconfiguration +    data: SandboxBackend.Circuit.CircuitAccountReconfiguration,    ) => Promise<HttpResponseOk<void>>;    changePassword: ( -    data: SandboxBackend.Circuit.AccountPasswordChange +    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") +async function getBusinessStatus( +  request: ReturnType<typeof useApiContext>["request"], +  url: string, +  basicAuth: { username: string; password: string }, +): Promise<boolean> { +  try { +    const result = await request< +      HttpResponseOk<SandboxBackend.Circuit.CircuitAccountData> +    >(url, `circuit-api/accounts/${basicAuth.username}`, { basicAuth }); +    return result.ok; +  } catch (error) { +    return false;    } -  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, +} + +export function useBusinessAccountFlag(): boolean | undefined { +  const [isBusiness, setIsBusiness] = useState<boolean | undefined>(); +  const { state } = useBackendContext(); +  const { request } = useApiContext(); +  const creds = +    state.status === "loggedOut" +      ? undefined +      : { username: state.username, password: state.password }; + +  useEffect(() => { +    if (!creds) return; +    getBusinessStatus(request, state.url, creds) +      .then((result) => { +        setIsBusiness(result); +      }) +      .catch((error) => { +        setIsBusiness(false); +      });    }); -  if (data) return data; -  if (error) return error; -  return { loading: true }; +  return isBusiness;  } -export function useAccountDetails(account: string): HttpResponse<SandboxBackend.Circuit.CircuitAccountData, SandboxBackend.SandboxError> { +export function useBusinessAccountDetails( +  account: string, +): HttpResponse< +  SandboxBackend.Circuit.CircuitAccountData, +  SandboxBackend.SandboxError +> {    const { fetcher } = useAuthenticatedBackend();    const { data, error } = useSWR< @@ -188,20 +209,22 @@ export function useAccountDetails(account: string): HttpResponse<SandboxBackend.      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, +  account?: string; +  page?: number;  } -export function useAccounts( +export function useBusinessAccounts(    args?: PaginationFilter, -): HttpResponsePaginated<SandboxBackend.Circuit.CircuitAccounts, SandboxBackend.SandboxError> { +): HttpResponsePaginated< +  SandboxBackend.Circuit.CircuitAccounts, +  SandboxBackend.SandboxError +> {    const { sandboxAccountsFetcher } = useAuthenticatedBackend();    const [page, setPage] = useState(0); @@ -212,17 +235,21 @@ export function useAccounts(    } = 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, -  }); +  >( +    [`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> @@ -247,18 +274,18 @@ export function useAccounts(        }      },      loadMorePrev: () => { -      null +      null;      },    };    const result = useMemo(() => { -    const customers = !afterData ? [] : (afterData)?.data?.customers ?? []; -    return { ok: true as const, data: { customers }, ...pagination } -  }, [afterData?.data]) +    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 +    return result;    }    // if (loadingAfter)  | 
