/* 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 { AmountString, Amounts, HttpStatusCode, OperationOk, OperationResult, TalerBankConversionApi, TranslatedString, assertUnreachable } from "@gnu-taler/taler-util"; import { LocalNotificationBanner, ShowInputErrorLabel, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser"; import { VNode, h } from "preact"; import { useBankCoreApiContext } from "../context/config.js"; import { useBackendState } from "../hooks/backend.js"; import { RouteDefinition } from "../route.js"; import { ProfileNavigation } from "./ProfileNavigation.js"; import { useState } from "preact/hooks"; import { undefinedIfEmpty } from "../utils.js"; import { InputAmount } from "./PaytoWireTransferForm.js"; interface Props { routeMyAccountDetails: RouteDefinition; routeMyAccountDelete: RouteDefinition; routeMyAccountPassword: RouteDefinition; routeMyAccountCashout: RouteDefinition; routeConversionConfig: RouteDefinition; routeCancel: RouteDefinition; onUpdateSuccess: () => void; } type FormType = { [k in keyof T]: string | undefined; } type ErrorsType = { [k in keyof T]?: TranslatedString; } type FormHandler = { [k in keyof T]?: { value: string | undefined; onUpdate: (s: string) => void; error: TranslatedString | undefined; } } function useFormState(defaultValue: FormType, validate: (f: FormType) => ErrorsType): FormHandler { const [form, updateForm] = useState>(defaultValue) const errors = undefinedIfEmpty>(validate(form)) const p = (Object.keys(form) as Array) console.log("FORM", p) const handler = p.reduce((prev, fieldName) => { console.log("fie;d", fieldName) const currentValue = form[fieldName] const currentError = errors !== undefined ? errors[fieldName] : undefined prev[fieldName] = { error: currentError, value: currentValue, onUpdate: (newValue) => { updateForm({ ...form, [fieldName]: newValue }) } } return prev }, {} as FormHandler) return handler } /** * Show histories of public accounts. */ export function ConversionConfig({ routeMyAccountCashout, routeMyAccountDelete, routeMyAccountDetails, routeMyAccountPassword, routeConversionConfig, routeCancel, onUpdateSuccess, }: Props): VNode { const { i18n } = useTranslationContext(); const { state: credentials } = useBackendState(); const creds = credentials.status !== "loggedIn" || !credentials.isUserAdministrator ? undefined : credentials; const { api, config } = useBankCoreApiContext(); const [notification, notify, handleError] = useLocalNotification(); if (!creds) { return
only admin can setup conversion
; } const form = useFormState({ cashin_min_amount: undefined, cashin_tiny_amount: undefined, cashin_fee: undefined, cashin_ratio: undefined, cashin_rounding_mode: undefined, cashout_min_amount: undefined, cashout_tiny_amount: undefined, cashout_fee: undefined, cashout_ratio: undefined, cashout_rounding_mode: undefined, }, (state) => { return ({ cashin_min_amount: !state.cashin_min_amount ? i18n.str`required` : !Amounts.parse(`${config.currency}:${state.cashin_min_amount}`) ? i18n.str`invalid` : undefined, }) }) async function doUpdate() { if (!creds) return await handleError(async () => { const resp = await api .getConversionInfoAPI() .updateConversionRate(creds.token, { } as any) if (resp.type === "ok") { onUpdateSuccess() } else { switch (resp.case) { case HttpStatusCode.Unauthorized: { return notify({ type: "error", title: i18n.str`Wrong credentials`, description: resp.detail.hint as TranslatedString, debug: resp.detail, }); } case HttpStatusCode.NotImplemented: { return notify({ type: "error", title: i18n.str`Conversion is disabled`, description: resp.detail.hint as TranslatedString, debug: resp.detail, }); } default: assertUnreachable(resp); } } }); } return (

Conversion

{ e.preventDefault(); }} >

Only cashout operation above this threshold will be allowed

Smallest difference between two amounts

Operation fee

{ form.cashout_ratio?.onUpdate(e.currentTarget.value); }} autocomplete="off" />

Your current password, for security

Cancel
); }