177 lines
5.5 KiB
TypeScript
177 lines
5.5 KiB
TypeScript
import React, { useState } from "react";
|
|
import type { FC } from "react";
|
|
import { graphql } from "babel-plugin-relay/macro";
|
|
import { useLazyLoadQuery } from "react-relay";
|
|
import { BigNumber } from "bignumber.js";
|
|
import cx from "classnames";
|
|
|
|
import { useCurrentUser } from "../../../contexts/UserProvider";
|
|
import { Unauthenticated } from "../../../messages/Unauthenticated";
|
|
import type { ExchangeQuery } from "./__generated__/ExchangeQuery.graphql";
|
|
|
|
const tabBaseStyles =
|
|
"w-full text-base font-bold text-black px-4 py-2 focus:ring-blue-500";
|
|
|
|
const selectedTabStyles =
|
|
"bg-blue-600 hover:bg-blue-700 rounded-l-frounded-full text-white";
|
|
|
|
const inputBaseStyles =
|
|
"rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent mb-3";
|
|
|
|
export const Exchange: FC = () => {
|
|
const { isAuthenticated } = useCurrentUser();
|
|
const [exchangeOption, setExchangeOption] = useState<"BUY" | "SELL">("BUY");
|
|
const [cryptoDock, setCryptoDock] = useState<string>("0");
|
|
const [fiatDock, setFiatDock] = useState<string>("0.00");
|
|
|
|
const { balances, fiatBalances } = useLazyLoadQuery<ExchangeQuery>(
|
|
graphql`
|
|
query ExchangeQuery {
|
|
fiatBalances {
|
|
edges {
|
|
node {
|
|
amountCents
|
|
}
|
|
}
|
|
}
|
|
balances {
|
|
edges {
|
|
node {
|
|
amount
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
{}
|
|
);
|
|
|
|
if (!isAuthenticated) return <Unauthenticated />;
|
|
const [crypto] = balances.edges;
|
|
const [fiat] = fiatBalances.edges;
|
|
|
|
const avaliableCrypto = new BigNumber(crypto.node.amount);
|
|
const avaliableFiat = (
|
|
fiat.node.amountCents ? fiat.node.amountCents / 100 : 0
|
|
).toFixed(2);
|
|
|
|
const handleSellTabClick = () => {
|
|
setExchangeOption("SELL");
|
|
setCryptoDock("0");
|
|
};
|
|
|
|
const handleBuyTabClick = () => {
|
|
setExchangeOption("BUY");
|
|
setCryptoDock("0");
|
|
};
|
|
|
|
const handleCryptoAmountChange = ({
|
|
currentTarget: { value },
|
|
}: React.ChangeEvent<HTMLInputElement>) => {
|
|
const newCryptoAmount = new BigNumber(value);
|
|
|
|
if (newCryptoAmount.isLessThanOrEqualTo(avaliableCrypto)) {
|
|
setCryptoDock(value);
|
|
}
|
|
};
|
|
|
|
const handleFiatAmountChange = ({
|
|
currentTarget: { value },
|
|
}: React.ChangeEvent<HTMLInputElement>) => {
|
|
const newFiatAmount = Number(value);
|
|
|
|
if (Number(avaliableFiat) >= newFiatAmount) {
|
|
setFiatDock(value);
|
|
}
|
|
};
|
|
|
|
const handleMaxFiatDockButton = () => {
|
|
setFiatDock(avaliableFiat);
|
|
};
|
|
|
|
const handleMaxCryptoButton = () => {
|
|
setCryptoDock(avaliableCrypto.toString());
|
|
};
|
|
|
|
return (
|
|
<div className="grid place-items-center w-full">
|
|
<div className="max-w-lg">
|
|
<div className="flex items-center bg-white rounded-full border border-gray-200 mb-3">
|
|
<button
|
|
type="button"
|
|
className={cx(
|
|
tabBaseStyles,
|
|
"rounded-full",
|
|
exchangeOption === "BUY" && selectedTabStyles
|
|
)}
|
|
onClick={handleBuyTabClick}
|
|
>
|
|
Comprar
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className={cx(
|
|
tabBaseStyles,
|
|
"rounded-full",
|
|
exchangeOption === "SELL" && selectedTabStyles
|
|
)}
|
|
onClick={handleSellTabClick}
|
|
>
|
|
Vender
|
|
</button>
|
|
</div>
|
|
<form className="bg-white p-4 rounded-2xl border border-gray-200">
|
|
<span className="mb-2">
|
|
{exchangeOption === "SELL" ? "CAKE" : "BRL"} disponível:{" "}
|
|
{exchangeOption === "SELL" ? crypto.node.amount : avaliableFiat}
|
|
</span>
|
|
<div className="flex flex-row">
|
|
{exchangeOption === "BUY" ? (
|
|
<>
|
|
<input
|
|
className={cx(inputBaseStyles)}
|
|
type="number"
|
|
value={fiatDock}
|
|
onChange={handleFiatAmountChange}
|
|
/>
|
|
<button
|
|
type="button"
|
|
disabled={fiatDock === avaliableFiat}
|
|
className="flex items-center mb-3 ml-3 font-bold rounded-full text-red-500"
|
|
onClick={handleMaxFiatDockButton}
|
|
>
|
|
Max
|
|
</button>
|
|
</>
|
|
) : (
|
|
<>
|
|
<input
|
|
className={cx(inputBaseStyles)}
|
|
type="number"
|
|
value={cryptoDock}
|
|
onChange={handleCryptoAmountChange}
|
|
/>
|
|
<button
|
|
type="button"
|
|
disabled={avaliableCrypto.isEqualTo(cryptoDock)}
|
|
className="flex items-center mb-3 ml-3 font-bold rounded-full text-red-500"
|
|
onClick={handleMaxCryptoButton}
|
|
>
|
|
Max
|
|
</button>
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
<button
|
|
className="cursor-pointer py-2 px-4 bg-blue-600 hover:bg-blue-700 focus:ring-blue-500 focus:ring-offset-blue-200 text-white w-full transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg"
|
|
type="submit"
|
|
>
|
|
{exchangeOption === "BUY" ? "Comprar" : "Vender"} CAKE
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|