Skip to content

Commit

Permalink
[PAY-1861] Expose Pay Extra details in purchase/sales tables (#6209)
Browse files Browse the repository at this point in the history
  • Loading branch information
schottra authored Oct 3, 2023
1 parent d90897f commit 9f7cf0c
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 56 deletions.
12 changes: 10 additions & 2 deletions packages/common/src/api/purchases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,21 @@ type GetPurchaseListArgs = {
}

const parsePurchase = (purchase: full.Purchase): USDCPurchaseDetails => {
const { contentId, contentType, amount, buyerUserId, sellerUserId, ...rest } =
purchase
const {
contentId,
contentType,
extraAmount,
amount,
buyerUserId,
sellerUserId,
...rest
} = purchase
return {
...rest,
contentType: contentType as USDCContentPurchaseType,
contentId: HashId.parse(contentId),
amount: amount as StringUSDC,
extraAmount: extraAmount as StringUSDC,
buyerUserId: HashId.parse(buyerUserId),
sellerUserId: HashId.parse(sellerUserId)
}
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/models/USDCTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export type USDCPurchaseDetails = {
sellerUserId: number
buyerUserId: number
amount: StringUSDC
extraAmount: StringUSDC
contentType: USDCContentPurchaseType
contentId: number
createdAt: string
Expand Down
12 changes: 9 additions & 3 deletions packages/common/src/utils/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,16 @@ export const floorBNUSDCToNearestCent = (value: BNUSDC): BNUSDC => {
}

/** Formats a USDC wei string (full precision) to a fixed string suitable for
display as a dollar amount. Note: will lose precision by rounding _up_ to nearest cent */
export const formatUSDCWeiToUSDString = (amount: StringUSDC, precision = 2) => {
display as a dollar amount. Note: will lose precision by rounding _up_ to nearest
cent and will drop negative signs
*/
export const formatUSDCWeiToUSDString = (
amount: StringUSDC | BN,
precision = 2
) => {
const amountBN = BN.isBN(amount) ? amount : new BN(amount)
// remove negative sign if present.
const amountPos = amount.replace('-', '')
const amountPos = amountBN.abs()
// Since we only need two digits of precision, we will multiply up by 1000
// with BN, divide by $1 Wei, ceiling up to the nearest cent,
// and then convert to JS number and divide back down before formatting to
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { formatPrice } from '@audius/common'

import { Text } from 'components/typography'

import styles from './PurchaseSummaryTable.module.css'
import { SummaryTable, SummaryTableItem } from 'components/summary-table'

const messages = {
summary: 'Summary',
summary: 'Transaction Summary',
premiumTrack: 'Premium Track',
existingBalance: 'Existing USDC Balance',
payExtra: 'Pay Extra',
Expand All @@ -30,33 +28,37 @@ export const PurchaseSummaryTable = ({
existingBalance,
isPurchased
}: PurchaseSummaryTableProps) => {
const items: SummaryTableItem[] = [
{
id: 'premiumTrack',
label: messages.premiumTrack,
value: messages.price(formatPrice(basePrice))
}
]
if (extraAmount != null) {
items.push({
id: 'payExtra',
label: messages.payExtra,
value: messages.price(formatPrice(extraAmount))
})
}
if (existingBalance != null) {
items.push({
id: 'existingBalance',
label: messages.existingBalance,
value: `-${messages.price(formatPrice(existingBalance))}`
})
}

return (
<Text className={styles.container}>
<Text className={styles.row} variant='label' size='large'>
{messages.summary}
</Text>
<div className={styles.row}>
<span>{messages.premiumTrack}</span>
<span>{messages.price(formatPrice(basePrice))}</span>
</div>
{extraAmount != null ? (
<div className={styles.row}>
<span>{messages.payExtra}</span>
<span>{messages.price(formatPrice(extraAmount))}</span>
</div>
) : null}
{existingBalance != null ? (
<div className={styles.row}>
<span>{messages.existingBalance}</span>
<span>{`-${messages.price(formatPrice(existingBalance))}`}</span>
</div>
) : null}
<Text className={styles.row} variant='title'>
<span>{isPurchased ? messages.youPaid : messages.total}</span>
<span className={styles.finalPrice}>
{messages.price(formatPrice(amountDue))}
</span>
</Text>
</Text>
<SummaryTable
items={items}
title={messages.summary}
summaryItem={{
id: 'total',
label: isPurchased ? messages.youPaid : messages.total,
value: messages.price(formatPrice(amountDue))
}}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,3 @@
.row:last-child {
background: var(--background-surface-1);
}

.finalPrice {
color: var(--focus);
}
45 changes: 45 additions & 0 deletions packages/web/src/components/summary-table/SummaryTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { ReactNode } from 'react'

import { Text } from 'components/typography'

import styles from './SummaryTable.module.css'

export type SummaryTableItem = {
id: string
label: ReactNode
value: ReactNode
}

export type SummaryTableProps = {
items: SummaryTableItem[]
summaryItem: SummaryTableItem
title: ReactNode
}

export const SummaryTable = ({
items,
summaryItem,
title
}: SummaryTableProps) => {
return (
<div className={styles.container}>
<Text className={styles.row} variant='title' size='large'>
{title}
</Text>
{items.map(({ id, label, value }) => (
<div key={id} className={styles.row}>
<Text>{label}</Text>
<Text>{value}</Text>
</div>
))}
<div className={styles.row}>
<Text variant='title' size='medium'>
{summaryItem.label}
</Text>
<Text variant='title' size='medium' color='secondary'>
{summaryItem.value}
</Text>
</div>
</div>
)
}
1 change: 1 addition & 0 deletions packages/web/src/components/summary-table/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './SummaryTable'
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback } from 'react'

import { useGetTrackById, formatUSDCWeiToUSDString } from '@audius/common'
import { useGetTrackById } from '@audius/common'
import {
ModalHeader,
ModalTitle,
Expand All @@ -21,12 +21,12 @@ import { useGoToRoute } from 'hooks/useGoToRoute'

import { DetailSection } from './DetailSection'
import { TrackLink } from './TrackLink'
import { TransactionSummary } from './TransactionSummary'
import styles from './styles.module.css'
import { ContentProps } from './types'

const messages = {
by: 'By',
cost: 'Cost',
date: 'Date',
done: 'Done',
purchaseDetails: 'Purchase Details',
Expand Down Expand Up @@ -75,11 +75,7 @@ export const PurchaseModalContent = ({
{moment(purchaseDetails.createdAt).format('MMM DD, YYYY')}
</Text>
</DetailSection>
<DetailSection label={messages.cost}>
<Text size='large'>{`$${formatUSDCWeiToUSDString(
purchaseDetails.amount
)}`}</Text>
</DetailSection>
<TransactionSummary transaction={purchaseDetails} />
</ModalContent>
<ModalFooter className={styles.footer}>
<HarmonyButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
CommonState,
chatActions,
chatSelectors,
formatUSDCWeiToUSDString,
useInboxUnavailableModal
} from '@audius/common'
import {
Expand All @@ -27,14 +26,14 @@ import { UserNameAndBadges } from 'components/user-name-and-badges/UserNameAndBa

import { DetailSection } from './DetailSection'
import { TrackLink } from './TrackLink'
import { TransactionSummary } from './TransactionSummary'
import styles from './styles.module.css'
import { ContentProps } from './types'

const { getCanCreateChat } = chatSelectors
const { createChat } = chatActions

const messages = {
cost: 'Cost',
date: 'Date',
done: 'Done',
messageBuyer: 'Message Buyer',
Expand Down Expand Up @@ -97,11 +96,7 @@ export const SaleModalContent = ({
{moment(purchaseDetails.createdAt).format('MMM DD, YYYY')}
</Text>
</DetailSection>
<DetailSection label={messages.cost}>
<Text size='large'>{`$${formatUSDCWeiToUSDString(
purchaseDetails.amount
)}`}</Text>
</DetailSection>
<TransactionSummary transaction={purchaseDetails} />
</ModalContent>
<ModalFooter className={styles.footer}>
<HarmonyButton
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { USDCPurchaseDetails, formatUSDCWeiToUSDString } from '@audius/common'
import BN from 'bn.js'

import { SummaryTable, SummaryTableItem } from 'components/summary-table'

const messages = {
cost: 'Cost of Track',
payExtra: 'Pay Extra',
title: 'Transaction Summary',
total: 'Total'
}

export const TransactionSummary = ({
transaction
}: {
transaction: USDCPurchaseDetails
}) => {
const amountBN = new BN(transaction.amount)
const items: SummaryTableItem[] = [
{
id: 'cost',
label: messages.cost,
value: `$${formatUSDCWeiToUSDString(amountBN)}`
}
]
const extraAmountBN = new BN(transaction.extraAmount)
if (!extraAmountBN.isZero()) {
items.push({
id: 'payExtra',
label: messages.payExtra,
value: `$${formatUSDCWeiToUSDString(extraAmountBN)}`
})
}

return (
<SummaryTable
title={messages.title}
items={items}
summaryItem={{
id: 'total',
label: messages.total,
value: `$${formatUSDCWeiToUSDString(amountBN.add(extraAmountBN))}`
}}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
USDCContentPurchaseType,
USDCPurchaseDetails
} from '@audius/common'
import BN from 'bn.js'
import moment from 'moment'

import { Table } from 'components/table'
Expand Down Expand Up @@ -76,7 +77,8 @@ const renderDateCell = (cellInfo: PurchaseCell) => {

const renderValueCell = (cellInfo: PurchaseCell) => {
const transaction = cellInfo.row.original
return `$${formatUSDCWeiToUSDString(transaction.amount)}`
const total = new BN(transaction.amount).add(new BN(transaction.extraAmount))
return `$${formatUSDCWeiToUSDString(total)}`
}

// Columns
Expand Down
4 changes: 3 additions & 1 deletion packages/web/src/pages/purchases-and-sales/SalesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
USDCContentPurchaseType,
USDCPurchaseDetails
} from '@audius/common'
import { BN } from 'bn.js'
import moment from 'moment'

import { Table } from 'components/table'
Expand Down Expand Up @@ -73,7 +74,8 @@ const renderDateCell = (cellInfo: PurchaseCell) => {

const renderValueCell = (cellInfo: PurchaseCell) => {
const transaction = cellInfo.row.original
return `$${formatUSDCWeiToUSDString(transaction.amount)}`
const total = new BN(transaction.amount).add(new BN(transaction.extraAmount))
return `$${formatUSDCWeiToUSDString(total)}`
}

// Columns
Expand Down

0 comments on commit 9f7cf0c

Please sign in to comment.