Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

[PAY-1506] USDC artist dashboard tile #3963

Merged
merged 5 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions packages/common/src/utils/formatUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,36 @@ export const formatCount = (count: number) => {
}
}

/**
* The format for USDC should be:
* - show 0 if 0
* - don't show decimal places if input is a round number
* - show only up to 2 decimal places if input is not a round number
* - round down to nearest thousand if input is greater than 10000
* ie.
* 0 => 0
* 8 => 8
* 8.01 => 8.01
* 8.10 => 8.10
* 4,210 => 4210
* 9,999.99 => 9999.99
* 56,010 => 56K
* 443,123 => 443K
*/
export const formatUSDC = (amount: number) => {
if (amount === 0) {
return '0'
} else if (amount >= 9999.995) {
const roundedAmount = Math.floor(amount / 1000)
return `${roundedAmount}k`
} else if (Number.isInteger(amount)) {
return amount.toString()
} else {
const decimalCount = amount > 10000 ? 0 : 2
return amount.toFixed(decimalCount)
}
}

/**
* Formats a number of bytes into a nice looking string.
* ie.
Expand Down
3 changes: 3 additions & 0 deletions packages/stems/src/assets/icons/iconQuestionCircle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/stems/src/assets/styles/fonts.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ root {
--font-2xl: 24px;
--font-3xl: 32px;
--font-4xl: 36px;
--font-5xl: 40px;

--font-ultra-light: 100;
--font-regular: 400;
Expand Down
1 change: 1 addition & 0 deletions packages/stems/src/components/Icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export { ReactComponent as IconIndent } from '../../assets/icons/iconIndent.svg'
export { ReactComponent as IconInfo } from '../../assets/icons/iconInfo.svg'
export { ReactComponent as IconInstagram } from '../../assets/icons/iconInstagram.svg'
export { ReactComponent as IconKebabHorizontal } from '../../assets/icons/iconKebabHorizontal.svg'
export { ReactComponent as IconQuestionCircle } from '../../assets/icons/iconQuestionCircle.svg'
export { ReactComponent as IconKebabVertical } from '../../assets/icons/iconKebabVertical.svg'
export { ReactComponent as IconLink } from '../../assets/icons/iconLink.svg'
export { ReactComponent as IconListens } from '../../assets/icons/iconListens.svg'
Expand Down
1 change: 1 addition & 0 deletions packages/stems/src/styles/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ export type ColorValue =
| 'accentBlue'
| 'specialLightGreen'
| 'darkmodeStaticWhite'
| 'staticWhite'
3 changes: 3 additions & 0 deletions packages/web/src/components/Icon/Icon.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@
.xxLarge {
--icon-size: var(--unit-8);
}
.xxxLarge {
dharit-tan marked this conversation as resolved.
Show resolved Hide resolved
--icon-size: var(--unit-10);
}
2 changes: 2 additions & 0 deletions packages/web/src/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type IconSize =
| 'large' // 24
| 'xLarge' // 30
| 'xxLarge' // 32
| 'xxxLarge' // 40

type IconProps = {
color?: ColorValue
Expand All @@ -29,6 +30,7 @@ type IconProps = {
* - large: 24
* - xLarge: 30
* - xxLarge: 32
* - xxxLarge: 40
*/
export const Icon = (props: IconProps) => {
const {
Expand Down
8 changes: 7 additions & 1 deletion packages/web/src/components/typography/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ export type FontWeight =

export type TextStrength = 'weak' | 'default' | 'strong'

export type TextSize = 'xLarge' | 'large' | 'medium' | 'small' | 'xSmall'
export type TextSize =
| 'xxLarge'
| 'xLarge'
| 'large'
| 'medium'
| 'small'
| 'xSmall'

export type TextVariant =
| 'display'
Expand Down
6 changes: 6 additions & 0 deletions packages/web/src/components/typography/typography.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@
font-weight: var(--font-bold);
}

/* 40 / 44 */
.headingXXLarge {
font-size: var(--unit-10);
line-height: var(--unit-11);
}

/* 36 / 40 */
.headingXLarge {
font-size: var(--unit-9);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,74 @@
justify-content: stretch;
margin: 12px 0px 36px;
}

.usdcContainer {
width: 100%;
flex-direction: column;
border-radius: var(--unit-3);
background: var(--static-white);
overflow: hidden;
}

.backgroundBlueGradient {
display: flex;
width: 100%;
flex-direction: column;
align-items: center;
justify-content: space-between;
gap: var(--unit-4);
padding: var(--unit-6);
background: linear-gradient(
315deg,
rgba(0, 0, 0, 0.1) 0%,
rgba(255, 255, 255, 0.1) 100%
),
#2775ca;
dharit-tan marked this conversation as resolved.
Show resolved Hide resolved
}

.usdcTitleContainer {
display: flex;
width: 100%;
flex-direction: row;
align-items: center;
justify-content: space-between;
text-transform: uppercase;
font-weight: 900;
dharit-tan marked this conversation as resolved.
Show resolved Hide resolved
font-size: var(--font-5xl);
color: var(--static-white);
}

.usdcTitle {
display: flex;
gap: var(--unit-2);
}

.usdc {
opacity: 0.8;
}

.usdcInfo {
display: flex;
width: 100%;
flex-direction: row;
align-items: center;
justify-content: space-between;
color: var(--static-white);
dharit-tan marked this conversation as resolved.
Show resolved Hide resolved
font-size: var(--font-m);
font-weight: var(--font-medium);
line-height: var(--unit-5); /* 125% */
}

.withdrawContainer {
display: flex;
width: 100%;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: var(--unit-6);
gap: var(--unit-6);
}

.learnMoreContainer {
color: var(--static-white);
}
108 changes: 105 additions & 3 deletions packages/web/src/pages/artist-dashboard-page/ArtistDashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,24 @@ import {
Theme,
Track,
User,
formatUSDC,
formatCount,
themeSelectors
themeSelectors,
FeatureFlags
} from '@audius/common'
import { IconFilter, IconNote, IconHidden } from '@audius/stems'
import {
IconFilter,
IconNote,
IconHidden,
IconKebabHorizontal,
IconQuestionCircle,
HarmonyButton,
HarmonyButtonType,
PopupMenu,
PopupMenuItem,
HarmonyPlainButton,
HarmonyPlainButtonType
} from '@audius/stems'
import cn from 'classnames'
import { push as pushRoute } from 'connected-react-router'
import { each } from 'lodash'
Expand All @@ -25,12 +39,15 @@ import { connect, useDispatch, useSelector } from 'react-redux'
import { withRouter, RouteComponentProps } from 'react-router-dom'
import { Dispatch } from 'redux'

import { Icon } from 'components/Icon'
import Header from 'components/header/desktop/Header'
import { Input } from 'components/input'
import LoadingSpinner from 'components/loading-spinner/LoadingSpinner'
import Page from 'components/page/Page'
import { TracksTable, TracksTableColumn } from 'components/tracks-table'
import { Text } from 'components/typography'
import useTabs, { useTabRecalculator } from 'hooks/useTabs/useTabs'
import { getFeatureEnabled } from 'services/remote-config/featureFlagHelpers'
import { AppState } from 'store/types'
import lazyWithPreload from 'utils/lazyWithPreload'
import { profilePage, TRENDING_PAGE } from 'utils/route'
Expand Down Expand Up @@ -86,7 +103,13 @@ export const messages = {
publicTracksTabTitle: 'PUBLIC TRACKS',
unlistedTracksTabTitle: 'HIDDEN TRACKS',
filterInputPlacehoder: 'Filter Tracks',
thisYear: 'This Year'
thisYear: 'This Year',
usdc: 'usdc',
earn: 'Earn USDC by selling your music',
learnMore: 'Learn More',
withdraw: 'Withdraw Funds',
salesSummary: 'Sales Summary',
withdrawHistory: 'Withdraw History'
dharit-tan marked this conversation as resolved.
Show resolved Hide resolved
}

const tableColumns: TracksTableColumn[] = [
Expand Down Expand Up @@ -380,9 +403,87 @@ export class ArtistDashboardPage extends Component<
)
}

renderUSDCSection() {
dharit-tan marked this conversation as resolved.
Show resolved Hide resolved
const { account } = this.props
if (!account) return null

// TODO: wire up balance
const balance = 10.29

const menuItems: PopupMenuItem[] = [
{
text: messages.salesSummary,
// TODO: link to sales page
dharit-tan marked this conversation as resolved.
Show resolved Hide resolved
onClick: () => {}
},
{
text: messages.withdrawHistory,
// TODO: link to withdraw history page
onClick: () => {}
}
]

return (
<div className={styles.usdcContainer}>
<div className={styles.backgroundBlueGradient}>
<div className={styles.usdcTitleContainer}>
<div className={styles.usdcTitle}>
{/* TODO: update icon */}
<Icon icon={IconNote} size='xxxLarge' />
<div className={styles.usdc}>
<Text
variant='heading'
size='xxLarge'
color='staticWhite'
strength='strong'
>
{messages.usdc}
</Text>
</div>
</div>
<div className={styles.usdcBalance}>${formatUSDC(balance)}</div>
</div>
<div className={styles.usdcInfo}>
<Text color='staticWhite'>{messages.earn}</Text>
<HarmonyPlainButton
// TODO: wire up learn more link
onClick={() => {}}
iconLeft={IconQuestionCircle}
variant={HarmonyPlainButtonType.INVERTED}
text={messages.learnMore}
/>
</div>
</div>
<div className={styles.withdrawContainer}>
<HarmonyButton
variant={HarmonyButtonType.SECONDARY}
text={messages.withdraw}
// TODO: update leftIcon and wire up withdraw page
iconLeft={() => <Icon icon={IconNote} size='medium' />}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we not passing IconNote directly?
And if we really need the override, can we extract it to a component instead of redefining it on each render?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think IconNote might be incorrectly sized which is why i had to override. With the correct icon i'm hoping it will work without. gonna leave for now, i have a linear to update the icons once they're added to figma.

onClick={() => {}}
/>
<PopupMenu
transformOrigin={{ horizontal: 'center', vertical: 'top' }}
anchorOrigin={{ horizontal: 'center', vertical: 'bottom' }}
items={menuItems}
renderTrigger={(anchorRef, triggerPopup) => (
<HarmonyButton
ref={anchorRef}
variant={HarmonyButtonType.SECONDARY}
iconLeft={() => <IconKebabHorizontal />}
dharit-tan marked this conversation as resolved.
Show resolved Hide resolved
onClick={triggerPopup}
/>
)}
/>
</div>
</div>
)
}

render() {
const { account, status } = this.props
const header = <Header primary='Dashboard' />
const isUSDCEnabled = getFeatureEnabled(FeatureFlags.USDC_PURCHASES)

return (
<Page
Expand All @@ -396,6 +497,7 @@ export class ArtistDashboardPage extends Component<
) : (
<>
{this.renderProfileSection()}
{isUSDCEnabled ? this.renderUSDCSection() : null}
{this.renderCreatorContent()}
</>
)}
Expand Down