Skip to content

Commit

Permalink
simulator input
Browse files Browse the repository at this point in the history
  • Loading branch information
pingustar committed Jan 29, 2024
1 parent df4910a commit 8a03443
Show file tree
Hide file tree
Showing 29 changed files with 1,487 additions and 349 deletions.
109 changes: 109 additions & 0 deletions src/components/simulator/BuySellBlockNew/BudgetSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { Tooltip } from 'components/common/tooltip/Tooltip';
import {
StrategyInputDispatch,
StrategyInputOrder,
} from 'hooks/useStrategyInput';
import { Token } from 'libs/tokens';
import { capitalize } from 'lodash';
import { FC, useEffect, useId } from 'react';
import { StrategyType } from 'libs/routing';
import { TokenInputField } from 'components/common/TokenInputField/TokenInputField';
import { UseQueryResult } from '@tanstack/react-query';
import { SafeDecimal } from 'libs/safedecimal';
import { ReactComponent as IconWarning } from 'assets/icons/warning.svg';

interface Props {
base: Token;
quote: Token;
order: StrategyInputOrder;
dispatch: StrategyInputDispatch;
strategyType?: StrategyType;
tokenBalanceQuery?: UseQueryResult<string>;
isBudgetOptional?: boolean;
buy?: boolean;
}

export const BudgetSection: FC<Props> = ({
buy,
quote,
base,
strategyType,
order,
dispatch,
isBudgetOptional,
tokenBalanceQuery,
}) => {
const inputId = useId();
const type = buy ? 'buy' : 'sell';
const budgetToken = buy ? quote : base;
const insufficientBalance =
tokenBalanceQuery &&
!tokenBalanceQuery?.isLoading &&
new SafeDecimal(tokenBalanceQuery?.data || 0).lt(order.budget);

useEffect(() => {
if (tokenBalanceQuery?.data) return;
if (insufficientBalance) {
dispatch(`${type}BudgetError`, 'Insufficient balance');
} else {
dispatch(`${type}BudgetError`, '');
}
}, [insufficientBalance, type, dispatch, tokenBalanceQuery?.data]);

return (
<fieldset className="flex flex-col gap-8">
<legend className="mb-11 flex items-center gap-6 text-14 font-weight-500">
<span className="flex h-16 w-16 items-center justify-center rounded-full bg-white/10 text-[10px] text-white/60">
2
</span>
<Tooltip
sendEventOnMount={{ buy }}
element={
buy
? `The amount of ${
quote.symbol
} tokens you would like to use in order to buy ${
base.symbol
}. ${
strategyType === 'recurring'
? 'Note: this amount will re-fill once the "Sell" order is used by traders.'
: ''
}`
: `The amount of ${base.symbol} tokens you would like to sell. ${
strategyType === 'recurring'
? 'Note: this amount will re-fill once the "Buy" order is used by traders.'
: ''
}`
}
>
<span className="text-white/80">Set {capitalize(type)} Budget</span>
</Tooltip>
{isBudgetOptional && (
<span className="ml-8 font-weight-500 text-white/60">Optional</span>
)}
</legend>
<TokenInputField
id={inputId}
className="rounded-16 bg-black p-16"
value={order.budget}
setValue={(value) => dispatch(`${type}Budget`, value)}
token={budgetToken}
isBalanceLoading={tokenBalanceQuery?.isLoading}
balance={tokenBalanceQuery?.data}
isError={insufficientBalance}
data-testid="input-budget"
/>
{insufficientBalance && (
<output
htmlFor={inputId}
role="alert"
aria-live="polite"
className="flex items-center gap-10 font-mono text-12 text-red"
>
<IconWarning className="h-12 w-12" />
<span className="flex-1">Insufficient balance</span>
</output>
)}
</fieldset>
);
};
82 changes: 82 additions & 0 deletions src/components/simulator/BuySellBlockNew/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {
StrategyInputDispatch,
StrategyInputOrder,
} from 'hooks/useStrategyInput';
import { FC, ReactNode } from 'react';
import { Tooltip } from 'components/common/tooltip/Tooltip';
import { Token } from 'libs/tokens';

interface Props {
children: ReactNode;
order: StrategyInputOrder;
dispatch: StrategyInputDispatch;
base: Token;
buy?: boolean;
}

export const BuySellHeader: FC<Props> = (props) => {
const { order, buy, children, base, dispatch } = props;
const { isRange } = order;

const type = buy ? 'buy' : 'sell';

const setLimit = () => {
if (!isRange) return;
dispatch(`${type}IsRange`, false);
// TODO reset fields
// resetFields(true);
};
const setRange = () => {
if (isRange) return;
dispatch(`${type}IsRange`, true);
// TODO reset fields
// resetFields(true);
};

return (
<header className="flex items-center justify-between">
{children}
<div className="flex items-center gap-10 text-14">
<div className="bg-body flex items-center rounded-[100px] p-2">
<button
type="button"
tabIndex={!isRange ? -1 : 0}
onClick={setLimit}
className={`rounded-40 font-weight-500 ${
!isRange ? 'bg-silver' : 'text-secondary'
} px-10 py-4`}
data-testid="tab-limit"
>
Limit
</button>
<button
type="button"
tabIndex={isRange ? -1 : 0}
onClick={setRange}
className={`rounded-40 font-weight-500 ${
isRange ? 'bg-silver' : 'text-secondary'
} px-10 py-4`}
data-testid="tab-range"
>
Range
</button>
</div>
<Tooltip
sendEventOnMount={{ buy }}
element={
<>
This section will define the order details in which you are
willing to {buy ? 'buy' : 'sell'} {base.symbol} at.
<br />
<b>Limit</b> will allow you to define a specific price point to{' '}
{buy ? 'buy' : 'sell'} the token at.
<br />
<b>Range</b> will allow you to define a range of prices to{' '}
{buy ? 'buy' : 'sell'} the token at.
</>
}
/>
</div>
</header>
);
};
105 changes: 105 additions & 0 deletions src/components/simulator/BuySellBlockNew/InputLimit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { ChangeEvent, FC, FocusEvent, useId } from 'react';
import { carbonEvents } from 'services/events';
import { useFiatCurrency } from 'hooks/useFiatCurrency';
import { Token } from 'libs/tokens';
import { formatNumber, sanitizeNumber } from 'utils/helpers';
import { decimalNumberValidationRegex } from 'utils/inputsValidations';
import { ReactComponent as IconWarning } from 'assets/icons/warning.svg';
import { MarketPriceIndication } from 'components/strategies/marketPriceIndication';
import { MarketPricePercentage } from 'components/strategies/marketPriceIndication/useMarketIndication';

type InputLimitProps = {
id?: string;
price: string;
setPrice: (value: string) => void;
token: Token;
error?: string;
setPriceError: (error: string) => void;
buy?: boolean;
marketPricePercentage: MarketPricePercentage;
};

export const InputLimit: FC<InputLimitProps> = ({
id,
price,
setPrice,
token,
error,
setPriceError,
marketPricePercentage,
buy = false,
}) => {
const inputId = useId();

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = sanitizeNumber(e.target.value);
if (Number(value) > 0) {
setPriceError('');
} else {
const errorMessage = 'Price must be greater than 0';
carbonEvents.strategy.strategyErrorShow({
buy,
message: errorMessage,
});
setPriceError(errorMessage);
}
setPrice(value);
};
const handleBlur = (e: FocusEvent<HTMLInputElement>) => {
const formatted = formatNumber(e.target.value);
if (formatted !== e.target.value) setPrice(formatted);
};

const { getFiatAsString } = useFiatCurrency(token);
const fiatAsString = getFiatAsString(price);

return (
<>
<div
className={`
bg-body flex cursor-text flex-col rounded-16 border p-16
focus-within:border-white/50
${error ? '!border-red/50' : 'border-black'}
`}
onClick={() => document.getElementById(id ?? inputId)?.focus()}
>
<input
id={id ?? inputId}
type="text"
pattern={decimalNumberValidationRegex}
inputMode="decimal"
value={price}
onChange={handleChange}
onFocus={(e) => e.target.select()}
onBlur={handleBlur}
aria-label="Enter Price"
placeholder="Enter Price"
className={`
mb-5 w-full text-ellipsis bg-transparent text-start text-18 font-weight-500 focus:outline-none
${error ? 'text-red' : ''}
`}
data-testid="input-price"
/>
<p className="flex flex-wrap items-center gap-8">
<span className="break-all font-mono text-12 text-white/60">
{fiatAsString}
</span>
<MarketPriceIndication
marketPricePercentage={marketPricePercentage.price}
/>
</p>
</div>
{error && (
<output
htmlFor={id ?? inputId}
role="alert"
aria-live="polite"
className="flex items-center gap-10 font-mono text-12 text-red"
>
<IconWarning className="h-12 w-12" />
<span className="flex-1">{error}</span>
</output>
)}
</>
);
};
Loading

0 comments on commit 8a03443

Please sign in to comment.