// Copyright (c) 2020-2021 Drew Lemmy // This file is part of KristWeb 2 under GPL-3.0. // Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt import React, { useState } from "react"; import { Form, FormInstance, Input, InputNumber, Button } from "antd"; import { useTranslation } from "react-i18next"; import { useWallets } from "@wallets"; import { useCurrency } from "@utils/currency"; import { AddressPicker } from "@comp/addresses/picker/AddressPicker"; import { KristSymbol } from "@comp/krist/KristSymbol"; export interface FormValues { from: string; to: string; value: number; metadata?: string; } interface Props { form: FormInstance<FormValues>; triggerSubmit: () => Promise<void>; } function SendTransactionForm({ form, triggerSubmit }: Props): JSX.Element { const { t } = useTranslation(); // Used to get the initial wallet to show for the 'from' field // TODO: Remember this value? const { addressList, walletAddressMap } = useWallets(); const initialFrom = addressList[0] || ""; // TODO: initialFrom here should never be an empty string, so need to add a // modal that says "You currently don't have any saved wallets" etc, // and prevents opening the sendTX modal/rendering the page // Used to format the 'amount' field const { currency_symbol } = useCurrency(); const [from, setFrom] = useState(initialFrom); const [to, setTo] = useState(""); function onValuesChange(_: unknown, values: Partial<FormValues>) { setFrom(values.from || ""); setTo(values.to || ""); } return <Form // The form instance is managed by the parent, so that it has control over // the behaviour of resetting. For example, a modal dialog would want to // reset the form values when the modal closes. It gets created by the // `useTransactionForm` hook. form={form} layout="vertical" name="sendTransaction" initialValues={{ from: initialFrom, to: "", value: 1, metadata: "" }} onValuesChange={onValuesChange} onFinish={triggerSubmit} > {/* From */} <AddressPicker walletsOnly name="from" label={t("sendTransaction.labelFrom")} value={from} /> {/* To */} <AddressPicker name="to" label={t("sendTransaction.labelTo")} value={to} otherPickerValue={from === undefined ? initialFrom : from} /> {/* Amount */} <Form.Item label={t("sendTransaction.labelValue")}> <Input.Group compact style={{ display: "flex" }}> {/* Prepend the Krist symbol if possible. Note that ant's InputNumber * doesn't support addons, so this has to be done manually. */} {(currency_symbol || "KST") === "KST" && ( <span className="ant-input-group-addon"><KristSymbol /></span> )} {/* Value/amount number input */} <Form.Item name="value" style={{ flex: 1, marginBottom: 0 }} > <InputNumber type="number" min={1} style={{ width: "100%", height: 32 }} /> </Form.Item> {/* Max value button */} <Button>{t("sendTransaction.buttonMax")}</Button> </Input.Group> </Form.Item> </Form>; } interface TransactionFormHookResponse { form: FormInstance<FormValues>; triggerSubmit: () => Promise<void>; isSubmitting: boolean; txForm: JSX.Element; } export function useTransactionForm(): TransactionFormHookResponse { const [form] = Form.useForm<FormValues>(); const [isSubmitting, setIsSubmitting] = useState(false); async function onSubmit() { setIsSubmitting(true); try { const values = await form.validateFields(); console.log(values); } finally { setTimeout(() => setIsSubmitting(false), 1000); } } // Create the transaction form instance here to be rendered by the caller const txForm = <SendTransactionForm form={form} triggerSubmit={onSubmit} />; return { form, triggerSubmit: onSubmit, isSubmitting, txForm }; }