diff options
Diffstat (limited to 'packages/demobank-ui/src/pages/ShowAccountDetails.tsx')
-rw-r--r-- | packages/demobank-ui/src/pages/ShowAccountDetails.tsx | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx new file mode 100644 index 000000000..6acf0361e --- /dev/null +++ b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx @@ -0,0 +1,167 @@ +import { ErrorType, HttpResponsePaginated, RequestError, notify, notifyError, useTranslationContext } from "@gnu-taler/web-util/browser"; +import { VNode, h } from "preact"; +import { useAdminAccountAPI, useBusinessAccountDetails } from "../hooks/circuit.js"; +import { useState } from "preact/hooks"; +import { HttpStatusCode, TranslatedString } from "@gnu-taler/taler-util"; +import { buildRequestErrorMessage } from "../utils.js"; +import { AccountForm } from "./admin/AccountForm.js"; + +export function ShowAccountDetails({ + account, + onClear, + onUpdateSuccess, + onLoadNotOk, + onChangePassword, +}: { + onLoadNotOk: <T>( + error: HttpResponsePaginated<T, SandboxBackend.SandboxError>, + ) => VNode; + onClear?: () => void; + onChangePassword: () => void; + onUpdateSuccess: () => void; + account: string; +}): VNode { + const { i18n } = useTranslationContext(); + const result = useBusinessAccountDetails(account); + const { updateAccount } = useAdminAccountAPI(); + const [update, setUpdate] = useState(false); + const [submitAccount, setSubmitAccount] = useState< + SandboxBackend.Circuit.CircuitAccountData | undefined + >(); + + if (!result.ok) { + if (result.loading || result.type === ErrorType.TIMEOUT) { + return onLoadNotOk(result); + } + if (result.status === HttpStatusCode.NotFound) { + return <div>account not found</div>; + } + return onLoadNotOk(result); + } + + async function doUpdate() { + if (!update) { + setUpdate(true); + } else { + if (!submitAccount) return; + try { + await updateAccount(account, { + cashout_address: submitAccount.cashout_address, + contact_data: submitAccount.contact_data, + }); + onUpdateSuccess(); + } catch (error) { + if (error instanceof RequestError) { + notify( + buildRequestErrorMessage(i18n, error.cause, { + onClientError: (status) => + status === HttpStatusCode.Forbidden + ? i18n.str`The rights to change the account are not sufficient` + : status === HttpStatusCode.NotFound + ? i18n.str`The username was not found` + : undefined, + }), + ); + } else { + notifyError( + i18n.str`Operation failed, please report`, + (error instanceof Error + ? error.message + : JSON.stringify(error)) as TranslatedString + ) + } + } + } + } + + return ( + <div> + <div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-10 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"> + <div class="px-4 sm:px-0"> + <h2 class="text-base font-semibold leading-7 text-gray-900"> + {update ? + <i18n.Translate>Update account</i18n.Translate> + : + <i18n.Translate>Account details</i18n.Translate> + } + </h2> + <div class="mt-4"> + <div class="flex items-center justify-between"> + <span class="flex flex-grow flex-col"> + <span class="text-sm text-black font-medium leading-6 " id="availability-label"> + <i18n.Translate>change the account details</i18n.Translate> + </span> + </span> + <button type="button" data-enabled={!update} class="bg-indigo-600 data-[enabled=true]:bg-gray-200 relative inline-flex h-5 w-10 flex-shrink-0 cursor-pointer rounded-full ring-2 border-gray-600 transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description" + onClick={() => { + setUpdate(!update) + }}> + <span aria-hidden="true" data-enabled={!update} class="translate-x-5 data-[enabled=true]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span> + </button> + </div> + </div> + + </div> + <AccountForm + template={result.data} + purpose={update ? "update" : "show"} + onChange={(a) => setSubmitAccount(a)} + > + + </AccountForm> + + <p class="buttons-account"> + <div + style={{ + display: "flex", + justifyContent: "space-between", + flexFlow: "wrap-reverse", + }} + > + <div> + {onClear ? ( + <input + class="pure-button" + type="submit" + value={i18n.str`Close`} + onClick={async (e) => { + e.preventDefault(); + onClear(); + }} + /> + ) : undefined} + </div> + <div style={{ display: "flex" }}> + <div> + <input + id="select-exchange" + class="pure-button pure-button-primary content" + disabled={update && !submitAccount} + type="submit" + value={i18n.str`Change password`} + onClick={async (e) => { + e.preventDefault(); + onChangePassword(); + }} + /> + </div> + <div> + <input + id="select-exchange" + class="pure-button pure-button-primary content" + disabled={update && !submitAccount} + type="submit" + value={update ? i18n.str`Confirm` : i18n.str`Update`} + onClick={async (e) => { + e.preventDefault(); + doUpdate() + }} + /> + </div> + </div> + </div> + </p> + </div> + </div> + ); +} |