Newer
Older
CrypticOreWallet / src / pages / transactions / send / SendTransactionForm.tsx
@Drew Lemmy Drew Lemmy on 12 Mar 2021 3 KB feat: minor progress on tx form
// 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
  };
}