From 329be8b28c7fd818f8a1a02b884174d23ada28db Mon Sep 17 00:00:00 2001 From: KJ Shanks Date: Thu, 29 Sep 2022 14:45:11 -0400 Subject: [PATCH] Add AudioTransactionsPage and display tiest data in AudioTransactionsTable --- .../AudioTransactionsTable.module.css | 20 + .../AudioTransactionsTable.tsx | 213 +++++++++++ .../audio-transactions-table/index.ts | 1 + .../test-table/TestTable.module.css | 1 + .../components/tracks-table/TracksTable.js | 8 +- packages/web/src/pages/App.js | 8 + .../AudioTransactionsPage.module.css | 27 ++ .../AudioTransactionsPage.tsx | 341 ++++++++++++++++++ .../pages/audio-transactions-page/index.ts | 1 + packages/web/src/utils/route.ts | 3 + 10 files changed, 619 insertions(+), 4 deletions(-) create mode 100644 packages/web/src/components/audio-transactions-table/AudioTransactionsTable.module.css create mode 100644 packages/web/src/components/audio-transactions-table/AudioTransactionsTable.tsx create mode 100644 packages/web/src/components/audio-transactions-table/index.ts create mode 100644 packages/web/src/pages/audio-transactions-page/AudioTransactionsPage.module.css create mode 100644 packages/web/src/pages/audio-transactions-page/AudioTransactionsPage.tsx create mode 100644 packages/web/src/pages/audio-transactions-page/index.ts diff --git a/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.module.css b/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.module.css new file mode 100644 index 0000000000..d1a1449c47 --- /dev/null +++ b/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.module.css @@ -0,0 +1,20 @@ +.textContainer { + position: relative; + display: inline-flex; + gap: 4px; + max-width: 100%; +} + +.textCell { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + line-height: 1.2; +} + +.changeCell.increase { + color: var(--accent-green); +} +.changeCell.decrease { + color: var(--accent-orange); +} diff --git a/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.tsx b/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.tsx new file mode 100644 index 0000000000..6f4eb5cad5 --- /dev/null +++ b/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.tsx @@ -0,0 +1,213 @@ +import { useCallback, useMemo } from 'react' + +import { + formatNumberCommas, + TransactionMethod, + TransactionType +} from '@audius/common' +import cn from 'classnames' +import moment from 'moment' +import { ColumnInstance } from 'react-table' + +import { AudioTransactionIcon } from 'components/audio-transaction-icon' +import { TestTable } from 'components/test-table' + +import styles from './AudioTransactionsTable.module.css' + +const transactionTypeLabelMap: Record = { + [TransactionType.TRANSFER]: '$AUDIO', + [TransactionType.CHALLENGE_REWARD]: '$AUDIO Reward Earned', + [TransactionType.TRENDING_REWARD]: 'Trending Competition Award', + [TransactionType.TIP]: 'Tip', + [TransactionType.PURCHASE]: 'Purchased $AUDIO' +} + +const transactionMethodLabelMap: Record = { + [TransactionMethod.COINBASE]: null, + [TransactionMethod.STRIPE]: null, + [TransactionMethod.RECEIVE]: 'Received', + [TransactionMethod.SEND]: 'Sent' +} + +export type AudioTransactionsTableColumn = + | 'balance' + | 'change' + | 'date' + | 'transactionIcon' + | 'transactionType' + | 'spacer' + | 'spacer2' + +type AudioTransactionsTableProps = { + columns?: AudioTransactionsTableColumn[] + data: any[] + isVirtualized?: boolean + loading?: boolean + onClickRow?: (collectible: any, index: number) => void + tableClassName?: string + wrapperClassName?: string +} + +const defaultColumns: AudioTransactionsTableColumn[] = [ + 'spacer', + 'transactionIcon', + 'transactionType', + 'date', + 'change', + 'balance', + 'spacer2' +] + +export const AudioTransactionsTable = ({ + columns = defaultColumns, + data, + isVirtualized = false, + loading = false, + onClickRow, + tableClassName, + wrapperClassName +}: AudioTransactionsTableProps) => { + // Cell Render Functions + const renderTransactionIconCell = useCallback((cellInfo) => { + const { transactionType, method } = cellInfo.row.original + return + }, []) + + const renderTransactionTypeCell = useCallback((cellInfo) => { + const { transactionType, method } = cellInfo.row.original + const typeText = transactionTypeLabelMap[transactionType as TransactionType] + const methodText = + transactionMethodLabelMap[method as TransactionMethod] ?? '' + + const isTransferType = + transactionType === TransactionType.TIP || + transactionType === TransactionType.TRANSFER + + return `${typeText} ${isTransferType ? methodText : ''}`.trim() + }, []) + + const renderBalanceCell = useCallback((cellInfo) => { + const transaction = cellInfo.row.original + return formatNumberCommas(transaction.balance) + }, []) + + const renderDateCell = useCallback((cellInfo) => { + const transaction = cellInfo.row.original + return moment(transaction.date).format('M/D/YY') + }, []) + + const renderChangeCell = useCallback((cellInfo) => { + const { change } = cellInfo.row.original + return ( +
0, + [styles.decrease]: Number(change) < 0 + })} + > + {Number(change) > 0 ? '+' : ''} + {change} +
+ ) + }, []) + + // Columns + const tableColumnMap: Record< + AudioTransactionsTableColumn, + Partial + > = useMemo( + () => ({ + transactionIcon: { + id: 'transactionIcon', + accessor: '', + Cell: renderTransactionIconCell, + minWidth: 64, + maxWidth: 64, + disableResizing: true, + disableSortBy: true + }, + transactionType: { + id: 'transactionType', + Header: 'Transaction Type', + accessor: 'type', + Cell: renderTransactionTypeCell, + width: 150, + disableSortBy: true, + align: 'left' + }, + date: { + id: 'date', + Header: 'Date', + accessor: 'date', + Cell: renderDateCell, + disableSortBy: true, + align: 'right' + }, + change: { + id: 'change', + Header: 'Change', + accessor: 'change', + Cell: renderChangeCell, + disableSortBy: true, + align: 'right' + }, + balance: { + id: 'balance', + Header: 'Balance', + accessor: 'balance', + Cell: renderBalanceCell, + disableSortBy: true, + align: 'right' + }, + spacer: { + id: 'spacer', + maxWidth: 24, + minWidth: 24, + disableSortBy: true, + disableResizing: true + }, + spacer2: { + id: 'spacer2', + maxWidth: 24, + minWidth: 24, + disableSortBy: true, + disableResizing: true + } + }), + [ + renderTransactionIconCell, + renderTransactionTypeCell, + renderDateCell, + renderChangeCell, + renderBalanceCell + ] + ) + + const tableColumns = useMemo( + () => columns.map((id) => tableColumnMap[id]), + [columns, tableColumnMap] + ) + + const handleClickRow = useCallback( + (rowInfo, index: number) => { + const transaction = rowInfo.original + onClickRow?.(transaction, index) + }, + [onClickRow] + ) + + const getRowClassName = useCallback(() => '', []) + + return ( + + ) +} diff --git a/packages/web/src/components/audio-transactions-table/index.ts b/packages/web/src/components/audio-transactions-table/index.ts new file mode 100644 index 0000000000..e3aa6f81db --- /dev/null +++ b/packages/web/src/components/audio-transactions-table/index.ts @@ -0,0 +1 @@ +export { AudioTransactionsTable } from './AudioTransactionsTable' diff --git a/packages/web/src/components/test-table/TestTable.module.css b/packages/web/src/components/test-table/TestTable.module.css index e497c1f1ec..655f685f10 100644 --- a/packages/web/src/components/test-table/TestTable.module.css +++ b/packages/web/src/components/test-table/TestTable.module.css @@ -199,6 +199,7 @@ align-items: center; vertical-align: middle; justify-content: center; + height: 64px; padding: 20px 12px; background: transparent; user-select: none; diff --git a/packages/web/src/components/tracks-table/TracksTable.js b/packages/web/src/components/tracks-table/TracksTable.js index a17ea9d1c5..f2cabdcdb7 100644 --- a/packages/web/src/components/tracks-table/TracksTable.js +++ b/packages/web/src/components/tracks-table/TracksTable.js @@ -87,7 +87,7 @@ const artistNameCell = (val, record, props) => { return `${record.user?.name} [Deactivated]` } return ( - +
{ @@ -133,7 +133,7 @@ const optionsButtonCell = ( props, storeActionButtonRefs ) => { - const deleted = record.is_delete || !!record.user.is_deactivated + const deleted = record.is_delete || !!record.user?.is_deactivated const optionsButtonRef = createRef() storeActionButtonRefs(record.key, optionsButtonRef) @@ -150,8 +150,8 @@ const optionsButtonCell = ( date={val.date} isFavorited={val.has_current_user_saved} isOwner={record.owner_id === props.userId} - isOwnerDeactivated={!!record.user.is_deactivated} - isArtistPick={val.user._artist_pick === val.track_id} + isOwnerDeactivated={!!record.user?.is_deactivated} + isArtistPick={val.user?._artist_pick === val.track_id} index={index} trackTitle={val.name} albumId={null} diff --git a/packages/web/src/pages/App.js b/packages/web/src/pages/App.js index 8e130832b4..d8ec93d870 100644 --- a/packages/web/src/pages/App.js +++ b/packages/web/src/pages/App.js @@ -49,6 +49,7 @@ import TrendingGenreSelectionPage from 'components/trending-genre-selection/Tren import AnnouncementPage from 'pages/announcement-page/AnnoucementPage' import ArtistDashboardPage from 'pages/artist-dashboard-page/ArtistDashboardPage' import { AudioRewardsPage } from 'pages/audio-rewards-page/AudioRewardsPage' +import { AudioTransactionsPage } from 'pages/audio-transactions-page' import CheckPage from 'pages/check-page/CheckPage' import CollectionPage from 'pages/collection-page/CollectionPage' import EmptyPage from 'pages/empty-page/EmptyPage' @@ -100,6 +101,7 @@ import { HISTORY_PAGE, DASHBOARD_PAGE, AUDIO_PAGE, + AUDIO_TRANSACTIONS_PAGE, UPLOAD_PAGE, UPLOAD_ALBUM_PAGE, UPLOAD_PLAYLIST_PAGE, @@ -783,6 +785,12 @@ class App extends Component { isMobile={isMobileClient} component={AudioRewardsPage} /> + { + const { isEnabled: isNewTablesEnabled } = useFlag(FeatureFlags.NEW_TABLES) + const tableLoading = !data.every((transaction: any) => + Boolean(transaction.signature) + ) + const isEmpty = data.length === 0 + + const userId = useSelector(getUserId) + + return ( + } + > +
+ {isEmpty && !tableLoading ? ( + + ) : isNewTablesEnabled ? ( + + ) : ( +
+ +
+ )} +
+
+ ) +} diff --git a/packages/web/src/pages/audio-transactions-page/index.ts b/packages/web/src/pages/audio-transactions-page/index.ts new file mode 100644 index 0000000000..bc38bb533e --- /dev/null +++ b/packages/web/src/pages/audio-transactions-page/index.ts @@ -0,0 +1 @@ +export { AudioTransactionsPage } from './AudioTransactionsPage' diff --git a/packages/web/src/utils/route.ts b/packages/web/src/utils/route.ts index f50f910d28..50bc7058c4 100644 --- a/packages/web/src/utils/route.ts +++ b/packages/web/src/utils/route.ts @@ -67,6 +67,7 @@ export const FAVORITES_PAGE = '/favorites' export const HISTORY_PAGE = '/history' export const DASHBOARD_PAGE = '/dashboard' export const AUDIO_PAGE = '/audio' +export const AUDIO_TRANSACTIONS_PAGE = '/audio/transactions' export const UPLOAD_PAGE = '/upload' export const UPLOAD_ALBUM_PAGE = '/upload/album' export const UPLOAD_PLAYLIST_PAGE = '/upload/playlist' @@ -187,6 +188,7 @@ export const orderedRoutes = [ HISTORY_PAGE, DASHBOARD_PAGE, AUDIO_PAGE, + AUDIO_TRANSACTIONS_PAGE, SETTINGS_PAGE, ACCOUNT_SETTINGS_PAGE, NOTIFICATION_SETTINGS_PAGE, @@ -216,6 +218,7 @@ export const staticRoutes = new Set([ HISTORY_PAGE, DASHBOARD_PAGE, AUDIO_PAGE, + AUDIO_TRANSACTIONS_PAGE, UPLOAD_PAGE, UPLOAD_ALBUM_PAGE, UPLOAD_PLAYLIST_PAGE,