@fortawesome/free-solid-svg-icons#faExclamationTriangle JavaScript Examples
The following examples show how to use
@fortawesome/free-solid-svg-icons#faExclamationTriangle.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AlertPanel.jsx From ashteki with GNU Affero General Public License v3.0 | 6 votes |
AlertPanel = ({ type = AlertType.Info, title, message, noIcon = false, children }) => {
let icon;
/**
* @type {AlertType}
*/
let alertType;
switch (type) {
case AlertType.Warning:
icon = faExclamationTriangle;
alertType = 'warning';
break;
case AlertType.Danger:
icon = faExclamationCircle;
alertType = 'danger';
break;
case AlertType.Info:
icon = faInfoCircle;
alertType = 'info';
break;
case AlertType.Success:
icon = faCheckCircle;
alertType = 'success';
break;
}
return (
<Alert variant={alertType}>
{title && <Alert.Heading>{title}</Alert.Heading>}
{!noIcon && <FontAwesomeIcon icon={icon} />}
{message && <span id='alert-message'> {getMessageWithLinks(message)}</span>}
{children && <span> {children}</span>}
</Alert>
);
}
Example #2
Source File: Icon.js From mailmask with GNU Affero General Public License v3.0 | 6 votes |
ICONS = {
bars: faBars,
'check-circle': faCheckCircle,
'chevron-down': faChevronDown,
'chevron-right': faChevronRight,
'exchange-alt': faExchangeAlt,
exclamation: faExclamation,
'exclamation-triangle': faExclamationTriangle,
info: faInfo,
moon: faMoon,
question: faQuestion,
rss: faRss,
'sign-in-alt': faSignInAlt,
sun: faSun,
snowflake: faSnowflake,
star: faStar,
'times-circle': faTimesCircle,
user: faUser,
}
Example #3
Source File: index.jsx From loopring-swap with GNU General Public License v3.0 | 6 votes |
InvalidChainId = () => {
const [chainName, setChainName] = useState("");
useEffect(() => {
let chainName;
switch (CHAIN_ID) {
case 1: {
chainName = "mainnet";
break;
}
case 5: {
chainName = "Goerli";
break;
}
default: {
chainName = "unknown";
}
}
setChainName(chainName);
}, []);
return (
<Flex flexDirection="column" alignItems="center">
<Box mb="20px">
<StyledFontAwesomeIcon icon={faExclamationTriangle} />
</Box>
<Box textAlign="center">
<Text>
<FormattedMessage
id="invalid.chain.id.message"
values={{ chainName }}
/>
</Text>
</Box>
</Flex>
);
}
Example #4
Source File: Alert.jsx From frontend-app-support-tools with GNU Affero General Public License v3.0 | 6 votes |
function getAlertIcon(type) {
if (type === 'error') {
return faExclamationTriangle;
}
if (type === 'danger') {
return faMinusCircle;
}
if (type === 'success') {
return faCheckCircle;
}
return faInfoCircle;
}
Example #5
Source File: Demo404.jsx From react-lte with MIT License | 6 votes |
Demo404 = () => {
return (
<>
<LteContentHeader title='404 Error Page' />
<LteContent>
<div className='error-page'>
<LteText tag='h2' color='warning' className='headline'>
404
</LteText>
<div className='error-content'>
<h3>
<FontAwesomeIcon icon={faExclamationTriangle} className='text-warning' />
<span> Oops! Page not found.</span>
</h3>
<p>
<span>We could not find the page you were looking for. Meanwhile, you may </span>
<Link to='/'>may return to dashboard</Link>
<span> or try using the search form.</span>
</p>
<Form className='search-form'>
<InputGroup>
<Input type='text' placeholder='Search' />
<InputGroupAddon addonType='append'>
<Button type='submit' name='submit' color='warning'>
<FontAwesomeIcon icon={faSearch} />
</Button>
</InputGroupAddon>
</InputGroup>
</Form>
</div>
</div>
</LteContent>
</>
);
}
Example #6
Source File: fontawesome.js From xmrig-workers with GNU General Public License v3.0 | 5 votes |
export default function () {
library.add(faGithub, faWindows, faLinux, faTwitter, faReddit, faTelegram, faCheckCircle, faMicrochip, faTrashAlt,
faPaperPlane, faSpinner, faFlask, faInfoCircle, faPen, faTools, faCheck, faPlus, faCog, faExclamationTriangle,
faQuestionCircle, faSyncAlt, faInfinity, faDownload, faCopy, faPlug, faTimesCircle);
}
Example #7
Source File: details.js From amazon-next with MIT License | 4 votes |
export default function Details({ product, error }) {
const dispatch = useDispatch();
const isSelected = useSelector(state =>
state.cart.products.find(
selectedProduct => selectedProduct.id === product.id
)
);
const stars = useMemo(() => {
const initial = [];
for (let i = 1; i < product.stars; i += 1) {
initial.push(
<FontAwesomeIcon
key={i}
size="lg"
className="w-5"
icon={faStar}
color="#e69d3f"
/>
);
}
return initial;
}, [product.stars]);
const liked = useSelector(state =>
state.user.likedProducts.find(
likedProduct => likedProduct.id === product.id
)
);
function handleCart() {
if (isSelected) return dispatch(removeFromCartRequest(product.id));
return dispatch(addToCartRequest(product));
}
function handleLike() {
dispatch(likeProductRequest(product));
}
return (
<Layout>
<motion.div
className={`product-details h-screen px-12 py-8 flex flex-col ${error &&
'justify-center items-center'}`}
exit={{ opacity: 0 }}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
>
{error ? (
<span className="text-xl text-center">
{' '}
<FontAwesomeIcon
icon={faExclamationTriangle}
color="red"
/>{' '}
There was an error while consulting the products{' '}
</span>
) : (
<motion.div className="flex flex-col lg:grid grid-cols-2 h-full py-12 lg:py-0">
<div className="h-full flex flex-col">
<Link href="/">
<div className="cursor-pointer transition-shadows duration-300 hover:shadow shadow-lg mb-5 lg:mb-0 rounded-full text-gray-500 w-12 h-12 flex items-center justify-center p-8">
<FontAwesomeIcon
icon={faArrowLeft}
size="lg"
/>
</div>
</Link>
<motion.img
src={product.image}
alt={product.name}
aria-label={product.name}
title={product.name}
initial={{ opacity: 0, x: -40 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -40 }}
transition={{ delay: 0.2 }}
className="lg:my-12 mx-0 h-300 max-w-480 self-center"
/>
</div>
<motion.div
variants={stagger}
className="h-full flex flex-col justify-between pr-8"
>
<motion.header
initial="fadeup"
animate="normal"
exit="exit"
>
<motion.h1
variants={fadeUp}
className="text-2xl mb-2 text-gray-800 font-bold"
>
{product.name}
</motion.h1>
<motion.div
variants={fadeUp}
className="flex flex-row"
>
{stars}{' '}
<span className="ml-2 font-light text-yellow-burn">
1540 reviews
</span>
</motion.div>
<motion.p
variants={fadeUp}
className="text-md text-gray-500 mt-8"
>
<DangerousHTML html={product.description} />
</motion.p>
</motion.header>
<motion.footer
variants={fadeUp}
initial="fadeup"
animate="normal"
exit="exit"
className="flex flex-col lg:flex-row w-full justify-between pt-5 pb-8"
>
<div className="flex flex-col">
<span className="text-gray-500">
Best price
</span>
<strong className="text-3xl text-gray-800">
${product.price / 100}
</strong>
</div>
<div className="flex flex-row items-center mt-5 lg:mt-0">
<Button
className="font-bold text-xl px-12 flex items-center justify-center lg:w-300 box-border"
title="Add to cart"
handleClick={handleCart}
>
{' '}
{isSelected
? 'Remove from cart'
: 'Add to cart'}
</Button>
<motion.button
className="ml-5 border-none bg-none outline-none"
type="button"
title="Save to my list"
onClick={handleLike}
whileTap={{ y: -10 }}
>
{liked ? (
<FontAwesomeIcon
size="lg"
icon={faHeart}
className="text-blue-500 hover:text-blue-600 transition-colors duration-500"
/>
) : (
<FontAwesomeIcon
size="lg"
icon={faHeartRegular}
className="text-blue-500 hover:text-blue-600 transition-colors duration-500"
/>
)}
</motion.button>
</div>
</motion.footer>
</motion.div>
</motion.div>
)}
</motion.div>
</Layout>
);
}
Example #8
Source File: index.js From amazon-next with MIT License | 4 votes |
function Home({ productList, error }) {
return (
<Layout>
{!error && Object.keys(productList).length > 0 ? (
<motion.div
initial={{ opacity: 0 }}
animate={{
opacity: 1,
transition: { staggerChildren: 5 },
}}
exit={{ opacity: 1 }}
className="w-full py-16 px-5 lg:py-0 lg:px-0"
>
<motion.div
variants={slide}
initial="initial"
animate="slidein"
exit="slideout"
key="technology"
className="mb-8 w-full"
>
<motion.h2
variants={slide}
initial="initial"
animate="slidein"
exit="slideout"
className="text-2xl mb-2 lg:pr-8 pr-0 text-gray-800 font-bold"
>
{' '}
Computers and Accessories{' '}
</motion.h2>
<ProductList
type="computersAndAccessories"
productList={productList}
/>
</motion.div>
<motion.div
variants={slide}
initial="initial"
animate="slidein"
exit="slideout"
key="videogames"
className="w-full my-8"
>
<motion.h2
variants={slide}
initial="initial"
animate="slidein"
exit="slideout"
className="text-2xl mb-2 lg:pr-8 pr-0 text-gray-800 font-bold"
>
{' '}
Video Games{' '}
</motion.h2>
<ProductList
type="videoGames"
productList={productList}
/>
</motion.div>
<motion.div
variants={slide}
initial="initial"
animate="slidein"
exit="slideout"
key="topsellers"
transition="transition"
className="w-full pb-5"
>
<motion.h2
variants={slide}
initial="initial"
animate="slidein"
exit="slideout"
className="text-2xl mb-2 lg:pr-8 pr-0 text-gray-800 font-bold"
>
{' '}
Amazon Top Sellers{' '}
</motion.h2>
<ProductList
type="topSellers"
productList={productList}
/>
</motion.div>
</motion.div>
) : (
<span className="text-xl text-center">
{' '}
<FontAwesomeIcon
icon={faExclamationTriangle}
color="red"
/>{' '}
There was an error while consulting the products{' '}
</span>
)}
</Layout>
);
}
Example #9
Source File: index.jsx From loopring-swap with GNU General Public License v3.0 | 4 votes |
TokenModal = ({
loading,
open,
onClose,
onRefresh,
onChange,
supportedTokens,
balances,
selected,
loggedIn,
}) => {
const { formatMessage, formatNumber } = useIntl();
const contentRef = useRef(null);
const [searchTerm, setSearchTerm] = useState("");
const [tokenDataset, setTokenDataset] = useState(supportedTokens);
useEffect(() => {
let dataset = supportedTokens;
if (searchTerm) {
dataset = dataset.filter(({ symbol, name, address }) => {
const lowerCasedSearchTerm = searchTerm.toLowerCase();
return (
symbol.toLowerCase().includes(lowerCasedSearchTerm) ||
name.toLowerCase().includes(lowerCasedSearchTerm) ||
address.toLowerCase().includes(lowerCasedSearchTerm)
);
});
}
if (balances) {
dataset = dataset.sort(
({ address: firstAddress }, { address: secondAddress }) => {
const wrappedFirstTokenBalance = balances.find(
(balance) => balance.address === firstAddress
);
const wrappedSecondTokenBalance = balances.find(
(balance) => balance.address === secondAddress
);
const firstTokenBalance = new BigNumber(
wrappedFirstTokenBalance &&
wrappedFirstTokenBalance.balance
? wrappedFirstTokenBalance.balance
: "0"
);
const secondTokenBalance = new BigNumber(
wrappedSecondTokenBalance &&
wrappedSecondTokenBalance.balance
? wrappedSecondTokenBalance.balance
: "0"
);
return secondTokenBalance
.minus(firstTokenBalance)
.toNumber();
}
);
}
setTokenDataset(dataset);
}, [searchTerm, supportedTokens, balances]);
const getClickHandler = (token) => () => {
onChange(token);
handleLocalClose();
};
const handleLocalClose = useCallback(() => {
onClose();
setTimeout(() => {
setTokenDataset(supportedTokens);
setSearchTerm("");
}, OPEN_CLOSE_ANIMATION_DURATION);
}, [onClose, supportedTokens]);
const handleLocalCloseOnOutsideClick = useCallback(
(event) => {
if (!contentRef.current.contains(event.target)) {
handleLocalClose();
}
},
[handleLocalClose]
);
const handleSearchTermChange = useCallback((event) => {
setSearchTerm(event.target.value);
}, []);
return (
<>
<FullScreenOverlay open={open} />
<RootFlex open={open} onClick={handleLocalCloseOnOutsideClick}>
<ContentFlex
ref={contentRef}
maxWidth="440px"
flexDirection="column"
>
<SearchFlex mt="4px">
<Box mr={3}>
<FontAwesomeIcon icon={faSearch} />
</Box>
<Box flex={1}>
<Input
value={searchTerm}
onChange={handleSearchTermChange}
placeholder={formatMessage({
id: "token.modal.searchbar.placeholder",
})}
/>
</Box>
{loggedIn && (
<PointableBox ml={3} p={2} minWidth="auto">
<FontAwesomeIcon
icon={faSync}
onClick={onRefresh}
/>
</PointableBox>
)}
<PointableBox ml={3} p={2}>
<FontAwesomeIcon
icon={faTimes}
onClick={handleLocalClose}
/>
</PointableBox>
</SearchFlex>
{loading ? (
<Flex justifyContent="center" mb={4} mt={2}>
<Box>
<Spinner size={40} />
</Box>
</Flex>
) : (
<>
<ListFlex
flexDirection="column"
px="12px"
py="12px"
>
{tokenDataset.length > 0 ? (
tokenDataset.map((token) => {
const { address, symbol, name } = token;
const currentlySelected =
selected === token;
const wrappedBalance = balances.find(
(balance) =>
balance.address === address
);
const etherBalance = new BigNumber(
wrappedBalance &&
wrappedBalance.balance
? wrappedBalance.balance
: "0"
);
return (
<RowFlex
key={address}
alignItems="center"
py={16}
pl="12px"
pr="16px"
onClick={getClickHandler(token)}
selected={currentlySelected}
>
<Box mr={3}>
<TokenIcon
address={address}
size={32}
/>
</Box>
<Flex
alignItems="center"
justifyContent="space-between"
flex={1}
>
<Flex flexDirection="column">
<PrimaryTextBox
mb="2px"
selected={
currentlySelected
}
>
{symbol}
</PrimaryTextBox>
<SecondaryTextBox
selected={
currentlySelected
}
>
{name}
</SecondaryTextBox>
</Flex>
<Box>
{etherBalance.isZero()
? "-"
: formatNumber(
etherBalance,
{
style:
"decimal",
maximumSignificantDigits: 4,
}
)}
</Box>
</Flex>
</RowFlex>
);
})
) : (
<Flex
flexDirection="column"
alignItems="center"
my={3}
px={3}
>
<Box mb={3}>
<EmptyIcon
icon={faExclamationTriangle}
/>
</Box>
<EmptyTextBox textAlign="center" mb={3}>
<FormattedMessage id="token.modal.empty" />
</EmptyTextBox>
</Flex>
)}
</ListFlex>
</>
)}
</ContentFlex>
</RootFlex>
</>
);
}
Example #10
Source File: index.jsx From loopring-swap with GNU General Public License v3.0 | 4 votes |
Swapper = ({ onConnectWalletClick }) => {
const { formatNumber } = useIntl();
const dispatch = useDispatch();
const {
loopringAccount,
loopringExchange,
loopringWallet,
supportedTokens,
loadingSupportedTokens,
loadingBalances,
supportedMarkets,
balances,
loggedIn,
swapData,
loadingSwapData,
loadingSwapSubmission,
} = useSelector((state) => ({
loopringAccount: state.loopring.account,
loopringExchange: state.loopring.exchange,
loopringWallet: state.loopring.wallet,
supportedTokens: state.loopring.supportedTokens.data,
loadingSupportedTokens: !!state.loopring.supportedTokens.loadings,
loadingBalances: !!state.loopring.balances.loadings,
supportedMarkets: state.loopring.supportedMarkets.data,
balances: state.loopring.balances.data,
loggedIn: !!state.loopring.account,
swapData: state.loopring.swap.data,
loadingSwapData: !!state.loopring.swap.loadings,
loadingSwapSubmission: !!state.loopring.swapSubmission.loadings,
}));
const [fromToken, setFromToken] = useState(null);
const [fromAmount, setFromAmount] = useState("");
const [liquidityError, setLiquidityError] = useState(null);
const [balanceError, setBalanceError] = useState(null);
const [lessThanMinimumOrderError, setLessThanMinimumOrderError] = useState(
null
);
const [moreThanMaximumOrderError, setMoreThanMaximumOrderError] = useState(
null
);
const [toToken, setToToken] = useState(null);
const [toAmount, setToAmount] = useState("");
const [feeAmount, setFeeAmount] = useState("");
const [filteredToTokens, setFilteredToTokens] = useState([]);
const [compatibleMarkets, setCompatibleMarkets] = useState([]);
const [changingToAmount, setChangingToAmount] = useState(false);
const [changingFromAmount, setChangingFromAmount] = useState(false);
const [selling, setSelling] = useState(false);
const [flippedPriceNotation, setFlippedPriceNotation] = useState(false);
const [debouncedGetSwapData] = useDebouncedCallback(
(
wallet,
account,
fromToken,
toToken,
fromAmount,
supportedTokens,
selling
) => {
dispatch(
getSwapData(
wallet,
account,
fromToken,
toToken,
fromAmount,
supportedTokens,
selling
)
);
},
500
);
useEffect(() => {
if (loggedIn) {
setFromAmount("");
setToAmount("");
dispatch(resetSwapData());
setLiquidityError(false);
setBalanceError(false);
setLessThanMinimumOrderError(false);
setMoreThanMaximumOrderError(false);
}
}, [dispatch, loggedIn]);
// set ether as the default "from" token
useEffect(() => {
if (supportedTokens && supportedTokens.length > 0 && !fromToken) {
setFromToken(
supportedTokens.find((token) => token.symbol === "ETH")
);
}
}, [fromToken, supportedTokens]);
// on "from" token change, find out the compatible markets
useEffect(() => {
if (supportedMarkets && supportedMarkets.length > 0 && fromToken) {
setCompatibleMarkets(
supportedMarkets.filter(
(market) =>
market.quoteTokenId === fromToken.tokenId ||
market.baseTokenId === fromToken.tokenId
)
);
}
}, [fromToken, supportedMarkets]);
// on "from" token change, we need to find the compatible "to" tokens based on available markets.
// Plus, we reset the currently selected "to" token if it's not compatible with the current "from" one.
useEffect(() => {
if (supportedMarkets && supportedMarkets.length > 0 && fromToken) {
const filteredToTokens = supportedTokens.filter(
(token) =>
token.tokenId !== fromToken.tokenId &&
compatibleMarkets.find(
(market) =>
market.baseTokenId === token.tokenId ||
market.quoteTokenId === token.tokenId
)
);
if (
filteredToTokens &&
filteredToTokens.length > 0 &&
toToken &&
!filteredToTokens.find(
(token) => token.tokenId === toToken.tokenId
)
) {
setToToken(filteredToTokens[0]);
setToAmount("");
}
setFilteredToTokens(filteredToTokens);
}
}, [
compatibleMarkets,
fromToken,
supportedMarkets,
supportedTokens,
toToken,
]);
// on valid "from" and "to" tokens setting, we need to find their current exchange rate
useEffect(() => {
if (
supportedTokens &&
supportedTokens.length > 0 &&
fromToken &&
toToken &&
!liquidityError &&
// when the exchange rate is used to calculate the expected to or from token amount,
// and that is enforced on the component's state, this effect is invoked again and again
// until the currently fetched exchange rate is the same as the previous.
// In particularly traded markets, where the order book changes often, this produces an
// annoying flickering effect. We avoid it by calculating from and to amounts only if
// an actual user interacted with the form (NOT when the app updates the to and
// from amounts after swap-details-related calculations)
((!changingFromAmount &&
!changingToAmount &&
fromAmount &&
toAmount) ||
(changingFromAmount && fromAmount) ||
(changingToAmount && toAmount))
) {
const tradedMarket = compatibleMarkets.find(
(market) =>
(market.baseTokenId === toToken.tokenId &&
market.quoteTokenId === fromToken.tokenId) ||
(market.baseTokenId === fromToken.tokenId &&
market.quoteTokenId === toToken.tokenId)
);
if (!tradedMarket) {
return;
}
debouncedGetSwapData(
loopringWallet,
loopringAccount,
supportedTokens.find(
(token) => token.tokenId === tradedMarket.baseTokenId
),
supportedTokens.find(
(token) => token.tokenId === tradedMarket.quoteTokenId
),
fromAmount,
supportedTokens,
selling
);
}
}, [
loopringWallet,
loopringAccount,
changingFromAmount,
changingToAmount,
compatibleMarkets,
debouncedGetSwapData,
liquidityError,
fromAmount,
fromToken,
selling,
supportedTokens,
toAmount,
toToken,
]);
// when the exchange rate is fetched, we need to calculate the expected
// token amount to receive based on it
useEffect(() => {
if (
swapData &&
swapData.averageFillPrice &&
fromToken &&
toToken &&
((!changingFromAmount &&
!changingToAmount &&
fromAmount &&
toAmount) ||
(changingFromAmount && fromAmount) ||
(changingToAmount && toAmount))
) {
const referenceAmount = changingToAmount ? toAmount : fromAmount;
let partialAmount = new BigNumber(referenceAmount);
if (changingToAmount) {
partialAmount = selling
? partialAmount.dividedBy(swapData.averageFillPrice)
: partialAmount.multipliedBy(swapData.averageFillPrice);
} else {
partialAmount = selling
? partialAmount.multipliedBy(swapData.averageFillPrice)
: partialAmount.dividedBy(swapData.averageFillPrice);
}
const newAmount = partialAmount.toFixed();
let newFromAmount = fromAmount;
let newToAmount = toAmount;
if (changingToAmount && newAmount !== fromAmount) {
// if the updated to amount is more than the maximum one based on
// the order book, the maximum possible value is set
newFromAmount = newAmount;
setLiquidityError(
!!(
swapData.maximumAmount &&
new BigNumber(newAmount)
.dividedBy(swapData.averageFillPrice)
.isGreaterThan(swapData.maximumAmount)
)
);
} else if (!changingToAmount && newAmount !== toAmount) {
// If the new from amount would bring, based on the current average
// fill price, the to token amount to be bigger than the maximum allowed
// quantity, the from amount is adjusted accordingly
newToAmount = newAmount;
setLiquidityError(
!!(
swapData.maximumAmount &&
swapData.maximumAmount.isLessThan(newAmount)
)
);
}
setFromAmount(newFromAmount);
const feeAmount = new BigNumber(newToAmount).multipliedBy(
swapData.feePercentage
);
setToAmount(new BigNumber(newToAmount).minus(feeAmount).toFixed());
setFeeAmount(feeAmount);
setChangingFromAmount(false);
setChangingToAmount(false);
}
}, [
changingFromAmount,
changingToAmount,
fromAmount,
fromToken,
selling,
swapData,
toAmount,
toToken,
]);
// on "from" or "to" token changes, we need to determine if the user is buying or selling a given market.
// We do this by checking if the corresponding market has the "from" token as a base or quote currency.
// If the "from" token is a quote currency, the user is buying, and vice-versa.
useEffect(() => {
if (fromToken && toToken) {
setSelling(
!!compatibleMarkets.find(
(market) =>
market.baseTokenId === fromToken.tokenId &&
market.quoteTokenId === toToken.tokenId
)
);
}
}, [compatibleMarkets, fromToken, toToken]);
useEffect(() => {
if (
(!fromAmount && toAmount && changingFromAmount) ||
(!toAmount && fromAmount && changingToAmount)
) {
setToAmount("");
dispatch(resetSwapData());
setLiquidityError(false);
setBalanceError(false);
setLessThanMinimumOrderError(false);
setMoreThanMaximumOrderError(false);
}
}, [changingFromAmount, dispatch, changingToAmount, fromAmount, toAmount]);
useEffect(() => {
if (!fromToken || !toToken) {
return;
}
const wrappedBalance = balances.find(
(balance) => balance.id === fromToken.tokenId
);
const tokenMaximumExchangeBalance =
wrappedBalance && wrappedBalance.balance;
const bigNumberFromAmount = new BigNumber(fromAmount);
const bigNumberToAmount = new BigNumber(toAmount);
setBalanceError(
!!(
tokenMaximumExchangeBalance &&
bigNumberFromAmount.isGreaterThan(tokenMaximumExchangeBalance)
)
);
const fromTokenMinimumTradeVolume = weiToEther(
new BigNumber(fromToken.minOrderAmount),
fromToken.decimals
);
const toTokenMinimumTradeVolume = weiToEther(
new BigNumber(toToken.minOrderAmount),
toToken.decimals
);
setLessThanMinimumOrderError(
!!(
!bigNumberFromAmount.isZero() &&
!bigNumberToAmount.isZero() &&
(bigNumberFromAmount.isLessThan(fromTokenMinimumTradeVolume) ||
bigNumberToAmount.isLessThan(toTokenMinimumTradeVolume))
)
);
const fromTokenMaximumTradeVolume = weiToEther(
new BigNumber(fromToken.maxOrderAmount),
fromToken.decimals
);
const toTokenMaximumTradeVolume = weiToEther(
new BigNumber(toToken.maxOrderAmount),
toToken.decimals
);
setMoreThanMaximumOrderError(
!!(
!bigNumberFromAmount.isZero() &&
!bigNumberToAmount.isZero() &&
(bigNumberFromAmount.isGreaterThan(
fromTokenMaximumTradeVolume
) ||
bigNumberToAmount.isGreaterThan(toTokenMaximumTradeVolume))
)
);
}, [balances, fromAmount, fromToken, toAmount, toToken]);
const handleFromAmountChange = useCallback((amount) => {
setChangingToAmount(false);
setChangingFromAmount(true);
setFromAmount(amount);
}, []);
const handleToAmountChange = useCallback((weiAmount) => {
setChangingToAmount(true);
setChangingFromAmount(false);
setToAmount(weiAmount);
}, []);
const handleSwap = useCallback(() => {
dispatch(
postSwap(
loopringAccount,
loopringWallet,
loopringExchange,
fromToken,
fromAmount,
toToken,
toAmount,
supportedTokens,
selling
)
);
}, [
dispatch,
fromAmount,
fromToken,
loopringAccount,
loopringExchange,
loopringWallet,
selling,
supportedTokens,
toAmount,
toToken,
]);
const handleBalancesRefresh = useCallback(() => {
if (
loggedIn &&
loopringAccount &&
loopringWallet &&
supportedTokens &&
supportedTokens.length > 0
) {
dispatch(
getUserBalances(
loopringAccount,
loopringWallet,
supportedTokens
)
);
}
}, [dispatch, loggedIn, loopringAccount, loopringWallet, supportedTokens]);
const handleAssetsInversion = useCallback(() => {
if (fromToken && toToken) {
setFromAmount("");
setToAmount("");
setFromToken(toToken);
setToToken(fromToken);
setLiquidityError(false);
setBalanceError(false);
setLessThanMinimumOrderError(false);
setMoreThanMaximumOrderError(false);
dispatch(resetSwapData());
}
}, [fromToken, toToken, dispatch]);
const getErrorCause = () => {
if (moreThanMaximumOrderError) {
return "maximum";
}
if (liquidityError) {
return "liquidity";
}
if (balanceError) {
return "balance";
}
if (lessThanMinimumOrderError) {
return "minimum";
}
return null;
};
const getPriceNotation = () => {
let price;
const priceFromToken = flippedPriceNotation ? fromToken : toToken;
const priceToToken = flippedPriceNotation ? toToken : fromToken;
if (selling) {
price = flippedPriceNotation
? new BigNumber("1").dividedBy(swapData.averageFillPrice)
: swapData.averageFillPrice;
} else {
price = flippedPriceNotation
? swapData.averageFillPrice
: new BigNumber("1").dividedBy(swapData.averageFillPrice);
}
return `${formatNumber(price, {
style: "decimal",
maximumSignificantDigits: 4,
})} ${priceFromToken.symbol} per ${priceToToken.symbol}`;
};
const handlePriceFlip = useCallback(() => {
setFlippedPriceNotation(!flippedPriceNotation);
}, [flippedPriceNotation]);
return (
<Flex flexDirection="column">
<BackgroundFlex flexDirection="column" alignItems="center" mb={4}>
<Box>
<TokenSpecifier
variant="from"
amount={fromAmount}
token={fromToken}
onAmountChange={handleFromAmountChange}
onBalancesRefresh={handleBalancesRefresh}
onTokenChange={setFromToken}
supportedTokens={supportedTokens}
balances={balances}
loadingSupportedTokens={loadingSupportedTokens}
loadingBalances={loadingBalances}
loggedIn={loggedIn}
/>
</Box>
<PointableBox
display="flex"
justifyContent="center"
alignItems="center"
height={36}
p={2}
onClick={handleAssetsInversion}
>
<ArrowIcon icon={faArrowDown} />
</PointableBox>
<Box mb="12px">
<TokenSpecifier
variant="to"
amount={toAmount}
token={toToken}
onAmountChange={handleToAmountChange}
onBalancesRefresh={handleBalancesRefresh}
onTokenChange={setToToken}
supportedTokens={filteredToTokens}
balances={balances}
loadingSupportedTokens={loadingSupportedTokens}
loadingBalances={loadingBalances}
loggedIn={loggedIn}
/>
</Box>
<Flex
mb="8px"
justifyContent="space-between"
alignItems="center"
px={2}
height="12px"
width="100%"
>
{(liquidityError ||
balanceError ||
lessThanMinimumOrderError ||
moreThanMaximumOrderError) && (
<>
<ErrorTextBox>
<FormattedMessage
id={`swapper.error.amount.${getErrorCause()}`}
/>
</ErrorTextBox>
<ErrorTextBox>
<FontAwesomeIcon icon={faExclamationTriangle} />
</ErrorTextBox>
</>
)}
</Flex>
<Flex
mb="8px"
justifyContent="space-between"
alignItems="center"
px={2}
width="100%"
>
<Box>
<FormattedMessage id="swapper.price" />
</Box>
<Box>
{loadingSwapData ? (
<Spinner size={12} />
) : swapData && swapData.averageFillPrice ? (
<Flex>
<Box mr="4px">{getPriceNotation()}</Box>
<PointableBox onClick={handlePriceFlip}>
<PriceFlipIcon icon={faRandom} />
</PointableBox>
</Flex>
) : (
"-"
)}
</Box>
</Flex>
<Flex
mb="8px"
justifyContent="space-between"
alignItems="center"
px={2}
width="100%"
>
<Box>
<FormattedMessage id="swapper.slippage" />
</Box>
<Box>
{loadingSwapData ? (
<Spinner size={12} />
) : swapData && swapData.slippagePercentage ? (
<SlippageText>
{formatNumber(swapData.slippagePercentage, {
style: "decimal",
maximumSignificantDigits: 4,
})}
%
</SlippageText>
) : (
"-"
)}
</Box>
</Flex>
<Flex
justifyContent="space-between"
alignItems="center"
px={2}
width="100%"
>
<Box>
<FormattedMessage id="swapper.fee" />
</Box>
<Box>
{feeAmount && feeAmount.isGreaterThan("0")
? `${formatNumber(feeAmount, {
style: "decimal",
maximumSignificantDigits: 4,
})} ${toToken.symbol}`
: "-"}
</Box>
</Flex>
</BackgroundFlex>
<Box display="flex" justifyContent="center" mb={4}>
<Button
faIcon={loggedIn ? faExchangeAlt : faLockOpen}
size="large"
loading={loggedIn && loadingSwapSubmission}
disabled={
loggedIn &&
(liquidityError ||
balanceError ||
lessThanMinimumOrderError ||
moreThanMaximumOrderError ||
!fromToken ||
!fromAmount ||
fromAmount === "0" ||
!toToken ||
!toAmount ||
toAmount === "0")
}
onClick={loggedIn ? handleSwap : onConnectWalletClick}
>
<FormattedMessage
id={`swapper.action.${loggedIn ? "swap" : "connect"}`}
/>
</Button>
</Box>
</Flex>
);
}
Example #11
Source File: SearchResult.js From covid-19-mask-map with MIT License | 4 votes |
function SearchResult() {
const { t, i18n } = useTranslation();
const {
mapObj,
maskStores,
setMaskStores,
centerCoord,
setCenterCoord,
} = useMaskData();
const { addColorIndicatorMarkers, resetMarker } = useNaverMapsMarkers();
const [isLoading, setIsLoading] = useState(false);
const [dataError, setDataError] = useState(false);
const [showBetaAlert, setShowBetaAlert] = useState(true);
const [markerFilter, setMarkerFilter] = useState({
plenty: true,
some: true,
few: true,
empty: false,
});
const setNewMaskStores = useCallback(
(data) => {
const priority = [
"plenty",
"some",
"few",
"empty",
"break",
null,
undefined,
];
data.sort(
(a, b) =>
priority.indexOf(a.remain_stat) -
priority.indexOf(b.remain_stat)
);
setMaskStores(data);
},
[setMaskStores]
);
const markerFilterCheckboxHandler = (e) => {
let target = e.target;
console.log(target);
setMarkerFilter((prev) => {
return {
...prev,
[target.name]: target.checked,
};
});
};
useEffect(() => {
console.log(markerFilter);
}, [markerFilter]);
useEffect(() => {
const fetchStoresByGeo = async (loc, range) => {
const serverUrl = `https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/storesByGeo/json?lat=${loc.lat}&lng=${loc.lng}&m=${range}`;
let result;
try {
setIsLoading(true);
result = await axios(serverUrl);
setIsLoading(false);
} catch (error) {
console.error("An error occurred in fetchStoresByGeo:", error);
setDataError(true);
setIsLoading(false);
throw Error("Failed");
}
return result.data.stores;
};
const fn = async () => {
resetMarker();
console.log("Fetching store data...");
let data;
try {
data = await fetchStoresByGeo(centerCoord, 5000);
console.log(`New store data fetched`);
console.log(data);
resetMarker();
setNewMaskStores(data);
} catch {
console.error("Failed to fetch data");
}
};
fn();
}, [centerCoord, setNewMaskStores]);
useEffect(() => {
if (mapObj) {
mapObj.setCenter(centerCoord);
mapObj.setZoom(14);
}
}, [mapObj, centerCoord]);
useEffect(() => {
if (!mapObj) {
return;
}
addColorIndicatorMarkers(mapObj, maskStores);
}, [maskStores, mapObj, addColorIndicatorMarkers]);
const onClickMapRelocate = () => {
const newCenter = mapObj.getCenter();
setCenterCoord({
lat: newCenter.y,
lng: newCenter.x,
});
};
const getAlternateMaskText = useCallback(() => {
const today = new Date();
const day = today.getDay();
if (day === 0 || day === 6) {
// Weekend
return t("maskBuyAlertWeekend");
} else {
// Weekday
return t("maskBuyAlertWeekday", {
dayOfWeek: t(`dayOfWeek.${alternateMaskDays[day].weekday}`),
digits: alternateMaskDays[day].availableDigits.join(", "),
});
}
}, [i18n]);
return (
<>
<main>
<Container id="mainContainer">
<Row>
<Col sm={12}>
{showBetaAlert && (
<Alert
variant="warning"
onClose={() => setShowBetaAlert(false)}
dismissible>
<FontAwesomeIcon
icon={faExclamationTriangle}
/>{" "}
{t("notice.publicMaskShutdown")}
</Alert>
)}
</Col>
</Row>
<Row>
<Col md={6}>
{/* <Card style={{ marginBottom: "5px" }}>
<Card.Body className="p-1">
{getAlternateMaskText()}
</Card.Body>
</Card> */}
<MapPanel />
<Button
variant="outline-primary"
className="mt-1 mb-1"
block
onClick={onClickMapRelocate}>
<FontAwesomeIcon icon={faLocationArrow} />{" "}
{t("refreshMapStores")}
</Button>
</Col>
<Col md={6}>
{dataError && (
<Alert variant="danger" className="mt-1">
<FontAwesomeIcon
icon={faExclamationTriangle}
/>{" "}
{t("error.failedToLoadData")}
</Alert>
)}
<div className="border p-1 mb-1 d-flex flex-row justify-content-between">
<div class="form-check">
<input
type="checkbox"
disabled
class="form-check-input"
id="showPlentyStores"
name="plenty"
defaultChecked={markerFilter.plenty}
value={markerFilter.plenty}
onChange={markerFilterCheckboxHandler}
/>
<label
class="form-check-label"
htmlFor="showPlentyStores">
<RemainingStockBadge remainingStockStr="plenty" />{" "}
100개 +
</label>
</div>
<div class="form-check">
<input
type="checkbox"
disabled
class="form-check-input"
id="showSomeStores"
name="some"
defaultChecked={markerFilter.some}
value={markerFilter.some}
onChange={markerFilterCheckboxHandler}
/>
<label
class="form-check-label"
for="showSomeStores">
<RemainingStockBadge remainingStockStr="some" />{" "}
30-100
</label>
</div>
<div class="form-check">
<input
type="checkbox"
disabled
class="form-check-input"
id="showFewStores"
name="few"
defaultChecked={markerFilter.few}
value={markerFilter.few}
onChange={markerFilterCheckboxHandler}
/>
<label
class="form-check-label"
for="showFewStores">
<RemainingStockBadge remainingStockStr="few" />{" "}
2-30
</label>
</div>
<div class="form-check">
<input
type="checkbox"
disabled
class="form-check-input"
id="showEmptyStores"
name="empty"
defaultChecked={markerFilter.empty}
value={markerFilter.empty}
onChange={markerFilterCheckboxHandler}
/>
<label
class="form-check-label"
for="showEmptyStores">
<RemainingStockBadge remainingStockStr="empty" />{" "}
0개
</label>
</div>
</div>
{isLoading ? (
<Spinner animation="border" role="status">
<span className="sr-only">Loading...</span>
</Spinner>
) : maskStores && maskStores.length ? (
<>
<MaskStoreTable
style={{
overflow: "auto",
maxHeight: "100px",
}}
/>
</>
) : (
<Alert variant="danger">
주변에 마스크 판매처가 없습니다. 지도를
이동한 후 지도 아래의 재검색 버튼을 이용해
주세요.
</Alert>
)}
</Col>
</Row>
</Container>
</main>
</>
);
}