This commit is contained in:
zeppi 2021-07-17 12:08:53 -04:00 committed by jessopb
parent 7bb5df97fd
commit 27aa4e4a22
9 changed files with 196 additions and 195 deletions

View file

@ -14,6 +14,7 @@ declare type Comment = {
is_pinned: boolean,
support_amount: number,
replies: number, // number of direct replies (i.e. excluding nested replies).
is_fiat?: boolean,
};
declare type PerChannelSettings = {

View file

@ -18,7 +18,7 @@ type Props = {
size?: number,
superChat?: boolean,
superChatLight?: boolean,
isFiat?: boolean
isFiat?: boolean,
};
class CreditAmount extends React.PureComponent<Props> {
@ -75,7 +75,7 @@ class CreditAmount extends React.PureComponent<Props> {
if (showLBC && !isFiat) {
amountText = <LbcSymbol postfix={amountText} size={size} />;
} else if (showLBC && isFiat) {
amountText = <p> ${(Math.round(amountText * 100) / 100).toFixed(2)}</p>;
amountText = <p> ${(Math.round(Number(amountText) * 100) / 100).toFixed(2)}</p>;
}
if (fee) {

View file

@ -8,6 +8,6 @@ const select = (state) => ({
user: selectUser(state),
});
const perform = (dispatch) => ({});
// const perform = (dispatch) => ({});
export default withRouter(connect(select, perform)(StripeAccountConnection));
export default withRouter(connect(select)(StripeAccountConnection));

View file

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import { selectBalance } from 'lbry-redux';
import WalletSpendableBalanceHelp from './view';
const select = (state, props) => ({
const select = (state) => ({
balance: selectBalance(state),
});

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux';
import { makeSelectClaimForUri, selectBalance } from 'lbry-redux';
import { selectBalance } from 'lbry-redux';
import WalletTipAmountSelector from './view';
import { selectUserVerifiedEmail } from 'redux/selectors/user';

View file

@ -33,10 +33,11 @@ type Props = {
claim: StreamClaim,
uri: string,
onTipErrorChange: (string) => void,
activeTab: string,
};
function WalletTipAmountSelector(props: Props) {
const { balance, amount, onChange, activeTab, isAuthenticated, claim, uri, onTipErrorChange } = props;
const { balance, amount, onChange, activeTab, claim, onTipErrorChange } = props;
const [useCustomTip, setUseCustomTip] = usePersistedState('comment-support:useCustomTip', false);
const [tipError, setTipError] = React.useState();
@ -106,19 +107,18 @@ function WalletTipAmountSelector(props: Props) {
setCanReceiveFiatTip(true);
}
})
.catch(function(error) {
.catch(function (error) {
// console.log(error);
});
}, []);
React.useEffect(() => {
// setHasSavedCard(false);
// setCanReceiveFiatTip(true);
const regexp = RegExp(/^(\d*([.]\d{0,8})?)$/);
const validTipInput = regexp.test(String(amount));
let tipError;
let tipError = '';
if (amount === 0) {
tipError = __('Amount must be a positive number');
@ -196,49 +196,52 @@ function WalletTipAmountSelector(props: Props) {
)}
</div>
{useCustomTip && activeTab === TAB_FIAT && !hasCardSaved &&
<>
<div className="help">
<span className="help--spendable">
<Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card ')} button="link" /> To {__(' Tip Creators')}
</span>
</div>
</>
}
{useCustomTip && activeTab === TAB_FIAT && !hasCardSaved && (
<>
<div className="help">
<span className="help--spendable">
<Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card ')} button="link" /> To{' '}
{__(' Tip Creators')}
</span>
</div>
</>
)}
{/* has card saved but cant creator cant receive tips */}
{useCustomTip && activeTab === TAB_FIAT && hasCardSaved && !canReceiveFiatTip &&
<>
<div className="help">
<span className="help--spendable">Only select creators can receive tips at this time</span>
</div>
</>
}
{useCustomTip && activeTab === TAB_FIAT && hasCardSaved && !canReceiveFiatTip && (
<>
<div className="help">
<span className="help--spendable">Only select creators can receive tips at this time</span>
</div>
</>
)}
{/* has card saved but cant creator cant receive tips */}
{useCustomTip && activeTab === TAB_FIAT && hasCardSaved && canReceiveFiatTip &&
<>
<div className="help">
<span className="help--spendable">Send a tip directly from your attached card</span>
</div>
</>
}
{useCustomTip && activeTab === TAB_FIAT && hasCardSaved && canReceiveFiatTip && (
<>
<div className="help">
<span className="help--spendable">Send a tip directly from your attached card</span>
</div>
</>
)}
{useCustomTip && (
<div className="comment__tip-input">
<FormField
autoFocus
name="tip-input"
label={ activeTab === TAB_LBC ?
<React.Fragment>
{__('Custom support amount')}{' '}
<I18nMessage tokens={{ lbc_balance: <CreditAmount precision={4} amount={balance} /> }}>
(%lbc_balance% available)
</I18nMessage>
</React.Fragment>
// TODO: add conditional based on hasSavedCard
: <>
</>
label={
activeTab === TAB_LBC ? (
<React.Fragment>
{__('Custom support amount')}{' '}
<I18nMessage tokens={{ lbc_balance: <CreditAmount precision={4} amount={balance} /> }}>
(%lbc_balance% available)
</I18nMessage>
</React.Fragment>
) : (
// TODO: add conditional based on hasSavedCard
<></>
)
// <>
// <div className="">
@ -258,38 +261,37 @@ function WalletTipAmountSelector(props: Props) {
</div>
)}
{/*// TODO: add conditional based on hasSavedCard*/}
{/* lbc tab */}
{activeTab === TAB_LBC && <WalletSpendableBalanceHelp />}
{/* fiat button but no card saved */}
{!useCustomTip && activeTab === TAB_FIAT && !hasCardSaved &&
<>
<div className="help">
<span className="help--spendable">
<Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card ')} button="link" /> To {__(' Tip Creators')}
</span>
</div>
</>
}
{!useCustomTip && activeTab === TAB_FIAT && !hasCardSaved && (
<>
<div className="help">
<span className="help--spendable">
<Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card ')} button="link" /> To{' '}
{__(' Tip Creators')}
</span>
</div>
</>
)}
{/* has card saved but cant creator cant receive tips */}
{!useCustomTip && activeTab === TAB_FIAT && hasCardSaved && !canReceiveFiatTip &&
<>
<div className="help">
<span className="help--spendable">Only select creators can receive tips at this time</span>
</div>
</>
}
{!useCustomTip && activeTab === TAB_FIAT && hasCardSaved && !canReceiveFiatTip && (
<>
<div className="help">
<span className="help--spendable">Only select creators can receive tips at this time</span>
</div>
</>
)}
{/* has card saved but cant creator cant receive tips */}
{!useCustomTip && activeTab === TAB_FIAT && hasCardSaved && canReceiveFiatTip &&
<>
<div className="help">
<span className="help--spendable">Send a tip directly from your attached card</span>
</div>
</>
}
{!useCustomTip && activeTab === TAB_FIAT && hasCardSaved && canReceiveFiatTip && (
<>
<div className="help">
<span className="help--spendable">Send a tip directly from your attached card</span>
</div>
</>
)}
</>
);
}

View file

@ -8,6 +8,6 @@ const select = (state) => ({
user: selectUser(state),
});
const perform = (dispatch) => ({});
// const perform = (dispatch) => ({});
export default withRouter(connect(select, perform)(StripeAccountConnection));
export default withRouter(connect(select)(StripeAccountConnection));

View file

@ -44,6 +44,7 @@ type State = {
accountNotConfirmedButReceivedTips: boolean,
unpaidBalance: number,
pageTitle: string,
accountTransactions: any, // define this type
};
class StripeAccountConnection extends React.Component<Props, State> {
@ -123,15 +124,14 @@ class StripeAccountConnection extends React.Component<Props, State> {
environment: stripeEnvironment,
},
'post'
)
.then((accountListResponse) => {
that.setState({
accountTransactions: accountListResponse,
});
console.log(accountListResponse);
).then((accountListResponse: any) => {
// TODO type this
that.setState({
accountTransactions: accountListResponse,
});
console.log(accountListResponse);
});
}
// if charges already enabled, no need to generate an account link
@ -227,16 +227,15 @@ class StripeAccountConnection extends React.Component<Props, State> {
<div>
<br />
<h3>
{__(
'Your pending account balance is $%balance% USD.',
{ balance: unpaidBalance / 100 }
)}
{__('Your pending account balance is $%balance% USD.', { balance: unpaidBalance / 100 })}
</h3>
</div>
) : (
<div>
<br />
<h3>{__('Your account balance is $0 USD. When you receive a tip you will see it here.')}</h3>
<h3>
{__('Your account balance is $0 USD. When you receive a tip you will see it here.')}
</h3>
</div>
)}
</div>
@ -251,16 +250,15 @@ class StripeAccountConnection extends React.Component<Props, State> {
<div>
<br />
<h3>
{__(
'Your pending account balance is $%balance% USD.',
{ balance: unpaidBalance / 100 }
)}
{__('Your pending account balance is $%balance% USD.', { balance: unpaidBalance / 100 })}
</h3>
</div>
<br />
<div>
<h3>
{__('Connect your bank account to be able to cash your pending balance out to your account.')}
{__(
'Connect your bank account to be able to cash your pending balance out to your account.'
)}
</h3>
</div>
<div className="section__actions">
@ -277,10 +275,8 @@ class StripeAccountConnection extends React.Component<Props, State> {
/>
<br />
{/* customer already has transactions */}
{accountTransactions && accountTransactions.length > 0 && (
<Card
title={__('Tip History')}
body={
@ -288,44 +284,47 @@ class StripeAccountConnection extends React.Component<Props, State> {
<div className="table__wrapper">
<table className="table table--transactions">
<thead>
<tr>
<th className="date-header">{__('Date')}</th>
<th>{<>{__('Receiving Channel Name')}</>}</th>
<th>{__('Tip Location')}</th>
<th>{__('Amount (USD)')} </th>
<th>{__('Processing Fee')}</th>
<th>{__('Odysee Fee')}</th>
<th>{__('Received Amount')}</th>
</tr>
<tr>
<th className="date-header">{__('Date')}</th>
<th>{<>{__('Receiving Channel Name')}</>}</th>
<th>{__('Tip Location')}</th>
<th>{__('Amount (USD)')} </th>
<th>{__('Processing Fee')}</th>
<th>{__('Odysee Fee')}</th>
<th>{__('Received Amount')}</th>
</tr>
</thead>
<tbody>
{accountTransactions &&
accountTransactions.reverse().map((transaction) => (
<tr key={transaction.name + transaction.created_at}>
<td>{moment(transaction.created_at).format('LLL')}</td>
<td>
<Button
className="stripe__card-link-text"
navigate={'/' + transaction.channel_name + ':' + transaction.channel_claim_id}
label={transaction.channel_name}
button="link"
/>
</td>
<td>
<Button
className="stripe__card-link-text"
navigate={'/' + transaction.channel_name + ':' + transaction.source_claim_id}
label={transaction.channel_claim_id === transaction.source_claim_id ? 'Channel Page' : 'File Page'}
button="link"
/>
</td>
<td>${transaction.tipped_amount / 100}</td>
<td>${transaction.transaction_fee / 100}</td>
<td>${transaction.application_fee / 100}</td>
<td>${transaction.received_amount / 100}</td>
</tr>
))}
{accountTransactions &&
accountTransactions.reverse().map((transaction) => (
<tr key={transaction.name + transaction.created_at}>
<td>{moment(transaction.created_at).format('LLL')}</td>
<td>
<Button
className="stripe__card-link-text"
navigate={'/' + transaction.channel_name + ':' + transaction.channel_claim_id}
label={transaction.channel_name}
button="link"
/>
</td>
<td>
<Button
className="stripe__card-link-text"
navigate={'/' + transaction.channel_name + ':' + transaction.source_claim_id}
label={
transaction.channel_claim_id === transaction.source_claim_id
? 'Channel Page'
: 'File Page'
}
button="link"
/>
</td>
<td>${transaction.tipped_amount / 100}</td>
<td>${transaction.transaction_fee / 100}</td>
<td>${transaction.application_fee / 100}</td>
<td>${transaction.received_amount / 100}</td>
</tr>
))}
</tbody>
</table>
</div>

View file

@ -55,11 +55,11 @@ class SettingsStripeCard extends React.Component<Props, State> {
}
componentDidMount() {
var that = this;
let that = this;
console.log(this.props);
var doToast = this.props.doToast;
let doToast = this.props.doToast;
const script = document.createElement('script');
script.src = 'https://js.stripe.com/v3/';
@ -69,14 +69,14 @@ class SettingsStripeCard extends React.Component<Props, State> {
document.body.appendChild(script);
// public key of the stripe account
var publicKey = STRIPE_PUBLIC_KEY;
let publicKey = STRIPE_PUBLIC_KEY;
// client secret of the SetupIntent (don't share with anyone but customer)
var clientSecret = '';
let clientSecret = '';
// setting a timeout to let the client secret populate
// TODO: fix this, should be a cleaner way
setTimeout(function() {
setTimeout(function () {
// check if customer has card setup already
Lbryio.call(
'customer',
@ -89,20 +89,20 @@ class SettingsStripeCard extends React.Component<Props, State> {
.then((customerStatusResponse) => {
// user has a card saved if their defaultPaymentMethod has an id
const defaultPaymentMethod = customerStatusResponse.Customer.invoice_settings.default_payment_method;
var userHasAlreadySetupPayment = Boolean(defaultPaymentMethod && defaultPaymentMethod.id);
let userHasAlreadySetupPayment = Boolean(defaultPaymentMethod && defaultPaymentMethod.id);
// show different frontend if user already has card
if (userHasAlreadySetupPayment) {
var card = customerStatusResponse.PaymentMethods[0].card;
let card = customerStatusResponse.PaymentMethods[0].card;
var customer = customerStatusResponse.Customer;
let customer = customerStatusResponse.Customer;
var topOfDisplay = customer.email.split('@')[0];
var bottomOfDisplay = '@' + customer.email.split('@')[1];
let topOfDisplay = customer.email.split('@')[0];
let bottomOfDisplay = '@' + customer.email.split('@')[1];
console.log(customerStatusResponse.Customer);
var cardDetails = {
let cardDetails = {
brand: card.brand,
expiryYear: card.exp_year,
expiryMonth: card.exp_month,
@ -159,7 +159,7 @@ class SettingsStripeCard extends React.Component<Props, State> {
});
// if the status call fails, either an actual error or need to run setup first
})
.catch(function(error) {
.catch(function (error) {
console.log(error);
// errorString passed from the API (with a 403 error)
@ -189,7 +189,7 @@ class SettingsStripeCard extends React.Component<Props, State> {
setupStripe();
});
} else if (error === 'internal_apis_down') {
var displayString = 'There was an error from the server, please let support know'
var displayString = 'There was an error from the server, please let support know';
doToast({ message: displayString, isError: true });
} else {
console.log('Unseen before error');
@ -197,11 +197,10 @@ class SettingsStripeCard extends React.Component<Props, State> {
});
}, 250);
function setupStripe() {
// TODO: have to fix this, using so that the script is available
setTimeout(function() {
var stripeElements = function(publicKey, setupIntent) {
setTimeout(function () {
var stripeElements = function (publicKey, setupIntent) {
var stripe = Stripe(publicKey);
var elements = stripe.elements();
@ -223,17 +222,17 @@ class SettingsStripeCard extends React.Component<Props, State> {
card.mount('#card-element');
// Element focus ring
card.on('focus', function() {
card.on('focus', function () {
var el = document.getElementById('card-element');
el.classList.add('focused');
});
card.on('blur', function() {
card.on('blur', function () {
var el = document.getElementById('card-element');
el.classList.remove('focused');
});
card.on('ready', function() {
card.on('ready', function () {
card.focus();
});
@ -260,7 +259,7 @@ class SettingsStripeCard extends React.Component<Props, State> {
billing_details: { email: email },
},
})
.then(function(result) {
.then(function (result) {
if (result.error) {
console.log(result);
@ -277,7 +276,7 @@ class SettingsStripeCard extends React.Component<Props, State> {
// Handle payment submission when user clicks the pay button.
var button = document.getElementById('submit');
button.addEventListener('click', function(event) {
button.addEventListener('click', function (event) {
submitForm(event);
});
@ -294,7 +293,7 @@ class SettingsStripeCard extends React.Component<Props, State> {
stripeElements(publicKey, clientSecret);
// Show a spinner on payment submission
var changeLoadingState = function(isLoading) {
var changeLoadingState = function (isLoading) {
if (isLoading) {
// $FlowFixMe
document.querySelector('button').disabled = true;
@ -313,8 +312,8 @@ class SettingsStripeCard extends React.Component<Props, State> {
};
// shows a success / error message when the payment is complete
var orderComplete = function(stripe, clientSecret) {
stripe.retrieveSetupIntent(clientSecret).then(function(result) {
var orderComplete = function (stripe, clientSecret) {
stripe.retrieveSetupIntent(clientSecret).then(function (result) {
Lbryio.call(
'customer',
'status',
@ -323,14 +322,14 @@ class SettingsStripeCard extends React.Component<Props, State> {
},
'post'
).then((customerStatusResponse) => {
var card = customerStatusResponse.PaymentMethods[0].card;
let card = customerStatusResponse.PaymentMethods[0].card;
var customer = customerStatusResponse.Customer;
let customer = customerStatusResponse.Customer;
var topOfDisplay = customer.email.split('@')[0];
var bottomOfDisplay = '@' + customer.email.split('@')[1];
let topOfDisplay = customer.email.split('@')[0];
let bottomOfDisplay = '@' + customer.email.split('@')[1];
var cardDetails = {
let cardDetails = {
brand: card.brand,
expiryYear: card.exp_year,
expiryMonth: card.exp_month,
@ -356,17 +355,16 @@ class SettingsStripeCard extends React.Component<Props, State> {
}
}
render() {
var that = this;
let that = this;
function setAsConfirmingCard(){
function setAsConfirmingCard() {
that.setState({
currentFlowStage: 'confirmingCard',
})
});
}
const { scriptFailedToLoad, doOpenModal, openModal } = this.props;
const { scriptFailedToLoad, openModal } = this.props;
const { currentFlowStage, customerTransactions, pageTitle, userCardDetails, paymentMethodId } = this.state;
@ -429,7 +427,7 @@ class SettingsStripeCard extends React.Component<Props, State> {
setAsConfirmingCard: setAsConfirmingCard,
});
}}
/>
/>
</>
}
/>
@ -442,7 +440,6 @@ class SettingsStripeCard extends React.Component<Props, State> {
subtitle={__('You have not sent any tips yet. When you do they will appear here. ')}
/>
)}
</div>
)}
@ -455,40 +452,43 @@ class SettingsStripeCard extends React.Component<Props, State> {
<div className="table__wrapper">
<table className="table table--transactions">
<thead>
<tr>
<th className="date-header">{__('Date')}</th>
<th>{<>{__('Receiving Channel Name')}</>}</th>
<th>{__('Tip Location')}</th>
<th>{__('Amount (USD)')} </th>
<th>{__('Anonymous')}</th>
</tr>
<tr>
<th className="date-header">{__('Date')}</th>
<th>{<>{__('Receiving Channel Name')}</>}</th>
<th>{__('Tip Location')}</th>
<th>{__('Amount (USD)')} </th>
<th>{__('Anonymous')}</th>
</tr>
</thead>
<tbody>
{customerTransactions &&
customerTransactions.reverse().map((transaction) => (
<tr key={transaction.name + transaction.created_at}>
<td>{moment(transaction.created_at).format('LLL')}</td>
<td>
<Button
className="stripe__card-link-text"
navigate={'/' + transaction.channel_name + ':' + transaction.channel_claim_id}
label={transaction.channel_name}
button="link"
/>
</td>
<td>
<Button
className="stripe__card-link-text"
navigate={'/' + transaction.channel_name + ':' + transaction.source_claim_id}
label={transaction.channel_claim_id === transaction.source_claim_id ? 'Channel Page' : 'File Page'}
button="link"
/>
</td>
<td>${transaction.tipped_amount / 100}</td>
<td>{transaction.private_tip ? 'Yes' : 'No'}</td>
</tr>
))}
{customerTransactions &&
customerTransactions.reverse().map((transaction) => (
<tr key={transaction.name + transaction.created_at}>
<td>{moment(transaction.created_at).format('LLL')}</td>
<td>
<Button
className="stripe__card-link-text"
navigate={'/' + transaction.channel_name + ':' + transaction.channel_claim_id}
label={transaction.channel_name}
button="link"
/>
</td>
<td>
<Button
className="stripe__card-link-text"
navigate={'/' + transaction.channel_name + ':' + transaction.source_claim_id}
label={
transaction.channel_claim_id === transaction.source_claim_id
? 'Channel Page'
: 'File Page'
}
button="link"
/>
</td>
<td>${transaction.tipped_amount / 100}</td>
<td>{transaction.private_tip ? 'Yes' : 'No'}</td>
</tr>
))}
</tbody>
</table>
</div>
@ -496,7 +496,6 @@ class SettingsStripeCard extends React.Component<Props, State> {
}
/>
)}
</Page>
);
}