Compare commits
4 commits
master
...
fiat-tip-i
Author | SHA1 | Date | |
---|---|---|---|
|
aba8b64dbe | ||
|
7b0cde601f | ||
|
a07146ffc1 | ||
|
7a81c8b404 |
2 changed files with 63 additions and 21 deletions
|
@ -22,6 +22,8 @@ const DEFAULT_TIP_AMOUNTS = [1, 5, 25, 100];
|
||||||
const MINIMUM_FIAT_TIP = 1;
|
const MINIMUM_FIAT_TIP = 1;
|
||||||
const MAXIMUM_FIAT_TIP = 1000;
|
const MAXIMUM_FIAT_TIP = 1000;
|
||||||
|
|
||||||
|
const DEFAULT_TIP_ERROR = __('Sorry, there was an error in processing your payment!');
|
||||||
|
|
||||||
const TAB_BOOST = 'TabBoost';
|
const TAB_BOOST = 'TabBoost';
|
||||||
const TAB_FIAT = 'TabFiat';
|
const TAB_FIAT = 'TabFiat';
|
||||||
const TAB_LBC = 'TabLBC';
|
const TAB_LBC = 'TabLBC';
|
||||||
|
@ -64,20 +66,48 @@ function WalletSendTip(props: Props) {
|
||||||
doToast,
|
doToast,
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
/** REACT STATE **/
|
||||||
const [presetTipAmount, setPresetTipAmount] = usePersistedState('comment-support:presetTip', DEFAULT_TIP_AMOUNTS[0]);
|
const [presetTipAmount, setPresetTipAmount] = usePersistedState('comment-support:presetTip', DEFAULT_TIP_AMOUNTS[0]);
|
||||||
const [customTipAmount, setCustomTipAmount] = usePersistedState('comment-support:customTip', 1.0);
|
const [customTipAmount, setCustomTipAmount] = usePersistedState('comment-support:customTip', 1.0);
|
||||||
const [useCustomTip, setUseCustomTip] = usePersistedState('comment-support:useCustomTip', false);
|
const [useCustomTip, setUseCustomTip] = usePersistedState('comment-support:useCustomTip', false);
|
||||||
const [tipError, setTipError] = React.useState();
|
|
||||||
const [isConfirming, setIsConfirming] = React.useState(false);
|
const [isConfirming, setIsConfirming] = React.useState(false);
|
||||||
|
|
||||||
|
// only allow certain creators to receive tips
|
||||||
|
const [canReceiveFiatTip, setCanReceiveFiatTip] = React.useState(); // dont persist because it needs to be calc'd per creator
|
||||||
|
|
||||||
|
// show things conditionally based on if a user has a card already
|
||||||
|
const [hasCardSaved, setHasSavedCard] = usePersistedState('comment-support:hasCardSaved', false);
|
||||||
|
|
||||||
|
// show the tip error on the frontend
|
||||||
|
const [tipError, setTipError] = React.useState();
|
||||||
|
|
||||||
|
// denote which tab to show on the frontend
|
||||||
|
const [activeTab, setActiveTab] = usePersistedState(TAB_LBC);
|
||||||
|
|
||||||
|
// handle default active tab
|
||||||
|
React.useEffect(() => {
|
||||||
|
// force to boost tab if it's someone's own upload
|
||||||
|
if (claimIsMine) {
|
||||||
|
setActiveTab(TAB_BOOST);
|
||||||
|
} else {
|
||||||
|
// or set LBC tip as the default if none is set yet
|
||||||
|
if (!activeTab || activeTab === 'undefined') {
|
||||||
|
setActiveTab(TAB_LBC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// alphanumeric claim id
|
||||||
const { claim_id: claimId } = claim;
|
const { claim_id: claimId } = claim;
|
||||||
|
|
||||||
|
// channel name used in url
|
||||||
const { channelName } = parseURI(uri);
|
const { channelName } = parseURI(uri);
|
||||||
|
|
||||||
const activeChannelName = activeChannelClaim && activeChannelClaim.name;
|
const activeChannelName = activeChannelClaim && activeChannelClaim.name;
|
||||||
const activeChannelId = activeChannelClaim && activeChannelClaim.claim_id;
|
const activeChannelId = activeChannelClaim && activeChannelClaim.claim_id;
|
||||||
|
|
||||||
const [canReceiveFiatTip, setCanReceiveFiatTip] = React.useState(); // dont persist because it needs to be calc'd per creator
|
// setup variables for backend tip API
|
||||||
const [hasCardSaved, setHasSavedCard] = usePersistedState('comment-support:hasCardSaved', false);
|
|
||||||
|
|
||||||
// setup variables for tip API
|
|
||||||
let channelClaimId, tipChannelName;
|
let channelClaimId, tipChannelName;
|
||||||
// if there is a signing channel it's on a file
|
// if there is a signing channel it's on a file
|
||||||
if (claim.signing_channel) {
|
if (claim.signing_channel) {
|
||||||
|
@ -114,7 +144,7 @@ function WalletSendTip(props: Props) {
|
||||||
}
|
}
|
||||||
}, [channelClaimId, isAuthenticated, stripeEnvironment]);
|
}, [channelClaimId, isAuthenticated, stripeEnvironment]);
|
||||||
|
|
||||||
// check if creator has an account saved
|
// focus tip element if it exists
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const tipInputElement = document.getElementById('tip-input');
|
const tipInputElement = document.getElementById('tip-input');
|
||||||
if (tipInputElement) {
|
if (tipInputElement) {
|
||||||
|
@ -122,6 +152,7 @@ function WalletSendTip(props: Props) {
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// check if user can receive tips
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (channelClaimId && stripeEnvironment) {
|
if (channelClaimId && stripeEnvironment) {
|
||||||
Lbryio.call(
|
Lbryio.call(
|
||||||
|
@ -147,11 +178,13 @@ function WalletSendTip(props: Props) {
|
||||||
}
|
}
|
||||||
}, [channelClaimId, stripeEnvironment]);
|
}, [channelClaimId, stripeEnvironment]);
|
||||||
|
|
||||||
|
// if user has no balance, used to show conditional frontend
|
||||||
const noBalance = balance === 0;
|
const noBalance = balance === 0;
|
||||||
|
|
||||||
|
// the tip amount, based on if a preset or custom tip amount is being used
|
||||||
const tipAmount = useCustomTip ? customTipAmount : presetTipAmount;
|
const tipAmount = useCustomTip ? customTipAmount : presetTipAmount;
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = React.useState(TAB_BOOST);
|
// get type of claim (stream/channel/repost/collection) for display on frontend
|
||||||
|
|
||||||
function getClaimTypeText() {
|
function getClaimTypeText() {
|
||||||
if (claim.value_type === 'stream') {
|
if (claim.value_type === 'stream') {
|
||||||
return __('Content');
|
return __('Content');
|
||||||
|
@ -167,6 +200,7 @@ function WalletSendTip(props: Props) {
|
||||||
}
|
}
|
||||||
const claimTypeText = getClaimTypeText();
|
const claimTypeText = getClaimTypeText();
|
||||||
|
|
||||||
|
// icon to use or explainer text to show per tab
|
||||||
let iconToUse;
|
let iconToUse;
|
||||||
let explainerText = '';
|
let explainerText = '';
|
||||||
if (activeTab === TAB_BOOST) {
|
if (activeTab === TAB_BOOST) {
|
||||||
|
@ -231,7 +265,7 @@ function WalletSendTip(props: Props) {
|
||||||
setTipError(tipError);
|
setTipError(tipError);
|
||||||
}, [tipAmount, balance, setTipError, activeTab]);
|
}, [tipAmount, balance, setTipError, activeTab]);
|
||||||
|
|
||||||
//
|
// make call to the backend to send lbc or fiat
|
||||||
function sendSupportOrConfirm(instantTipMaxAmount = null) {
|
function sendSupportOrConfirm(instantTipMaxAmount = null) {
|
||||||
// send a tip
|
// send a tip
|
||||||
if (!isConfirming && (!instantTipMaxAmount || !instantTipEnabled || tipAmount > instantTipMaxAmount)) {
|
if (!isConfirming && (!instantTipMaxAmount || !instantTipEnabled || tipAmount > instantTipMaxAmount)) {
|
||||||
|
@ -271,6 +305,7 @@ function WalletSendTip(props: Props) {
|
||||||
} else if (isConfirming) {
|
} else if (isConfirming) {
|
||||||
let sendAnonymously = !activeChannelClaim || incognito;
|
let sendAnonymously = !activeChannelClaim || incognito;
|
||||||
|
|
||||||
|
// hit backend to send tip
|
||||||
Lbryio.call(
|
Lbryio.call(
|
||||||
'customer',
|
'customer',
|
||||||
'tip',
|
'tip',
|
||||||
|
@ -297,10 +332,12 @@ function WalletSendTip(props: Props) {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
let displayError = 'Sorry, there was an error in processing your payment!';
|
// show error message from Stripe if one exists (being passed from backend by Beamer's API currently)
|
||||||
|
let displayError;
|
||||||
if (error.message !== 'payment intent failed to confirm') {
|
if (error.message) {
|
||||||
displayError = error.message;
|
displayError = error.message;
|
||||||
|
} else {
|
||||||
|
displayError = DEFAULT_TIP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
doToast({ message: displayError, isError: true });
|
doToast({ message: displayError, isError: true });
|
||||||
|
@ -385,6 +422,7 @@ function WalletSendTip(props: Props) {
|
||||||
// if it's a valid number display it, otherwise do an empty string
|
// if it's a valid number display it, otherwise do an empty string
|
||||||
const displayAmount = !isNan(tipAmount) ? amountToShow : '';
|
const displayAmount = !isNan(tipAmount) ? amountToShow : '';
|
||||||
|
|
||||||
|
// build button text based on tab
|
||||||
if (activeTab === TAB_BOOST) {
|
if (activeTab === TAB_BOOST) {
|
||||||
return claimIsMine
|
return claimIsMine
|
||||||
? __('Boost Your %claimTypeText%', { claimTypeText })
|
? __('Boost Your %claimTypeText%', { claimTypeText })
|
||||||
|
@ -396,12 +434,14 @@ function WalletSendTip(props: Props) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dont allow user to click send button
|
||||||
function shouldDisableAmountSelector(amount) {
|
function shouldDisableAmountSelector(amount) {
|
||||||
return (
|
return (
|
||||||
(amount > balance && activeTab !== TAB_FIAT) || (activeTab === TAB_FIAT && (!hasCardSaved || !canReceiveFiatTip))
|
(amount > balance && activeTab !== TAB_FIAT) || (activeTab === TAB_FIAT && (!hasCardSaved || !canReceiveFiatTip))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// showed on confirm page above amount
|
||||||
function setConfirmLabel() {
|
function setConfirmLabel() {
|
||||||
if (activeTab === TAB_LBC) {
|
if (activeTab === TAB_LBC) {
|
||||||
return __('Tipping Credit');
|
return __('Tipping Credit');
|
||||||
|
@ -530,6 +570,7 @@ function WalletSendTip(props: Props) {
|
||||||
<ChannelSelector />
|
<ChannelSelector />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* prompt to save a card */}
|
||||||
{activeTab === TAB_FIAT && !hasCardSaved && (
|
{activeTab === TAB_FIAT && !hasCardSaved && (
|
||||||
<h3 className="add-card-prompt">
|
<h3 className="add-card-prompt">
|
||||||
<Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card')} button="link" />{' '}
|
<Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card')} button="link" />{' '}
|
||||||
|
|
|
@ -361,12 +361,14 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
||||||
className="card-stack"
|
className="card-stack"
|
||||||
backout={{ title: __(pageTitle), backLabel: __('Back') }}
|
backout={{ title: __(pageTitle), backLabel: __('Back') }}
|
||||||
>
|
>
|
||||||
|
{/* if Stripe javascript didn't load */}
|
||||||
<div>
|
<div>
|
||||||
{scriptFailedToLoad && (
|
{scriptFailedToLoad && (
|
||||||
<div className="error__text">{__('There was an error connecting to Stripe. Please try again later.')}</div>
|
<div className="error__text">{__('There was an error connecting to Stripe. Please try again later.')}</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* initial markup to show while getting information */}
|
||||||
{currentFlowStage === 'loading' && (
|
{currentFlowStage === 'loading' && (
|
||||||
<div className="headerCard toConfirmCard">
|
<div className="headerCard toConfirmCard">
|
||||||
<Card title={__('Connect your card with Odysee')} subtitle={__('Getting your card connection status...')} />
|
<Card title={__('Connect your card with Odysee')} subtitle={__('Getting your card connection status...')} />
|
||||||
|
@ -407,7 +409,7 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<Button
|
<Button
|
||||||
button="secondary"
|
button="primary"
|
||||||
label={__('Remove Card')}
|
label={__('Remove Card')}
|
||||||
icon={ICONS.DELETE}
|
icon={ICONS.DELETE}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
@ -419,15 +421,14 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
|
||||||
}
|
|
||||||
actions={
|
|
||||||
<Button
|
<Button
|
||||||
button="primary"
|
button="secondary"
|
||||||
label={__('View Transactions')}
|
label={__('View Transactions')}
|
||||||
icon={ICONS.SETTINGS}
|
icon={ICONS.SETTINGS}
|
||||||
navigate={`/$/${PAGES.WALLET}?fiatType=outgoing&tab=fiat-payment-history¤cy=fiat`}
|
navigate={`/$/${PAGES.WALLET}?fiatType=outgoing&tab=fiat-payment-history¤cy=fiat`}
|
||||||
|
style={{marginLeft: '10px'}}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
|
|
Loading…
Reference in a new issue