Add promo fetch and associated logic
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { Button, Col, Panel, Row, Well } from 'react-bootstrap';
|
||||
import { Button, Input, Col, Panel, Row, Well } from 'react-bootstrap';
|
||||
import { contain } from 'thundercats-react';
|
||||
|
||||
const paypalIds = {
|
||||
@ -12,14 +12,26 @@ const paypalIds = {
|
||||
export default contain(
|
||||
{
|
||||
store: 'JobsStore',
|
||||
actions: 'JobActions',
|
||||
actions: 'jobActions',
|
||||
map({
|
||||
job: { id, isHighlighted } = {},
|
||||
buttonId = paypalIds.regular,
|
||||
price = 200,
|
||||
discountAmount = 0
|
||||
discountAmount = 0,
|
||||
promoCode = '',
|
||||
promoApplied = false,
|
||||
promoName
|
||||
}) {
|
||||
return { id, isHighlighted, buttonId, price, discountAmount };
|
||||
return {
|
||||
id,
|
||||
isHighlighted,
|
||||
buttonId,
|
||||
price,
|
||||
discountAmount,
|
||||
promoName,
|
||||
promoCode,
|
||||
promoApplied
|
||||
};
|
||||
}
|
||||
},
|
||||
React.createClass({
|
||||
@ -30,7 +42,11 @@ export default contain(
|
||||
isHighlighted: PropTypes.bool,
|
||||
buttonId: PropTypes.string,
|
||||
price: PropTypes.number,
|
||||
discountAmount: PropTypes.number
|
||||
discountAmount: PropTypes.number,
|
||||
promoName: PropTypes.string,
|
||||
promoCode: PropTypes.string,
|
||||
promoApplied: PropTypes.bool,
|
||||
jobActions: PropTypes.object
|
||||
},
|
||||
|
||||
renderDiscount(discountAmount) {
|
||||
@ -42,7 +58,7 @@ export default contain(
|
||||
<Col
|
||||
md={ 3 }
|
||||
mdOffset={ 3 }>
|
||||
<h4>Discount</h4>
|
||||
<h4>Promo Discount</h4>
|
||||
</Col>
|
||||
<Col
|
||||
md={ 3 }>
|
||||
@ -71,8 +87,75 @@ export default contain(
|
||||
);
|
||||
},
|
||||
|
||||
renderPromo() {
|
||||
const {
|
||||
promoApplied,
|
||||
promoCode,
|
||||
promoName,
|
||||
isHighlighted,
|
||||
jobActions
|
||||
} = this.props;
|
||||
if (promoApplied) {
|
||||
return (
|
||||
<div>
|
||||
<div className='spacer' />
|
||||
<Row>
|
||||
<Col
|
||||
md={ 3 }
|
||||
mdOffset={ 3 }>
|
||||
{ promoName } applied
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className='spacer' />
|
||||
<Row>
|
||||
<Col
|
||||
md={ 3 }
|
||||
mdOffset={ 3 }>
|
||||
Have a promo code?
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col
|
||||
md={ 3 }
|
||||
mdOffset={ 3 }>
|
||||
<Input
|
||||
onChange={ jobActions.setPromoCode }
|
||||
type='text'
|
||||
value={ promoCode } />
|
||||
</Col>
|
||||
<Col
|
||||
md={ 3 }>
|
||||
<Button
|
||||
block={ true }
|
||||
bsSize='large'
|
||||
onClick={ () => {
|
||||
jobActions.applyCode({
|
||||
code: promoCode,
|
||||
type: isHighlighted ? 'isHighlighted' : null
|
||||
});
|
||||
}}>
|
||||
Find Promo
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
render() {
|
||||
const { id, isHighlighted, buttonId, price, discountAmount } = this.props;
|
||||
const {
|
||||
id,
|
||||
isHighlighted,
|
||||
buttonId,
|
||||
price,
|
||||
discountAmount
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Row>
|
||||
@ -124,6 +207,7 @@ export default contain(
|
||||
</Col>
|
||||
</Row>
|
||||
</Well>
|
||||
{ this.renderPromo() }
|
||||
<div className='spacer' />
|
||||
<Row>
|
||||
<Col
|
||||
|
@ -2,6 +2,7 @@ import { Actions } from 'thundercats';
|
||||
import store from 'store';
|
||||
import debugFactory from 'debug';
|
||||
import { jsonp$ } from '../../../../utils/jsonp$';
|
||||
import { postJSON$ } from '../../../../utils/ajax-stream';
|
||||
|
||||
const debug = debugFactory('freecc:jobs:actions');
|
||||
const assign = Object.assign;
|
||||
@ -65,6 +66,26 @@ export default Actions({
|
||||
getFollowers: null,
|
||||
setFollowersCount(numOfFollowers) {
|
||||
return { numOfFollowers };
|
||||
},
|
||||
setPromoCode({ target: { value = '' }} = {}) {
|
||||
return { promoCode: value.replace(/[^\d\w\s]/, '') };
|
||||
},
|
||||
applyCode: null,
|
||||
applyPromo({
|
||||
fullPrice: price,
|
||||
buttonId,
|
||||
discountAmount,
|
||||
code: promoCode,
|
||||
name: promoName
|
||||
} = {}) {
|
||||
return {
|
||||
price,
|
||||
buttonId,
|
||||
discountAmount,
|
||||
promoCode,
|
||||
promoApplied: true,
|
||||
promoName
|
||||
};
|
||||
}
|
||||
})
|
||||
.refs({ displayName: 'JobActions' })
|
||||
@ -139,5 +160,23 @@ export default Actions({
|
||||
);
|
||||
});
|
||||
|
||||
jobActions.applyCode.subscribe(({ code = '', type = null}) => {
|
||||
const body = { code: code.replace(/[^\d\w\s]/, '') };
|
||||
if (type) {
|
||||
body.type = type;
|
||||
}
|
||||
postJSON$('/api/promos/getButton', body)
|
||||
.pluck('response')
|
||||
.subscribe(
|
||||
({ promo }) => {
|
||||
if (promo && promo.buttonId) {
|
||||
jobActions.applyPromo(promo);
|
||||
}
|
||||
jobActions.setError(new Error('no promo found'));
|
||||
},
|
||||
jobActions.setError
|
||||
);
|
||||
});
|
||||
|
||||
return jobActions;
|
||||
});
|
||||
|
@ -20,7 +20,9 @@ export default Store({
|
||||
closeModal,
|
||||
handleForm,
|
||||
setForm,
|
||||
setFollowersCount
|
||||
setFollowersCount,
|
||||
setPromoCode,
|
||||
applyPromo
|
||||
} = cat.getActions('JobActions');
|
||||
const register = createRegistrar(jobsStore);
|
||||
register(setter(setJobs));
|
||||
@ -28,6 +30,8 @@ export default Store({
|
||||
register(setter(openModal));
|
||||
register(setter(closeModal));
|
||||
register(setter(setForm));
|
||||
register(setter(setPromoCode));
|
||||
register(setter(applyPromo));
|
||||
register(setter(setFollowersCount));
|
||||
|
||||
register(transformer(findJob));
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { isAlphanumeric } from 'validator';
|
||||
|
||||
export default function promo(Promo) {
|
||||
Promo.getButton = function getButton(code, type = null) {
|
||||
|
||||
Promo.getButton = function getButton(code, type = 'isNot') {
|
||||
if (
|
||||
!isAlphanumeric(code) &&
|
||||
type &&
|
||||
@ -15,8 +14,7 @@ export default function promo(Promo) {
|
||||
|
||||
const query = {
|
||||
where: {
|
||||
code,
|
||||
type
|
||||
and: [{ code }, { type }]
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -255,6 +255,7 @@ export function postJSON$(url, body) {
|
||||
url,
|
||||
body: JSON.stringify(body),
|
||||
method: 'POST',
|
||||
responseType: 'json',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
@ -277,9 +278,6 @@ export function get$(url) {
|
||||
* @returns {Observable} The observable sequence which contains the parsed JSON
|
||||
*/
|
||||
export function getJSON$(url) {
|
||||
if (!root.JSON && typeof root.JSON.parse !== 'function') {
|
||||
throw new TypeError('JSON is not supported in your runtime.');
|
||||
}
|
||||
return ajax$({ url: url, responseType: 'json' }).map(function(x) {
|
||||
return x.response;
|
||||
});
|
||||
|
Reference in New Issue
Block a user