I am creating a platform, where friends can buy friends Starbucks.
Users create a request & other users can fulfill these requests by paying $5, then the requesting user receives a Starbucks gift card of $5.
Right now the only requirement to fulfill a request is the message text form (submitting without will throw an error) & I need to add the requirement of completing the Stripe payment before submitting the fulfill request form.
Ideally, I would like the fulfill the request button to be disabled until the Stripe payment is complete.
Fulfill Request form:
import { connect } from 'react-redux';
import { fulfillRequest, clearErrors } from 'redux/actions/dataActions';
import { Elements } from 'react-stripe-elements';
import CheckoutForm from '../FulfillRequest/Stripe/CheckoutForm';
class FulfillRequest extends Component {
state = {
open: false,
body: '',
errors: {}
};
componentWillReceiveProps(nextProps) {
if (nextProps.UI.errors) {
this.setState({
errors: nextProps.UI.errors
});
}
if (!nextProps.UI.errors && !nextProps.UI.loading) {
this.setState({ body: '', open: false, errors: {} });
}
}
handleOpen = () => {
this.setState({ open: true });
};
handleClose = () => {
this.props.clearErrors();
this.setState({ open: false, errors: {} });
};
handleChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
handleSubmit = event => {
event.preventDefault();
this.props.fulfillRequest(this.props.requestId, { body: this.state.body });
};
render() {
const {
classes,
UI: { loading }
} = this.props;
const { errors } = this.state;
return (
<Fragment>
<IconButton onClick={this.handleOpen} color="inherit">
<TagFaces />
</IconButton>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby="form-dialog-title"
fullWidth
maxWidth="sm">
<DialogTitle id="form-dialog-title">Fulfill request</DialogTitle>
<DialogContent>
<Elements>
<CheckoutForm />
</Elements>
<Grid
container
spacing={0}
direction="column"
alignItems="center"
justify="center">
{errors.error && (
<FormHelperText error className={classes.customError}>
{errors.error}
</FormHelperText>
)}
</Grid>
<form onSubmit={this.handleSubmit}>
<TextField
autoFocus
margin="dense"
multiline
placeholder="say something"
id="name"
name="body"
label="say something"
type="text"
fullWidth
error={errors.body ? true : false}
helperText={errors.body}
onChange={this.handleChange}
/>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
Cancel
</Button>
<Button type="submit" color="primary" disabled={loading}>
Fulfill Request
{loading && <CircularProgress />}
</Button>
</DialogActions>
</form>
</DialogContent>
</Dialog>
</Fragment>
);
}
}
FulfillRequest.propTypes = {
fulfillRequest: PropTypes.func.isRequired,
classes: PropTypes.object.isRequired,
requestId: PropTypes.string.isRequired,
clearErrors: PropTypes.func.isRequired,
UI: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
UI: state.UI
});
export default connect(
mapStateToProps,
{ fulfillRequest, clearErrors }
)(withStyles(styles)(FulfillRequest));
Stripe Element:
class CheckoutForm extends Component {
constructor(props) {
super(props);
this.state = { complete: false };
this.submit = this.submit.bind(this);
}
async submit(ev) {
let { token } = await this.props.stripe.createToken({ name: 'Name' });
let response = await fetch(
'https://us-east1-foodmigo-v01-101.cloudfunctions.net/api/charge',
{
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: token.id
}
);
if (response.ok) this.setState({ complete: true });
}
render() {
if (this.state.complete) return <h1>Purchase Complete</h1>;
return (
<div className="checkout">
<p>Would you like to be a hero?</p>
<CardElement />
<Button variant="contained" color="secondary" onClick={this.submit}>
Send
</Button>
</div>
);
}
}
export default injectStripe(CheckoutForm);