/* This file is part of GNU Taler (C) 2022-2024 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 */ import { AbsoluteTime, AmountJson, Amounts, HttpStatusCode, TranslatedString, assertUnreachable, parseWithdrawUri, } from "@gnu-taler/taler-util"; import { Attention, LocalNotificationBanner, notifyError, useLocalNotification, useTranslationContext, } from "@gnu-taler/web-util/browser"; import { VNode, h } from "preact"; import { forwardRef } from "preact/compat"; import { useState } from "preact/hooks"; import { useBankCoreApiContext } from "@gnu-taler/web-util/browser"; import { useSessionState } from "../hooks/session.js"; import { useBankState } from "../hooks/bank-state.js"; import { usePreferences } from "../hooks/preferences.js"; import { RouteDefinition } from "@gnu-taler/web-util/browser"; import { undefinedIfEmpty } from "../utils.js"; import { OperationState } from "./OperationState/index.js"; import { InputAmount, RenderAmount, doAutoFocus, } from "./PaytoWireTransferForm.js"; const RefAmount = forwardRef(InputAmount); function OldWithdrawalForm({ onOperationCreated, limit, balance, routeCancel, focus, routeOperationDetails, }: { limit: AmountJson; balance: AmountJson; focus?: boolean; routeOperationDetails: RouteDefinition<{ wopid: string }>; onOperationCreated: (wopid: string) => void; routeCancel: RouteDefinition; }): VNode { const { i18n } = useTranslationContext(); const [settings] = usePreferences(); // const walletInegrationApi = useTalerWalletIntegrationAPI() // const { navigateTo } = useNavigationContext(); const [bankState, updateBankState] = useBankState(); const { lib: { bank: api }, config, } = useBankCoreApiContext(); const { state: credentials } = useSessionState(); const creds = credentials.status !== "loggedIn" ? undefined : credentials; const [amountStr, setAmountStr] = useState( `${settings.maxWithdrawalAmount}`, ); const [notification, notify, handleError] = useLocalNotification(); if (bankState.currentWithdrawalOperationId) { // FIXME: doing the preventDefault is not optimal // const suri = stringifyWithdrawUri({ // bankIntegrationApiBaseUrl: api.getIntegrationAPI().baseUrl, // withdrawalOperationId: bankState.currentWithdrawalOperationId, // }); // const uri = parseWithdrawUri(suri)! const url = routeOperationDetails.url({ wopid: bankState.currentWithdrawalOperationId, }); return ( { updateBankState("currentWithdrawalOperationId", undefined); }} > Complete the operation in{" "} { // e.preventDefault() // walletInegrationApi.publishTalerAction(uri, () => { // navigateTo(url) // }) // }} > this page ); } const trimmedAmountStr = amountStr?.trim(); const parsedAmount = trimmedAmountStr ? Amounts.parse(`${limit.currency}:${trimmedAmountStr}`) : undefined; const errors = undefinedIfEmpty({ amount: trimmedAmountStr == null ? i18n.str`Required` : !parsedAmount ? i18n.str`Invalid` : Amounts.cmp(limit, parsedAmount) === -1 ? i18n.str`Balance is not enough` : undefined, }); async function doStart() { if (!parsedAmount || !creds) return; await handleError(async () => { const resp = await api.createWithdrawal(creds, { amount: Amounts.stringify(parsedAmount), }); if (resp.type === "ok") { const uri = parseWithdrawUri(resp.body.taler_withdraw_uri); if (!uri) { return notifyError( i18n.str`Server responded with an invalid withdraw URI`, i18n.str`Withdraw URI: ${resp.body.taler_withdraw_uri}`, ); } else { updateBankState( "currentWithdrawalOperationId", uri.withdrawalOperationId, ); onOperationCreated(uri.withdrawalOperationId); } } else { switch (resp.case) { case HttpStatusCode.Conflict: { notify({ type: "error", title: i18n.str`The operation was rejected due to insufficient funds`, description: resp.detail.hint as TranslatedString, debug: resp.detail, when: AbsoluteTime.now(), }); break; } case HttpStatusCode.Unauthorized: { notify({ type: "error", title: i18n.str`The operation was rejected due to insufficient funds`, description: resp.detail.hint as TranslatedString, debug: resp.detail, when: AbsoluteTime.now(), }); break; } case HttpStatusCode.NotFound: { notify({ type: "error", title: i18n.str`Account not found`, description: resp.detail.hint as TranslatedString, debug: resp.detail, when: AbsoluteTime.now(), }); break; } default: assertUnreachable(resp); } } }); } return (
{ e.preventDefault(); }} >
{ setAmountStr(v); }} error={errors?.amount} ref={focus ? doAutoFocus : undefined} />

Current balance is{" "}

{Amounts.cmp(limit, balance) > 0 ? (

Your account allows you to withdraw{" "}

) : undefined}
Cancel
); } export function WalletWithdrawForm({ focus, limit, balance, routeCancel, onAuthorizationRequired, onOperationCreated, onOperationAborted, routeOperationDetails, }: { limit: AmountJson; balance: AmountJson; focus?: boolean; routeOperationDetails: RouteDefinition<{ wopid: string }>; onAuthorizationRequired: () => void; onOperationCreated: (wopid: string) => void; onOperationAborted: () => void; routeCancel: RouteDefinition; }): VNode { const { i18n } = useTranslationContext(); const [settings, updateSettings] = usePreferences(); return (

Prepare your Taler wallet

After using your wallet you will need to confirm or cancel the operation on this site.

{settings.showInstallWallet && ( { updateSettings("showInstallWallet", false); }} > If you don't have one yet you can follow the instruction in {" "} this page )} {!settings.fastWithdrawal ? ( ) : ( )}
); }