From 8ff3b753ad80936eed9a474a4a8244dc39b73b35 Mon Sep 17 00:00:00 2001 From: mayeaux Date: Fri, 13 Aug 2021 19:59:43 +0200 Subject: [PATCH] Move transactions from Settings to Wallet (#6871) * remove unused conditional get stuff ready for merge bugfix and cleanup requested changes fixing flow errors fix last flow error and touchups fiat and lbc tabs coming along support setting currency as the default tab via query param add wallet fiat balance fixing naming add fiat transactions using es6 to populate data should be fine but keeps crashing transaction listing working add no transactions thing about to add a third tab add third tab add card last 4 to transaction history some renaming show payments successfully show filler for subscriptions display if no transactions or subs working but in the wrong component approaching something thats working showing total tipped amount about to add last couple features cleanup More touchups adding last features calculate the total amount of unique creators tipped couple touchups remove transaction listings from settings add view transactions buttons small optimization add subscriptions section fix lot of linting errors and make command more userful * some copy changes * about to add last couple changes * update still require verification * fix button spacing * hide subscriptions sections and fix links * cleanups before merging * more cleanup * cleanup with last four fix * changing tab functionality * bugfix and fix presentation of cards * fix transactions bug * change order and remove logs * remove unused code in account * more linter fixes * update account balance presentation * fix flow errors --- package.json | 2 +- ui/component/common/tabs.jsx | 2 +- .../walletFiatAccountHistory/index.js | 3 + .../walletFiatAccountHistory/view.jsx | 88 ++++++ ui/component/walletFiatBalance/index.js | 3 + ui/component/walletFiatBalance/view.jsx | 94 +++++++ .../walletFiatPaymentBalance/index.js | 3 + .../walletFiatPaymentBalance/view.jsx | 76 ++++++ .../walletFiatPaymentHistory/index.js | 3 + .../walletFiatPaymentHistory/view.jsx | 118 ++++++++ ui/page/settings/view.jsx | 76 +++--- ui/page/settingsStripeAccount/index.js | 5 +- ui/page/settingsStripeAccount/view.jsx | 257 +++++++----------- ui/page/settingsStripeCard/view.jsx | 76 +----- ui/page/wallet/view.jsx | 234 ++++++++++++++-- ui/scss/component/_stripe-card.scss | 4 + 16 files changed, 757 insertions(+), 287 deletions(-) create mode 100644 ui/component/walletFiatAccountHistory/index.js create mode 100644 ui/component/walletFiatAccountHistory/view.jsx create mode 100644 ui/component/walletFiatBalance/index.js create mode 100644 ui/component/walletFiatBalance/view.jsx create mode 100644 ui/component/walletFiatPaymentBalance/index.js create mode 100644 ui/component/walletFiatPaymentBalance/view.jsx create mode 100644 ui/component/walletFiatPaymentHistory/index.js create mode 100644 ui/component/walletFiatPaymentHistory/view.jsx diff --git a/package.json b/package.json index e6765f310..eb99f3de0 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "build:dir": "yarn build -- --dir -c.compression=store -c.mac.identity=null", "crossenv": "./node_modules/cross-env/dist/bin/cross-env", "lint": "eslint 'ui/**/*.{js,jsx}' && eslint 'web/**/*.{js,jsx}' && eslint 'electron/**/*.js' && flow", - "lint-fix": "eslint --fix 'ui/**/*.{js,jsx}' && eslint --fix 'web/**/*.{js,jsx}' && eslint --fix 'electron/**/*.js' && flow", + "lint-fix": "eslint --fix --quiet 'ui/**/*.{js,jsx}' && eslint --fix --quiet 'web/**/*.{js,jsx}' && eslint --fix --quiet 'electron/**/*.js'", "format": "prettier 'src/**/*.{js,jsx,scss,json}' --write", "flow-defs": "flow-typed install", "precommit": "lint-staged", diff --git a/ui/component/common/tabs.jsx b/ui/component/common/tabs.jsx index 6e08f6ad9..edd225f4a 100644 --- a/ui/component/common/tabs.jsx +++ b/ui/component/common/tabs.jsx @@ -28,7 +28,7 @@ import { useRect } from '@reach/rect'; // // // -// the base @reach/tabs components handle all the focus/accessibilty labels +// the base @reach/tabs components handle all the focus/accessibility labels // We're just adding some styling type TabsProps = { diff --git a/ui/component/walletFiatAccountHistory/index.js b/ui/component/walletFiatAccountHistory/index.js new file mode 100644 index 000000000..8fed953a8 --- /dev/null +++ b/ui/component/walletFiatAccountHistory/index.js @@ -0,0 +1,3 @@ +import FiatAccountHistory from './view'; + +export default FiatAccountHistory; diff --git a/ui/component/walletFiatAccountHistory/view.jsx b/ui/component/walletFiatAccountHistory/view.jsx new file mode 100644 index 000000000..49b1ff299 --- /dev/null +++ b/ui/component/walletFiatAccountHistory/view.jsx @@ -0,0 +1,88 @@ +// @flow +import React from 'react'; +import Button from 'component/button'; +import Card from 'component/common/card'; +import moment from 'moment'; + +type Props = { + accountDetails: any, + transactions: any, +}; + +const WalletBalance = (props: Props) => { + // receive transactions from parent component + const { transactions } = props; + + let accountTransactions; + + // reverse so most recent payments come first + if (transactions && transactions.length) { + accountTransactions = transactions.reverse(); + } + + // if there are more than 10 transactions, limit it to 10 for the frontend + if (accountTransactions && accountTransactions.length > 10) { + accountTransactions.length = 10; + } + + return ( + <> +
+ + + + + + + + + + + + + + {accountTransactions && + accountTransactions.map((transaction) => ( + + + + + + + + + + ))} + +
{__('Date')}{<>{__('Receiving Channel Name')}}{__('Tip Location')}{__('Amount (USD)')} {__('Processing Fee')}{__('Odysee Fee')}{__('Received Amount')}
{moment(transaction.created_at).format('LLL')} + + ${transaction.tipped_amount / 100}${transaction.transaction_fee / 100}${transaction.application_fee / 100}${transaction.received_amount / 100}
+ {!accountTransactions &&

No Transactions

} +
+ + )} + /> + + ); +}; + +export default WalletBalance; diff --git a/ui/component/walletFiatBalance/index.js b/ui/component/walletFiatBalance/index.js new file mode 100644 index 000000000..b35b2d4af --- /dev/null +++ b/ui/component/walletFiatBalance/index.js @@ -0,0 +1,3 @@ +import WalletFiatBalance from './view'; + +export default WalletFiatBalance; diff --git a/ui/component/walletFiatBalance/view.jsx b/ui/component/walletFiatBalance/view.jsx new file mode 100644 index 000000000..9c71623ba --- /dev/null +++ b/ui/component/walletFiatBalance/view.jsx @@ -0,0 +1,94 @@ +// @flow +import * as ICONS from 'constants/icons'; +import * as PAGES from 'constants/pages'; +import React from 'react'; +import Button from 'component/button'; +import Card from 'component/common/card'; +import Icon from 'component/common/icon'; +import I18nMessage from 'component/i18nMessage'; + +type Props = { + accountDetails: any, +}; + +const WalletBalance = (props: Props) => { + const { + accountDetails, + } = props; + + return ( + <>{{(accountDetails && ((accountDetails.total_received_unpaid - accountDetails.total_paid_out) / 100)) || 0} USD} + subtitle={accountDetails && accountDetails.total_received_unpaid > 0 && + + This is your pending balance that will be automatically sent to your bank account + + } + actions={ + <> +

+ ${(accountDetails && (accountDetails.total_received_unpaid / 100)) || 0} Total Received Tips +

+ +

+ ${(accountDetails && (accountDetails.total_paid_out / 100)) || 0} Withdrawn + {/*

+ + {/* view more section */} + {/* commenting out because not implemented, but could be used in the future */} + {/* {detailsExpanded && ( */} + {/*
*/} + {/*
*/} + {/*
*/} + {/* {__('Earned from uploads')} */} + {/* /!* ({__('Earned from channel page')}) *!/ */} + {/*
*/} + {/*
*/} + {/* */} + {/* {Boolean(1) && ( */} + {/*
*/} + + {/*
*/} + {/* {__('Earned from channel page')} */} + {/* /!* ({__('Delete or edit past content to spend')}) *!/ */} + {/*
*/} + {/*
*/} + {/* */} + {/*
*/} + + {/* /!*
*!/ */} + {/* /!* {__('...supporting content')} *!/ */} + {/* /!* ({__('Delete supports to spend')}) *!/ */} + {/* /!*
*!/ */} + {/* /!*
*!/ */} + {/* /!* *!/ */} + {/* /!*
*!/ */} + {/*
*/} + {/*
*/} + {/* )} */} + +
+ {/*
+ + } + />} + ); +}; + +export default WalletBalance; diff --git a/ui/component/walletFiatPaymentBalance/index.js b/ui/component/walletFiatPaymentBalance/index.js new file mode 100644 index 000000000..d40e374be --- /dev/null +++ b/ui/component/walletFiatPaymentBalance/index.js @@ -0,0 +1,3 @@ +import WalletFiatPaymentBalance from './view'; + +export default WalletFiatPaymentBalance; diff --git a/ui/component/walletFiatPaymentBalance/view.jsx b/ui/component/walletFiatPaymentBalance/view.jsx new file mode 100644 index 000000000..3b8032d3a --- /dev/null +++ b/ui/component/walletFiatPaymentBalance/view.jsx @@ -0,0 +1,76 @@ +// @flow +import * as ICONS from 'constants/icons'; +import * as PAGES from 'constants/pages'; +import React from 'react'; +import Button from 'component/button'; +import Card from 'component/common/card'; + +type Props = { + totalTippedAmount: number, + accountDetails: any, + transactions: any, +}; + +const WalletBalance = (props: Props) => { + const { + // accountDetails, + transactions, + } = props; + + // let cardDetails = { + // brand: card.brand, + // expiryYear: card.exp_year, + // expiryMonth: card.exp_month, + // lastFour: card.last4, + // topOfDisplay: topOfDisplay, + // bottomOfDisplay: bottomOfDisplay, + // }; + + // const [detailsExpanded, setDetailsExpanded] = React.useState(false); + const [totalCreatorsSupported, setTotalCreatorsSupported] = React.useState(false); + + // calculate how many unique users tipped + React.useEffect(() => { + if (transactions) { + let channelNames = []; + + for (const transaction of transactions) { + channelNames.push(transaction.channel_name); + } + + let unique = [...new Set(channelNames)]; + setTotalCreatorsSupported(unique.length); + } + }, [transactions]); + + return ( + <>{Hello + // // + // } + actions={ + <> +

+ {(transactions && transactions.length) || 0} Total Tips +

+ +

+ {totalCreatorsSupported || 0} Creators Supported +

+ +
+
+ + } + />} + ); +}; + +export default WalletBalance; diff --git a/ui/component/walletFiatPaymentHistory/index.js b/ui/component/walletFiatPaymentHistory/index.js new file mode 100644 index 000000000..0d41b2e19 --- /dev/null +++ b/ui/component/walletFiatPaymentHistory/index.js @@ -0,0 +1,3 @@ +import WalletFiatPaymentHistory from './view'; + +export default WalletFiatPaymentHistory; diff --git a/ui/component/walletFiatPaymentHistory/view.jsx b/ui/component/walletFiatPaymentHistory/view.jsx new file mode 100644 index 000000000..da2e3dc96 --- /dev/null +++ b/ui/component/walletFiatPaymentHistory/view.jsx @@ -0,0 +1,118 @@ +// @flow +import React from 'react'; +import Button from 'component/button'; +import Card from 'component/common/card'; +import { Lbryio } from 'lbryinc'; +import moment from 'moment'; +import { STRIPE_PUBLIC_KEY } from 'config'; + +let stripeEnvironment = 'test'; +// if the key contains pk_live it's a live key +// update the environment for the calls to the backend to indicate which environment to hit +if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) { + stripeEnvironment = 'live'; +} + +type Props = { + accountDetails: any, + transactions: any, +}; + +const WalletBalance = (props: Props) => { + // receive transactions from parent component + const { transactions } = props; + + let accountTransactions; + + // reverse so most recent payments come first + if (transactions && transactions.length) { + accountTransactions = transactions.reverse(); + } + // const [accountStatusResponse, setAccountStatusResponse] = React.useState(); + + // const [subscriptions, setSubscriptions] = React.useState(); + + const [lastFour, setLastFour] = React.useState(); + + function getCustomerStatus() { + return Lbryio.call( + 'customer', + 'status', + { + environment: stripeEnvironment, + }, + 'post' + ); + } + + // TODO: this is actually incorrect, last4 should be populated based on the transaction not the current customer details + React.useEffect(() => { + (async function() { + const customerStatusResponse = await getCustomerStatus(); + + const lastFour = customerStatusResponse.PaymentMethods && customerStatusResponse.PaymentMethods.length && customerStatusResponse.PaymentMethods[0].card.last4; + + setLastFour(lastFour); + })(); + }, []); + + return ( + <> + +
+ + + + + + + + + + + + + {accountTransactions && + accountTransactions.map((transaction) => ( + + + + + + + + + ))} + +
{__('Date')}{<>{__('Receiving Channel Name')}}{__('Tip Location')}{__('Amount (USD)')} {__('Card Last 4')}{__('Anonymous')}
{moment(transaction.created_at).format('LLL')} + + ${transaction.tipped_amount / 100}{lastFour}{transaction.private_tip ? 'Yes' : 'No'}
+ {(!accountTransactions || accountTransactions.length === 0) &&

No Transactions

} +
+ + } + /> + + ); +}; + +export default WalletBalance; diff --git a/ui/page/settings/view.jsx b/ui/page/settings/view.jsx index 034a2ee28..3f201373a 100644 --- a/ui/page/settings/view.jsx +++ b/ui/page/settings/view.jsx @@ -208,44 +208,6 @@ class SettingsPage extends React.PureComponent { }} className="card-stack" > - {/* @if TARGET='web' */} - {user && user.fiat_enabled && ( - -