diff options
Diffstat (limited to 'packages/demobank-ui/src/pages/BankFrame.tsx')
-rw-r--r-- | packages/demobank-ui/src/pages/BankFrame.tsx | 227 |
1 files changed, 119 insertions, 108 deletions
diff --git a/packages/demobank-ui/src/pages/BankFrame.tsx b/packages/demobank-ui/src/pages/BankFrame.tsx index e682085ae..80a8224d4 100644 --- a/packages/demobank-ui/src/pages/BankFrame.tsx +++ b/packages/demobank-ui/src/pages/BankFrame.tsx @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { Logger, PaytoUriIBAN, TranslatedString, parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util"; +import { Amounts, Logger, PaytoUriIBAN, TranslatedString, parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util"; import { useNotifications, useTranslationContext } from "@gnu-taler/web-util/browser"; import { ComponentChildren, Fragment, h, VNode } from "preact"; import { StateUpdater, useEffect, useState } from "preact/hooks"; @@ -25,6 +25,7 @@ import { bankUiSettings } from "../settings.js"; import { useSettings } from "../hooks/settings.js"; import { CopyButton, CopyIcon } from "../components/CopyButton.js"; import logo from "../assets/logo-2021.svg"; +import { useAccountDetails } from "../hooks/access.js"; const IS_PUBLIC_ACCOUNT_ENABLED = false; const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined; @@ -63,7 +64,9 @@ function MaybeBusinessButton({ export function BankFrame({ children, goToBusinessAccount, + account, }: { + account: string | undefined, children: ComponentChildren; goToBusinessAccount?: () => void; }): VNode { @@ -122,123 +125,118 @@ export function BankFrame({ </div> {open && - <Fragment> - <div class="relative z-10" aria-labelledby="slide-over-title" role="dialog" aria-modal="true" - onClick={() => { - setOpen(false) - }}> - <div class="fixed inset-0"></div> - - <div class="fixed inset-0 overflow-hidden"> - <div class="absolute inset-0 overflow-hidden"> - <div class="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10"> - <div class="pointer-events-auto w-screen max-w-md" > - <div class="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl" onClick={(e) => { - //do not trigger close if clicking inside the sidebar - e.stopPropagation(); - }}> - <div class="px-4 sm:px-6" > - <div class="flex items-start justify-between" > - <h2 class="text-base font-semibold leading-6 text-gray-900" id="slide-over-title"> - <i18n.Translate>Settings</i18n.Translate> - </h2> - <div class="ml-3 flex h-7 items-center"> - <button type="button" class="relative rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2" - onClick={(e) => { - setOpen(false) - }} - - > - <span class="absolute -inset-2.5"></span> - <span class="sr-only"> - <i18n.Translate>Close panel</i18n.Translate> - </span> - <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> - <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> - </svg> - </button> - </div> + <div class="relative z-10" aria-labelledby="slide-over-title" role="dialog" aria-modal="true" + onClick={() => { + setOpen(false) + }}> + <div class="fixed inset-0"></div> + + <div class="fixed inset-0 overflow-hidden"> + <div class="absolute inset-0 overflow-hidden"> + <div class="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10"> + <div class="pointer-events-auto w-screen max-w-md" > + <div class="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl" onClick={(e) => { + //do not trigger close if clicking inside the sidebar + e.stopPropagation(); + }}> + <div class="px-4 sm:px-6" > + <div class="flex items-start justify-between" > + <h2 class="text-base font-semibold leading-6 text-gray-900" id="slide-over-title"> + <i18n.Translate>Preferences</i18n.Translate> + </h2> + <div class="ml-3 flex h-7 items-center"> + <button type="button" class="relative rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2" + onClick={(e) => { + setOpen(false) + }} + + > + <span class="absolute -inset-2.5"></span> + <span class="sr-only"> + <i18n.Translate>Close panel</i18n.Translate> + </span> + <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> + <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> + </svg> + </button> </div> </div> - <div class="relative mt-6 flex-1 px-4 sm:px-6"> - {/* <!-- Your content --> */} - - <nav class="flex flex-1 flex-col" aria-label="Sidebar"> - <ul role="list" class="flex flex-1 flex-col gap-y-7"> - <li> - <ul role="list" class="-mx-2 space-y-1"> - <li> - <a href="#" - class="text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold" - onClick={() => { - backend.logOut(); - setOpen(false) - updateSettings("currentWithdrawalOperationId", undefined); - }} - > - <svg class="h-6 w-6 shrink-0 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> - <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" /> - </svg> - Log out - {/* <span class="ml-auto w-9 min-w-max whitespace-nowrap rounded-full bg-gray-50 px-2.5 py-0.5 text-center text-xs font-medium leading-5 text-gray-600 ring-1 ring-inset ring-gray-200" aria-hidden="true">5</span> */} - </a> - </li> - <li> - <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>Show withdrawal confirmation</i18n.Translate> - </span> + </div> + <div class="relative mt-6 flex-1 px-4 sm:px-6"> + <nav class="flex flex-1 flex-col" aria-label="Sidebar"> + <ul role="list" class="flex flex-1 flex-col gap-y-7"> + <li> + <ul role="list" class="-mx-2 space-y-1"> + <li> + <a href="#" + class="text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold" + onClick={() => { + backend.logOut(); + setOpen(false) + updateSettings("currentWithdrawalOperationId", undefined); + }} + > + <svg class="h-6 w-6 shrink-0 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> + <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" /> + </svg> + Log out + {/* <span class="ml-auto w-9 min-w-max whitespace-nowrap rounded-full bg-gray-50 px-2.5 py-0.5 text-center text-xs font-medium leading-5 text-gray-600 ring-1 ring-inset ring-gray-200" aria-hidden="true">5</span> */} + </a> + </li> + <li> + <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>Show withdrawal confirmation</i18n.Translate> </span> - <button type="button" data-enabled={settings.showWithdrawalSuccess} class="bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent 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={() => { - console.log(settings.showWithdrawalSuccess) - updateSettings("showWithdrawalSuccess", !settings.showWithdrawalSuccess); - }}> - <span aria-hidden="true" data-enabled={settings.showWithdrawalSuccess} class="translate-x-5 data-[enabled=false]: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> - </li> - </ul> - </li> - - - - <li class="sm:hidden"> - <div class="text-xs font-semibold leading-6 text-gray-400"> - <i18n.Translate>Sites</i18n.Translate> - </div> - <ul role="list" class="-mx-2 mt-2 space-y-1"> - {bankUiSettings.demoSites.map(([name, url]) => { - return <a href={url} target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold"> - <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border text-[0.625rem] font-medium bg-white text-gray-400 border-gray-200 group-hover:border-indigo-600 group-hover:text-indigo-600">></span> - <span class="truncate">{name}</span> - </a> - })} - </ul> - </li> - </ul> - </nav> - </div> + </span> + <button type="button" data-enabled={settings.showWithdrawalSuccess} class="bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent 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={() => { + console.log(settings.showWithdrawalSuccess) + updateSettings("showWithdrawalSuccess", !settings.showWithdrawalSuccess); + }}> + <span aria-hidden="true" data-enabled={settings.showWithdrawalSuccess} class="translate-x-5 data-[enabled=false]: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> + </li> + </ul> + </li> + + + + <li class="sm:hidden"> + <div class="text-xs font-semibold leading-6 text-gray-400"> + <i18n.Translate>Sites</i18n.Translate> + </div> + <ul role="list" class="-mx-2 mt-2 space-y-1"> + {bankUiSettings.demoSites.map(([name, url]) => { + return <a href={url} target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold"> + <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border text-[0.625rem] font-medium bg-white text-gray-400 border-gray-200 group-hover:border-indigo-600 group-hover:text-indigo-600">></span> + <span class="truncate">{name}</span> + </a> + })} + </ul> + </li> + </ul> + </nav> </div> </div> </div> </div> </div> </div> - - </Fragment> + </div> } </nav > - {true && + {account && <header class="py-5 border-t border-indigo-300 border-opacity-25 bg-indigo-600 lg:border-t lg:border-indigo-400 lg:border-opacity-25"> <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8"> <div class=" flex flex-wrap items-center justify-between sm:flex-nowrap"> - <h3 class="text-2xl font-bold tracking-tight text-white"><WelcomeAccount /></h3> + <h3 class="text-2xl font-bold tracking-tight text-white"><WelcomeAccount account={account} /></h3> <div> - <h3 class="text-2xl font-bold tracking-tight text-white"><AccountBalance /></h3> + <h3 class="text-2xl font-bold tracking-tight text-white"><AccountBalance account={account} /></h3> </div> </div> </div> @@ -466,17 +464,30 @@ function Footer() { ); } -function WelcomeAccount(): VNode { +function WelcomeAccount({ account }: { account: string }): VNode { const { i18n } = useTranslationContext(); - const account = "Sebastian" - const payto: PaytoUriIBAN = parsePaytoUri("payto://iban/bank.localhost/DE955922") as PaytoUriIBAN + + const result = useAccountDetails(account); + if (!result.ok) return <div /> + + // const account = "Sebastian" + const payto = parsePaytoUri(result.data.paytoUri) + if (!payto) return <div /> + + const accountNumber = !payto.isKnown ? undefined : payto.targetType === "iban" ? payto.iban : payto.targetType === "x-taler-bank" ? payto.account : undefined; return <i18n.Translate> - Welcome, {account} (<a href={stringifyPaytoUri(payto)}>{payto.iban}</a>)! <CopyButton getContent={() => stringifyPaytoUri(payto)} /> + Welcome, {account} {accountNumber !== undefined ? + <span> + (<a href={result.data.paytoUri}>{accountNumber}</a> <CopyButton getContent={() => result.data.paytoUri} />) + </span> + : <Fragment />}! </i18n.Translate> } -function AccountBalance(): VNode { +function AccountBalance({ account }: { account: string }): VNode { + const result = useAccountDetails(account); + if (!result.ok) return <div /> - return <div>KUDOS 100.00</div> + return <div>{result.data.balance.credit_debit_indicator === "debit" ? "-" : ""} {Amounts.currencyOf(result.data.balance.amount)} {Amounts.stringifyValue(result.data.balance.amount)}</div> } |