UNPKG

@coinmeca/ui

Version:

This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

171 lines 9.06 kB
"use client"; "currency"; import { Controls, Elements, Layouts } from "../../../../components"; import { useMobile, useOrder, usePortal } from "../../../../hooks"; import { format } from "../../../../lib/utils"; import { Exchange } from "../../../../prefabs"; import { useEffect, useState } from "react"; export default function Order(props) { const { isMobile } = useMobile(); const mode = typeof props?.mode === "undefined" ? true : props?.mode; const assets = props?.assets || []; const available = parseFloat(format(assets[0]?.balance || 0, "number", true)); const option = props?.option || "market"; const [currency, setCurrency] = useState(0); const currencies = mode ? [assets[1]?.symbol?.toUpperCase() || "", assets[0]?.symbol?.toUpperCase() || ""] : [assets[0]?.symbol?.toUpperCase() || "", assets[1]?.symbol?.toUpperCase() || ""]; const { order, price, amount, quantity, maxQuantity } = useOrder({ pay: assets[0], price: parseFloat(format(props?.price, "number", true)), amount: 0, quantity: 0, fees: 0, total: 0, }, mode, 0.01, available); const color = { buy: props?.color?.buy || "green", sell: props?.color?.sell || "red", }; const gap = { col: { small: 0.5, big: 1, }, row: 2, space: { small: { padding: "0 0.5em" }, big: { padding: "0.5em" }, }, width: 12, }; const text = { height: 1.5, opacity: 0.45, label: { flex: 0 }, setting: { fontFeatureSettings: `"tnum" on,"lnum" on` }, width: { width: "100%", maxWidth: `${gap.width - 5.125}em` }, align: "right", }; const range = { min: 0, max: 100, step: 5, unit: "%", }; useEffect(() => { return () => { closePricePad(); closeAmountPad(); }; }, []); const [limit, setLimit] = useState(props?.price); useEffect(() => { if (option === "limit") setLimit(order.price); if (typeof props?.onChange === "function") props?.onChange(order); }, [order]); useEffect(() => { if (option === "market") price(parseFloat(format(props?.price, "number", true))); if (option === "limit") price(parseFloat(format(limit, "number", true))); }, [option]); const handleChangePrice = (p) => { price(parseFloat(format(p, "number", true))); }; const handleChangeAmount = (a) => { mode ? currency === 0 ? quantity(parseFloat(format(a, "number", true))) : amount(parseFloat(format(a, "number", true))) : currency === 0 ? amount(parseFloat(format(a, "number", true))) : quantity(parseFloat(format(a, "number", true))); }; const handleChangeRange = (v) => { const a = available; const q = maxQuantity(); if (a && q) { mode ? currency === 0 ? quantity((q * parseFloat(format(v, "number", true))) / 100) : amount((a * parseFloat(format(v, "number", true))) / 100) : currency === 0 ? amount((a * parseFloat(format(v, "number", true))) / 100) : quantity((q * parseFloat(format(v, "number", true))) / 100); } }; const pricePosition = order?.price === 0 ? 0 : (1 - parseFloat(props?.price?.toString()) / order?.price) * 100; const [handlePricePad, closePricePad] = usePortal(<Exchange.BottomSheets.OrderPad label={"Price"} placeholder={order?.price} value={order?.price} unit={[...assets][mode ? 0 : 1]?.symbol} sub={{ color: `${mode ? (pricePosition > 0 && "red") || (pricePosition < 0 && "green") : (pricePosition > 0 && "green") || (pricePosition < 0 && "red")}`, value: `${(pricePosition > 0 && "+ ") || (pricePosition < 0 && "- ") || ""}${Math.abs(pricePosition)}`, unit: "%", }} button={{ children: "OK", onClick: () => closePricePad() }} onChange={(e, v) => handleChangePrice(v)}/>); const [handleAmountPad, closeAmountPad] = usePortal(<Exchange.BottomSheets.OrderPad label={currency === 0 ? "Quantity" : "Amount"} placeholder={"0"} value={currency === 0 ? order?.quantity : order?.amount} unit={[...assets].reverse()[currency]?.symbol} sub={{ value: `= ${format(currency === 0 ? order?.amount : order?.quantity || 0, "currency", { unit: 9, limit: 12, fix: 3 })}`, unit: assets[currency]?.symbol, }} button={{ color: mode ? color.buy : color.sell, children: mode ? "BUY" : "SELL", onClick: () => closeAmountPad(), }} onChange={(e, v) => handleChangeAmount(v)} onClose={() => closeAmountPad()}/>); return (<Layouts.Col gap={gap.col.big} style={{ paddingTop: `${gap.col.small}em` }}> <Layouts.Row gap={gap.row} style={{ ...gap.space.big, overflow: "hidden" }} fix> <Elements.Text height={text.height} opacity={text.opacity} style={text.label} fit> Available </Elements.Text> <Layouts.Row gap={gap.row} fix> <Elements.Text height={text.height} align={"right"} style={text.setting}> {format(assets[0]?.balance, "currency", { unit: 9, limit: 12, fix: 3 })} </Elements.Text> <Elements.Text height={text.height} opacity={text.opacity} style={text.width}> {assets[0]?.symbol} </Elements.Text> </Layouts.Row> </Layouts.Row> <Controls.Input placeholder={props?.price} type={"currency"} align={"right"} value={order?.price} onChange={(e, v) => handleChangePrice(v)} onClick={() => isMobile && handlePricePad()} inputMode={isMobile ? "none" : undefined} left={{ children: <span>Price</span> }} right={{ width: gap.width, children: <span style={{ justifyContent: "flex-start" }}>{assets[mode ? 0 : 1]?.symbol}</span>, }} style={text.setting} lock={option === "market"}/> <Controls.Input placeholder={"0"} type={"currency"} align={"right"} value={mode ? (currency === 0 ? order?.quantity : order?.amount) : currency === 0 ? order?.amount : order?.quantity} max={mode ? (currency === 0 ? maxQuantity() : available) : currency === 0 ? available : maxQuantity()} onChange={(e, v) => handleChangeAmount(v)} onClick={() => isMobile && handleAmountPad()} inputMode={isMobile ? "none" : undefined} left={{ children: <span>{currency === 0 ? "Qunatity" : "Amount"}</span>, }} right={{ width: gap.width, children: (<Controls.Dropdown option={currencies[currency]} options={currencies} onClickItem={(e, v, k) => { setCurrency(k); }} responsive={isMobile}/>), }} style={text.setting}/> <Controls.Range color={mode ? color.buy : color.sell} value={order?.amount !== 0 ? (order?.amount / available) * 100 : 0} min={range.min} max={range.max} step={range.step} unit={range.unit} onChange={(v, p) => handleChangeRange(p)}/> <Layouts.Col gap={gap.col.big}> <Layouts.Row gap={gap.row} style={gap.space.small} fix> <Elements.Text height={text.height} opacity={text.opacity} style={text.label} fit> Fees </Elements.Text> <Layouts.Row gap={gap.row} fix> <Elements.Text height={text.height} align={"right"} style={text.setting}> - {format(order?.fees, "currency", { unit: 9, limit: 12, fix: 3 })} </Elements.Text> <Elements.Text height={text.height} opacity={text.opacity} style={text.width}> {assets[1]?.symbol} </Elements.Text> </Layouts.Row> </Layouts.Row> <Layouts.Row gap={gap.row} style={gap.space.small} fix> <Elements.Text height={text.height} opacity={text.opacity} style={text.label} fit> Total </Elements.Text> <Layouts.Row gap={gap.row} fix> <Elements.Text height={text.height} align={"right"} style={text.setting}> {format(order?.total, "currency", { unit: 9, limit: 12, fix: 3 })} </Elements.Text> <Elements.Text height={text.height} opacity={text.opacity} style={text.width}> {assets[1]?.symbol} </Elements.Text> </Layouts.Row> </Layouts.Row> </Layouts.Col> </Layouts.Col>); } //# sourceMappingURL=Order.jsx.map