diff --git a/src/components/DepositBorrowTopPanel/index.tsx b/src/components/DepositBorrowTopPanel/index.tsx index 9d4354d46..eb3994d53 100644 --- a/src/components/DepositBorrowTopPanel/index.tsx +++ b/src/components/DepositBorrowTopPanel/index.tsx @@ -272,6 +272,7 @@ export default function DepositBorrowTopPanel() { isColumn={true} titleColor="white" titleLightWeight={true} + withHALLink={true} /> diff --git a/src/components/HealthFactor/index.tsx b/src/components/HealthFactor/index.tsx index d31adb936..4977db1c2 100644 --- a/src/components/HealthFactor/index.tsx +++ b/src/components/HealthFactor/index.tsx @@ -24,6 +24,7 @@ interface HealthFactorProps { titleLightWeight?: boolean; isColumn?: boolean; onWhiteBackground?: boolean; + withHALLink?: boolean; } export default function HealthFactor({ @@ -39,6 +40,7 @@ export default function HealthFactor({ titleLightWeight, isColumn, onWhiteBackground, + withHALLink, }: HealthFactorProps) { const intl = useIntl(); const { currentTheme } = useThemeContext(); @@ -76,6 +78,7 @@ export default function HealthFactor({ color={titleColor} lightWeight={titleLightWeight} onWhiteBackground={onWhiteBackground} + withSecondaryIcon={withHALLink} /> )} diff --git a/src/components/HelpModal/HealthFactorHelpModal/HALNotificationIcon.tsx b/src/components/HelpModal/HealthFactorHelpModal/HALNotificationIcon.tsx new file mode 100644 index 000000000..8ca10cb4e --- /dev/null +++ b/src/components/HelpModal/HealthFactorHelpModal/HALNotificationIcon.tsx @@ -0,0 +1,96 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; +import classNames from 'classnames'; +import { CustomTooltip } from '@aave/aave-ui-kit'; + +import { useUserWalletDataContext } from '../../../libs/web3-data-provider'; +import { useProtocolDataContext } from '../../../libs/protocol-data-provider'; +import { CustomMarket } from '../../../ui-config/markets'; +import { AdditionalItemProps } from '../../TextWithModal'; + +import messages from './messages'; +import staticStyles from './style'; + +import bellGrayDark from './images/bellGrayDark.svg'; +import bellGray from './images/bellGray.svg'; +import bell from './images/bell.svg'; + +const marketToHALAaveVersionUrlParam = (market: CustomMarket): string | undefined => { + const exhaustCases = (_: never) => undefined; + switch (market) { + case CustomMarket.proto_matic: + return 'aavepolygon'; + case CustomMarket.proto_avalanche: + return 'aaveavalanche'; + case CustomMarket.proto_mainnet: + return 'aavev2'; + + case CustomMarket.proto_kovan: + case CustomMarket.proto_mumbai: + case CustomMarket.proto_fuji: + case CustomMarket.amm_kovan: + case CustomMarket.amm_mainnet: + return undefined; + + default: + return exhaustCases(market); + } +}; + +export default function HALNotificationIcon({ + height, + width, + containerClassName, + containerStyle, + iconTheme, +}: AdditionalItemProps) { + const intl = useIntl(); + const { currentAccount } = useUserWalletDataContext(); + const { currentMarket } = useProtocolDataContext(); + + const supportedAaveVersion = marketToHALAaveVersionUrlParam(currentMarket); + const urlString = React.useMemo(() => { + const url = new URL('https://9000.hal.xyz/recipes/aave-track-your-health-factor'); + url.searchParams.set('user', currentAccount); + + const aaveVersionParam = supportedAaveVersion; + if (aaveVersionParam !== undefined) { + url.searchParams.set('aaveversion', aaveVersionParam); + } + + return url.toString(); + }, [currentAccount, supportedAaveVersion]); + + const tooltipId = `${currentAccount}__healthFactor`; + + // Do not show the HAL Noticiation icon on unsupported markets. + if (supportedAaveVersion === undefined) { + return null; + } + + return ( + + Notify Me + + + + + + ); +} diff --git a/src/components/HelpModal/HealthFactorHelpModal/images/bell.svg b/src/components/HelpModal/HealthFactorHelpModal/images/bell.svg new file mode 100644 index 000000000..9cd31d475 --- /dev/null +++ b/src/components/HelpModal/HealthFactorHelpModal/images/bell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/HelpModal/HealthFactorHelpModal/images/bellGray.svg b/src/components/HelpModal/HealthFactorHelpModal/images/bellGray.svg new file mode 100644 index 000000000..ba3fbcb69 --- /dev/null +++ b/src/components/HelpModal/HealthFactorHelpModal/images/bellGray.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/HelpModal/HealthFactorHelpModal/images/bellGrayDark.svg b/src/components/HelpModal/HealthFactorHelpModal/images/bellGrayDark.svg new file mode 100644 index 000000000..7f17c458a --- /dev/null +++ b/src/components/HelpModal/HealthFactorHelpModal/images/bellGrayDark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/HelpModal/HealthFactorHelpModal/index.tsx b/src/components/HelpModal/HealthFactorHelpModal/index.tsx index 113710c53..613818950 100644 --- a/src/components/HelpModal/HealthFactorHelpModal/index.tsx +++ b/src/components/HelpModal/HealthFactorHelpModal/index.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { useIntl } from 'react-intl'; import HelpModalWrapper from '../HelpModalWrapper'; +import HALNotificationIcon from './HALNotificationIcon'; import { HelpModalProps } from '../types'; import messages from './messages'; @@ -13,8 +14,10 @@ export default function HealthFactorHelpModal({ color, lightWeight, onWhiteBackground, + withSecondaryIcon, }: HelpModalProps) { const intl = useIntl(); + return ( : undefined} /> ); } diff --git a/src/components/HelpModal/HealthFactorHelpModal/messages.ts b/src/components/HelpModal/HealthFactorHelpModal/messages.ts index a89ff474d..8f758f8c1 100644 --- a/src/components/HelpModal/HealthFactorHelpModal/messages.ts +++ b/src/components/HelpModal/HealthFactorHelpModal/messages.ts @@ -4,4 +4,6 @@ export default defineMessages({ caption: 'Health factor', description: 'The health factor represents the safety of your loan derived from the proportion of collateral versus amount borrowed. Keep it above 1 to avoid liquidation.', + + notificationIconTooltipText: 'Set up notification when your Health Factor is getting low.', }); diff --git a/src/components/HelpModal/HealthFactorHelpModal/style.ts b/src/components/HelpModal/HealthFactorHelpModal/style.ts new file mode 100644 index 000000000..a5ce095c7 --- /dev/null +++ b/src/components/HelpModal/HealthFactorHelpModal/style.ts @@ -0,0 +1,13 @@ +import css from 'styled-jsx/css'; + +/*language=SCSS*/ +const staticStyles = css` + @import 'src/_mixins/vars'; + @import 'src/_mixins/screen-size'; + + .HALNotificationIcon { + opacity: 1; + } +`; + +export default staticStyles; diff --git a/src/components/HelpModal/HelpModalWrapper/index.tsx b/src/components/HelpModal/HelpModalWrapper/index.tsx index 5bd04562b..40d5c23ed 100644 --- a/src/components/HelpModal/HelpModalWrapper/index.tsx +++ b/src/components/HelpModal/HelpModalWrapper/index.tsx @@ -1,9 +1,9 @@ import React, { ReactNode } from 'react'; import HelpItem from '../../HelpItem'; -import TextWithModal from '../../TextWithModal'; +import TextWithModal, { TextWithModalProps } from '../../TextWithModal'; -export interface HelpModalWrapperProps { +export interface HelpModalWrapperProps extends Pick { text: string; iconSize?: number; className?: string; @@ -31,6 +31,7 @@ export default function HelpModalWrapper({ clickOnText, withGrayIcon, captionColor, + secondaryIcon, }: HelpModalWrapperProps) { return ( JSX.Element; }; +const PRIMARY_ICON_POSTION = 1; +const SECONDARY_ICON_POSITION = 2; +const ICON_PADDING = 4; + export default function TextWithModal({ text, children, @@ -40,6 +53,7 @@ export default function TextWithModal({ onWhiteBackground, clickOnText, withGrayIcon, + secondaryIcon, }: TextWithModalProps) { const intl = useIntl(); const { currentTheme, xl, lg, md, isCurrentThemeDark } = useThemeContext(); @@ -48,10 +62,27 @@ export default function TextWithModal({ const baseIconSize = !xl ? 14 : lg && !md ? 10 : md ? 12 : 12; + const iconHeight: number = iconSize || baseIconSize; + const iconWidth: number = iconSize || baseIconSize; + + const getIconContainerStyle = (position: number): React.CSSProperties => { + const iconWidthOffset = iconWidth * position; + const iconOffset = -(iconWidthOffset + ICON_PADDING); + + const isSecondPosition = position === SECONDARY_ICON_POSITION; + + return { + height: isSecondPosition ? iconHeight + 2 : iconHeight, + width: isSecondPosition ? iconWidth + 2 : iconWidth, + right: isSecondPosition ? iconOffset - 4 : iconOffset, + }; + }; + return (
{text}
- + +
+ + + {secondaryIcon && + secondaryIcon({ + height: iconHeight, + width: iconWidth, + containerClassName: 'TextWithModal__button', + containerStyle: getIconContainerStyle(SECONDARY_ICON_POSITION), + iconTheme: withGrayIcon ? (isCurrentThemeDark ? 'dark' : 'gray') : 'default', + })} +
)} @@ -323,6 +324,7 @@ export default function Dashboard() { value={user?.healthFactor || '-1'} titleColor="white" titleLightWeight={true} + withHALLink={true} />