Custom reward codes #374
7 changed files with 125 additions and 3 deletions
26
app/src/component/customRewardCard/index.js
Normal file
26
app/src/component/customRewardCard/index.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doToast } from 'lbry-redux';
|
||||
import {
|
||||
doClaimRewardType,
|
||||
doClaimRewardClearError,
|
||||
makeSelectClaimRewardError,
|
||||
makeSelectIsRewardClaimPending,
|
||||
rewards as REWARD_TYPES
|
||||
} from 'lbryinc';
|
||||
import CustomRewardCard from './view';
|
||||
|
||||
const select = state => ({
|
||||
rewardIsPending: makeSelectIsRewardClaimPending()(state, {
|
||||
reward_type: REWARD_TYPES.TYPE_REWARD_CODE,
|
||||
}),
|
||||
error: makeSelectClaimRewardError()(state, { reward_type: REWARD_TYPES.TYPE_REWARD_CODE }),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
claimReward: reward => dispatch(doClaimRewardType(reward.reward_type, true)),
|
||||
clearError: reward => dispatch(doClaimRewardClearError(reward)),
|
||||
notify: data => dispatch(doToast(data)),
|
||||
submitRewardCode: code => dispatch(doClaimRewardType(REWARD_TYPES.TYPE_REWARD_CODE, { params: { code } }))
|
||||
});
|
||||
|
||||
export default connect(select, perform)(CustomRewardCard);
|
83
app/src/component/customRewardCard/view.js
Normal file
83
app/src/component/customRewardCard/view.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
||||
import Colors from '../../styles/colors';
|
||||
I'll look into this. I'll look into this.
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import Button from '../button';
|
||||
import Link from '../link';
|
||||
import rewardStyle from '../../styles/reward';
|
||||
|
||||
class CustomRewardCard extends React.PureComponent<Props> {
|
||||
state = {
|
||||
claimStarted: false,
|
||||
rewardCode: ''
|
||||
};
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { error, rewardIsPending } = nextProps;
|
||||
const { clearError, notify } = this.props;
|
||||
if (this.state.claimStarted && !rewardIsPending) {
|
||||
if (error && error.trim().length > 0) {
|
||||
We get whitespace errors? We get whitespace errors?
This seems like something that should be cleaned up at the source
|
||||
notify({ message: error });
|
||||
} else {
|
||||
notify({ message: 'Reward successfully claimed!' });
|
||||
this.setState({ rewardCode: '' });
|
||||
}
|
||||
this.setState({ claimStarted: false });
|
||||
}
|
||||
}
|
||||
|
||||
onClaimPress = () => {
|
||||
const { canClaim, notify, submitRewardCode } = this.props;
|
||||
const { rewardCode } = this.state;
|
||||
|
||||
if (!canClaim) {
|
||||
notify({ message: 'Unfortunately, you are not eligible to claim this reward at this time.' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rewardCode || rewardCode.trim().length === 0) {
|
||||
notify({ message: 'Please enter a reward code to claim.' });
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ claimStarted: true }, () => {
|
||||
submitRewardCode(rewardCode);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { canClaim, rewardIsPending } = this.props;
|
||||
|
||||
return (
|
||||
<View style={[rewardStyle.rewardCard, rewardStyle.row]} >
|
||||
<View style={rewardStyle.leftCol}>
|
||||
{rewardIsPending && <ActivityIndicator size="small" color={Colors.LbryGreen} />}
|
||||
</View>
|
||||
<View style={rewardStyle.midCol}>
|
||||
<Text style={rewardStyle.rewardTitle}>Custom Code</Text>
|
||||
<Text style={rewardStyle.rewardDescription}>Are you a supermodel or rockstar that received a custom reward code? Claim it here.</Text>
|
||||
|
||||
<View>
|
||||
<TextInput style={rewardStyle.customCodeInput}
|
||||
placeholder={"0123abc"}
|
||||
onChangeText={text => this.setState({ rewardCode: text })}
|
||||
value={this.state.rewardCode} />
|
||||
<Button style={rewardStyle.redeemButton}
|
||||
text={"Redeem"}
|
||||
disabled={(!this.state.rewardCode || this.state.rewardCode.trim().length === 0 || rewardIsPending)}
|
||||
onPress={() => {
|
||||
if (!rewardIsPending) { this.onClaimPress(); }
|
||||
}} />
|
||||
</View>
|
||||
</View>
|
||||
<View style={rewardStyle.rightCol}>
|
||||
<Text style={rewardStyle.rewardAmount}>?</Text>
|
||||
<Text style={rewardStyle.rewardCurrency}>LBC</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default CustomRewardCard;
|
|
@ -9,6 +9,7 @@ import {
|
|||
} from 'react-native';
|
||||
import Colors from '../../styles/colors';
|
||||
import Link from '../../component/link';
|
||||
import CustomRewardCard from '../../component/customRewardCard';
|
||||
import PhoneNumberRewardSubcard from '../../component/phoneNumberRewardSubcard';
|
||||
import EmailRewardSubcard from '../../component/emailRewardSubcard';
|
||||
import PageHeader from '../../component/pageHeader';
|
||||
|
@ -122,6 +123,7 @@ class RewardsPage extends React.PureComponent {
|
|||
canClaim={!isNotEligible}
|
||||
reward={reward}
|
||||
reward_type={reward.reward_type} />)}
|
||||
<CustomRewardCard canClaim={!isNotEligible} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -202,6 +202,17 @@ const rewardStyle = StyleSheet.create({
|
|||
paddingLeft: 4,
|
||||
paddingRight: 4,
|
||||
flex: 0.2
|
||||
},
|
||||
customCodeInput: {
|
||||
fontFamily: 'Metropolis-Regular',
|
||||
fontSize: 16,
|
||||
letterSpacing: 1.3,
|
||||
marginTop: -8,
|
||||
marginBottom: 4
|
||||
},
|
||||
redeemButton: {
|
||||
alignSelf: 'flex-end',
|
||||
backgroundColor: Colors.LbryGreen
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ version.filename = %(source.dir)s/main.py
|
|||
|
||||
# (list) Application requirements
|
||||
# comma seperated e.g. requirements = sqlite3,kivy
|
||||
requirements = python3crystax, openssl, sqlite3, hostpython3crystax, android, distro, pyjnius, certifi==2018.4.16, constantly, incremental, miniupnpc==1.9, gmpy, appdirs==1.4.3, argparse==1.2.1, docopt, base58==1.0.0, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2, pyyaml, qrcode==5.2.2, requests, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, txJSON-RPC, zope.interface==4.3.3, protobuf==3.6.1, keyring==10.4.0, txupnp, git+https://github.com/lbryio/lbryschema.git#egg=lbryschema, git+https://github.com/lbryio/lbry.git#egg=lbrynet, git+https://github.com/lbryio/aioupnp.git#egg=aioupnp, asn1crypto, treq==17.8.0, funcsigs, mock, pbr, pyopenssl, twisted, idna, Automat, hyperlink, PyHamcrest, netifaces, cryptography, aiohttp, aiorpcX==0.9.0, asyncio, git+https://github.com/lbryio/torba@997b573aa4223ec6c8c01948cd2df0c6475b5f42#egg=torba, coincurve
|
||||
requirements = python3crystax, openssl, sqlite3, hostpython3crystax, android, distro, pyjnius, certifi==2018.4.16, constantly, incremental, miniupnpc==1.9, gmpy, appdirs==1.4.3, argparse==1.2.1, docopt, base58==1.0.0, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2, pyyaml, qrcode==5.2.2, requests, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, txJSON-RPC, zope.interface==4.3.3, protobuf==3.6.1, keyring==10.4.0, txupnp, git+https://github.com/lbryio/lbryschema.git#egg=lbryschema, git+https://github.com/lbryio/lbry.git#egg=lbrynet, git+https://github.com/lbryio/aioupnp.git#egg=aioupnp, asn1crypto, treq==17.8.0, funcsigs, mock, pbr, pyopenssl, twisted, idna, Automat, hyperlink, PyHamcrest, netifaces, cryptography, aiohttp, aiorpcX==0.9.0, asyncio, git+https://github.com/lbryio/torba@python36-current-task#egg=torba, coincurve
|
||||
|
||||
# (str) Custom source folders for requirements
|
||||
# Sets custom source for any requirements with recipes
|
||||
|
|
|
@ -36,7 +36,7 @@ version.filename = %(source.dir)s/main.py
|
|||
|
||||
# (list) Application requirements
|
||||
# comma seperated e.g. requirements = sqlite3,kivy
|
||||
requirements = python3crystax, openssl, sqlite3, hostpython3crystax, android, distro, pyjnius, certifi==2018.4.16, constantly, incremental, miniupnpc==1.9, gmpy, appdirs==1.4.3, argparse==1.2.1, docopt, base58==1.0.0, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2, pyyaml, qrcode==5.2.2, requests, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, txJSON-RPC, zope.interface==4.3.3, protobuf==3.6.1, keyring==10.4.0, txupnp, git+https://github.com/lbryio/lbryschema.git#egg=lbryschema, git+https://github.com/lbryio/lbry.git#egg=lbrynet, git+https://github.com/lbryio/aioupnp.git#egg=aioupnp, asn1crypto, treq==17.8.0, funcsigs, mock, pbr, pyopenssl, twisted, idna, Automat, hyperlink, PyHamcrest, netifaces, cryptography, aiohttp, aiorpcX==0.9.0, asyncio, git+https://github.com/lbryio/torba@997b573aa4223ec6c8c01948cd2df0c6475b5f42#egg=torba, coincurve
|
||||
requirements = python3crystax, openssl, sqlite3, hostpython3crystax, android, distro, pyjnius, certifi==2018.4.16, constantly, incremental, miniupnpc==1.9, gmpy, appdirs==1.4.3, argparse==1.2.1, docopt, base58==1.0.0, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2, pyyaml, qrcode==5.2.2, requests, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, txJSON-RPC, zope.interface==4.3.3, protobuf==3.6.1, keyring==10.4.0, txupnp, git+https://github.com/lbryio/lbryschema.git#egg=lbryschema, git+https://github.com/lbryio/lbry.git#egg=lbrynet, git+https://github.com/lbryio/aioupnp.git#egg=aioupnp, asn1crypto, treq==17.8.0, funcsigs, mock, pbr, pyopenssl, twisted, idna, Automat, hyperlink, PyHamcrest, netifaces, cryptography, aiohttp, aiorpcX==0.9.0, asyncio, git+https://github.com/lbryio/torba@python36-current-task#egg=torba, coincurve
|
||||
|
||||
# (str) Custom source folders for requirements
|
||||
# Sets custom source for any requirements with recipes
|
||||
|
|
|
@ -36,7 +36,7 @@ version.filename = %(source.dir)s/main.py
|
|||
|
||||
# (list) Application requirements
|
||||
# comma seperated e.g. requirements = sqlite3,kivy
|
||||
requirements = python3crystax, openssl, sqlite3, hostpython3crystax, android, distro, pyjnius, certifi==2018.4.16, constantly, incremental, miniupnpc==1.9, gmpy, appdirs==1.4.3, argparse==1.2.1, docopt, base58==1.0.0, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2, pyyaml, qrcode==5.2.2, requests, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, txJSON-RPC, zope.interface==4.3.3, protobuf==3.6.1, keyring==10.4.0, txupnp, git+https://github.com/lbryio/lbryschema.git#egg=lbryschema, git+https://github.com/lbryio/lbry.git#egg=lbrynet, git+https://github.com/lbryio/aioupnp.git#egg=aioupnp, asn1crypto, treq==17.8.0, funcsigs, mock, pbr, pyopenssl, twisted, idna, Automat, hyperlink, PyHamcrest, netifaces, cryptography, aiohttp, aiorpcX==0.9.0, asyncio, git+https://github.com/lbryio/torba@997b573aa4223ec6c8c01948cd2df0c6475b5f42#egg=torba, coincurve
|
||||
requirements = python3crystax, openssl, sqlite3, hostpython3crystax, android, distro, pyjnius, certifi==2018.4.16, constantly, incremental, miniupnpc==1.9, gmpy, appdirs==1.4.3, argparse==1.2.1, docopt, base58==1.0.0, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2, pyyaml, qrcode==5.2.2, requests, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, txJSON-RPC, zope.interface==4.3.3, protobuf==3.6.1, keyring==10.4.0, txupnp, git+https://github.com/lbryio/lbryschema.git#egg=lbryschema, git+https://github.com/lbryio/lbry.git#egg=lbrynet, git+https://github.com/lbryio/aioupnp.git#egg=aioupnp, asn1crypto, treq==17.8.0, funcsigs, mock, pbr, pyopenssl, twisted, idna, Automat, hyperlink, PyHamcrest, netifaces, cryptography, aiohttp, aiorpcX==0.9.0, asyncio, git+https://github.com/lbryio/torba@python36-current-task#egg=torba, coincurve
|
||||
|
||||
# (str) Custom source folders for requirements
|
||||
# Sets custom source for any requirements with recipes
|
||||
|
|
Loading…
Reference in a new issue
Have you looked at using aliases for these through babel?
This would be ideal since we can use it across all apps:
https://www.npmjs.com/package/babel-plugin-webpack-aliases
And here's an alternative that isn't opinionated towards how Webpack does things:
https://www.npmjs.com/package/babel-plugin-module-resolver