Skip to content

Commit

Permalink
feat: add HAL Notification Icon on supported market (aave#324)
Browse files Browse the repository at this point in the history
Co-authored-by: Alex <[email protected]>
  • Loading branch information
Prithpal-Sooriya and Argeare5 authored Jan 18, 2022
1 parent 6c382ff commit 5e83157
Show file tree
Hide file tree
Showing 26 changed files with 219 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/components/DepositBorrowTopPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ export default function DepositBorrowTopPanel() {
isColumn={true}
titleColor="white"
titleLightWeight={true}
withHALLink={true}
/>
</div>

Expand Down
3 changes: 3 additions & 0 deletions src/components/HealthFactor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface HealthFactorProps {
titleLightWeight?: boolean;
isColumn?: boolean;
onWhiteBackground?: boolean;
withHALLink?: boolean;
}

export default function HealthFactor({
Expand All @@ -39,6 +40,7 @@ export default function HealthFactor({
titleLightWeight,
isColumn,
onWhiteBackground,
withHALLink,
}: HealthFactorProps) {
const intl = useIntl();
const { currentTheme } = useThemeContext();
Expand Down Expand Up @@ -76,6 +78,7 @@ export default function HealthFactor({
color={titleColor}
lightWeight={titleLightWeight}
onWhiteBackground={onWhiteBackground}
withSecondaryIcon={withHALLink}
/>
)}

Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<a
href={urlString}
target="_blank"
rel="noreferrer"
className={classNames(containerClassName, 'HALNotificationIcon')}
style={containerStyle}
data-tip={true}
data-for={tooltipId}
>
<img
src={iconTheme === 'dark' ? bellGrayDark : iconTheme === 'gray' ? bellGray : bell}
alt="Notify Me"
height={height + 2}
width={width + 2}
/>

<CustomTooltip
tooltipId={tooltipId}
text={intl.formatMessage(messages.notificationIconTooltipText)}
/>

<style jsx={true}>{staticStyles}</style>
</a>
);
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/components/HelpModal/HealthFactorHelpModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -13,8 +14,10 @@ export default function HealthFactorHelpModal({
color,
lightWeight,
onWhiteBackground,
withSecondaryIcon,
}: HelpModalProps) {
const intl = useIntl();

return (
<HelpModalWrapper
text={text}
Expand All @@ -25,6 +28,7 @@ export default function HealthFactorHelpModal({
color={color}
lightWeight={lightWeight}
onWhiteBackground={onWhiteBackground}
secondaryIcon={withSecondaryIcon ? (props) => <HALNotificationIcon {...props} /> : undefined}
/>
);
}
2 changes: 2 additions & 0 deletions src/components/HelpModal/HealthFactorHelpModal/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.',
});
13 changes: 13 additions & 0 deletions src/components/HelpModal/HealthFactorHelpModal/style.ts
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 4 additions & 2 deletions src/components/HelpModal/HelpModalWrapper/index.tsx
Original file line number Diff line number Diff line change
@@ -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<TextWithModalProps, 'secondaryIcon'> {
text: string;
iconSize?: number;
className?: string;
Expand Down Expand Up @@ -31,6 +31,7 @@ export default function HelpModalWrapper({
clickOnText,
withGrayIcon,
captionColor,
secondaryIcon,
}: HelpModalWrapperProps) {
return (
<TextWithModal
Expand All @@ -43,6 +44,7 @@ export default function HelpModalWrapper({
modalClassName={modalClassName}
clickOnText={clickOnText}
withGrayIcon={withGrayIcon}
secondaryIcon={secondaryIcon}
>
<HelpItem
caption={caption}
Expand Down
1 change: 1 addition & 0 deletions src/components/HelpModal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export interface HelpModalProps
caption?: string;
description?: string;
withGrayIcon?: boolean;
withSecondaryIcon?: boolean;
}
79 changes: 59 additions & 20 deletions src/components/TextWithModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ import info from './images/info.svg';
import infoGray from './images/infoGray.svg';
import infoGrayDark from './images/infoGrayDark.svg';

export type AdditionalItemProps = {
height: number;
width: number;
containerClassName: string;
containerStyle: React.CSSProperties;
iconTheme: 'dark' | 'gray' | 'default';
};

export type TextWithModalProps = {
text: string;
children: ReactNode;
Expand All @@ -25,8 +33,13 @@ export type TextWithModalProps = {
onWhiteBackground?: boolean;
clickOnText?: boolean;
withGrayIcon?: boolean;
secondaryIcon?: (props: AdditionalItemProps) => JSX.Element;
};

const PRIMARY_ICON_POSTION = 1;
const SECONDARY_ICON_POSITION = 2;
const ICON_PADDING = 4;

export default function TextWithModal({
text,
children,
Expand All @@ -40,6 +53,7 @@ export default function TextWithModal({
onWhiteBackground,
clickOnText,
withGrayIcon,
secondaryIcon,
}: TextWithModalProps) {
const intl = useIntl();
const { currentTheme, xl, lg, md, isCurrentThemeDark } = useThemeContext();
Expand All @@ -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 (
<div
className={classNames('TextWithModal', className, `TextWithModal__${color}`, {
TextWithModal__lightWeight: lightWeight,
TextWithModal__withDoubleIcons: !!secondaryIcon,
})}
>
<div
Expand All @@ -65,26 +96,34 @@ export default function TextWithModal({
>
{text}
</div>
<button
className="TextWithModal__button"
type="button"
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
setVisible(true);
}}
style={{
height: iconSize || baseIconSize,
width: iconSize || baseIconSize,
right: -((iconSize || baseIconSize) + 4),
}}
>
<img
src={withGrayIcon ? (isCurrentThemeDark ? infoGrayDark : infoGray) : info}
alt={text}
height={iconSize || baseIconSize}
width={iconSize || baseIconSize}
/>
</button>

<div className="TextWithModal__icons">
<button
className="TextWithModal__button"
type="button"
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
setVisible(true);
}}
style={getIconContainerStyle(PRIMARY_ICON_POSTION)}
>
<img
src={withGrayIcon ? (isCurrentThemeDark ? infoGrayDark : infoGray) : info}
alt={text}
height={iconHeight}
width={iconWidth}
/>
</button>

{secondaryIcon &&
secondaryIcon({
height: iconHeight,
width: iconWidth,
containerClassName: 'TextWithModal__button',
containerStyle: getIconContainerStyle(SECONDARY_ICON_POSITION),
iconTheme: withGrayIcon ? (isCurrentThemeDark ? 'dark' : 'gray') : 'default',
})}
</div>

<BasicModal
isVisible={visible}
Expand Down
19 changes: 19 additions & 0 deletions src/components/TextWithModal/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,21 @@ const staticStyles = css.global`
align-items: flex-start;
position: relative;
&__withDoubleIcons {
.TextWithModal__button {
position: relative;
top: 2px;
transform: unset;
margin-left: 4px;
right: unset !important;
&:active {
transform: scale(0.8);
}
}
}
&__text {
display: inline-block;
font-size: $large;
@include respond-to(xl) {
font-size: $medium;
Expand All @@ -32,6 +46,11 @@ const staticStyles = css.global`
cursor: pointer;
}
&__icons {
display: inline-flex;
align-items: center;
}
&__button {
background: transparent;
border: none;
Expand Down
2 changes: 2 additions & 0 deletions src/modules/dashboard/screens/Dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ export default function Dashboard() {
value={user?.healthFactor || '-1'}
titleColor="white"
titleLightWeight={true}
withHALLink={true}
/>
)}
</>
Expand Down Expand Up @@ -323,6 +324,7 @@ export default function Dashboard() {
value={user?.healthFactor || '-1'}
titleColor="white"
titleLightWeight={true}
withHALLink={true}
/>

<Row
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ export default function UserInformation({
value={user?.healthFactor || '-1'}
titleColor={elementsColor}
titleLightWeight={sm}
withHALLink={true}
/>
<Row
title={intl.formatMessage(messages.loanToValue)}
Expand Down
Loading

0 comments on commit 5e83157

Please sign in to comment.