diff options
Diffstat (limited to 'packages/demobank-ui/src/pages/ShowAccountDetails.tsx')
-rw-r--r-- | packages/demobank-ui/src/pages/ShowAccountDetails.tsx | 278 |
1 files changed, 151 insertions, 127 deletions
diff --git a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx index 91b50b84c..6acf0361e 100644 --- a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx +++ b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx @@ -1,5 +1,5 @@ import { ErrorType, HttpResponsePaginated, RequestError, notify, notifyError, useTranslationContext } from "@gnu-taler/web-util/browser"; -import { VNode,h } from "preact"; +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"; @@ -7,137 +7,161 @@ 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>; - } + 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); } - - return ( - <div> - <div> - <h1 class="nav welcome-text"> - <i18n.Translate>Business account details</i18n.Translate> - </h1> + 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 style={{ maxWidth: 600, overflowX: "hidden", margin: "auto" }}> - <AccountForm - template={result.data} - purpose={update ? "update" : "show"} - onChange={(a) => setSubmitAccount(a)} - /> - - <p class="buttons-account"> - <div - style={{ - display: "flex", - justifyContent: "space-between", - flexFlow: "wrap-reverse", - }} - > + </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> - {onClear ? ( - <input - class="pure-button" - type="submit" - value={i18n.str`Close`} - onClick={async (e) => { - e.preventDefault(); - onClear(); - }} - /> - ) : undefined} + <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 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(); - - 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 - ) - } - } - } - }} - /> - </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> - </p> - </div> + </div> + </p> </div> - ); - } -
\ No newline at end of file + </div> + ); +} |