import React, { FocusEventHandler, ReactNode, useCallback, useEffect, useMemo, } from "react"; import { ControllerProps, ControllerRenderProps, FieldErrors, } from "react-hook-form"; import { Asset, useAssets } from "../useAssets"; import { useDisplayDecimalDigits } from "../useDisplayDecimalDigits"; import { BuySellContext, BuySellFormProps } from "./context"; import { useBuySellAmountValidation } from "./useBuySellAmountValidation"; import { useBuySellMarketConfigs } from "./useBuySellConfigs"; import { useUpdatePreview } from "./useUpdatePreview"; type BuySpendRenderProps = { render: (state: { field: ControllerRenderProps & { assets: Asset[]; asset?: Asset; minQuantity: number; hasError?: boolean; maxQuantity: number; availableRemain?: number | string; onSelect?: (value?: Asset | undefined) => void; onFocus?: (e: FocusEventHandler | undefined) => void; getMaxSize?: (value: number) => string | number; stepSize?: number; }; }) => React.ReactElement; renderErrorComponent?: (message?: string) => ReactNode; }; export const BuySpendController = ({ render, renderErrorComponent, }: BuySpendRenderProps) => { const { request, resetRefreshCount } = useUpdatePreview({ mode: "from", type: "buy", }); // const { control } = BuySellContext.useFormContext(); // const [ lastChangedField] = useWatch({ // name: ["fromAsset", "toAsset", "lastChangedField"], // control, // defaultValue: { // lastChangedField: "from", // }, // }); const { setValue, clearErrors, register } = BuySellContext.useFormContext(); const { lastChangedField } = BuySellContext.useWatch(); // console.log({1:lastChangedField}) const { getValues } = BuySellContext.useFormContext(); const { allAssets } = useAssets(); const { filterPrice, getMaxSize, selectedCurrency } = useBuySellMarketConfigs( { mode: "from", }, ); const { truncFix } = useDisplayDecimalDigits(); const { minimumFrom, maximumFrom, checkAmount } = useBuySellAmountValidation(); const assets = useMemo(() => { return allAssets?.filter((i) => i.canCharge); }, [allAssets]); useEffect(() => { const { fromAsset } = getValues(); if (fromAsset === undefined) { const symbol = assets?.[0].symbol; setValue("fromAsset", symbol); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [assets]); register("shouldCharge"); const clearFormErrors = useCallback( (errors: FieldErrors) => { if (Object.values(errors).length > 0) { clearErrors(); } }, // eslint-disable-next-line react-hooks/exhaustive-deps [], ); const rules = useMemo( () => ({ validate: { check: (value: string | null | undefined) => checkAmount({ value, mode: "from", }), }, }), [checkAmount], ); const renderForm: ControllerProps["render"] = useCallback( ({ field: { onChange, value, ...rest }, formState, fieldState }) => { return ( <> {render({ field: { value: value, assets: assets || [], availableRemain: truncFix( selectedCurrency?.availableRemain || 0, selectedCurrency?.symbol, ), minQuantity: minimumFrom || 0, maxQuantity: maximumFrom || 0, asset: selectedCurrency, hasError: value ? !!fieldState.error : false, getMaxSize: getMaxSize, async onSelect(asset?: Asset) { if (selectedCurrency?.symbol !== asset?.symbol) { onChange(""); setValue("toAmount", ""); const symbol = await new Promise( (res) => { res(asset?.symbol); }, ); setValue("fromAsset", symbol); clearFormErrors(formState.errors); } }, onFocus() { lastChangedField !== "from" && setValue("lastChangedField", "from"); }, onChange(value) { onChange(value); if (value === "") { setValue("toAmount", ""); } clearFormErrors(formState.errors); request(); resetRefreshCount(); lastChangedField !== "from" && setValue("lastChangedField", "from"); }, stepSize: filterPrice?.tickSize, ...rest, }, })} {renderErrorComponent && renderErrorComponent( fieldState.error ? fieldState.error.message : "", )} ); }, // eslint-disable-next-line react-hooks/exhaustive-deps [ assets, clearFormErrors, filterPrice?.tickSize, getMaxSize, lastChangedField, maximumFrom, minimumFrom, render, selectedCurrency, truncFix, resetRefreshCount, ], ); return ( ); };