Getting credit card brand and show error message when using hosted fields in Braintree - braintree-sandbox

I am trying to create payment page using braintree's hosted fields.
I have created sandbox account.
But i am not getting additional details like Card brand, error message like Drop in UI.
How to get those functionalities using Hosted fields.
import React from 'react';
var braintree = require('braintree-web');
class BillingComponent extends React.Component {
constructor(props) {
super(props);
this.clientDidCreate = this.clientDidCreate.bind(this);
this.hostedFieldsDidCreate = this.hostedFieldsDidCreate.bind(this);
this.submitHandler = this.submitHandler.bind(this);
this.showPaymentPage = this.showPaymentPage.bind(this);
this.state = {
hostedFields: null,
errorOccurred: false,
};
}
componentDidCatch(error, info) {
this.setState({errorOccurred: true});
}
componentDidMount() {
this.showPaymentPage();
}
showPaymentPage() {
braintree.client.create({
authorization: 'sandbox_xxxxx_xxxxxxx'
}, this.clientDidCreate);
}
clientDidCreate(err, client) {
braintree.hostedFields.create({
onFieldEvent: function (event) {console.log(JSON.stringify(event))},
client: client,
styles: {
'input': {
'font-size': '16pt',
'color': '#020202'
},
'.number': {
'font-family': 'monospace'
},
'.valid': {
'color': 'green'
}
},
fields: {
number: {
selector: '#card-number',
'card-brand-id': true,
supportedCardBrands: 'visa'
},
cvv: {
selector: '#cvv',
type: 'password'
},
expirationDate: {
selector: '#expiration-date',
prefill: "12/21"
}
}
}, this.hostedFieldsDidCreate);
}
hostedFieldsDidCreate(err, hostedFields) {
let submitBtn = document.getElementById('my-submit');
this.setState({hostedFields: hostedFields});
submitBtn.addEventListener('click', this.submitHandler);
submitBtn.removeAttribute('disabled');
}
submitHandler(event) {
let submitBtn = document.getElementById('my-submit');
event.preventDefault();
submitBtn.setAttribute('disabled', 'disabled');
this.state.hostedFields.tokenize(
function (err, payload) {
if (err) {
submitBtn.removeAttribute('disabled');
console.error(err);
}
else {
let form = document.getElementById('my-sample-form');
form['payment_method_nonce'].value = payload.nonce;
alert(payload.nonce);
// form.submit();
}
});
}
render() {
return (
<div className="user-prelogin">
<div className="row gutter-reset">
<div className="col">
<div className="prelogin-container">
<form action="/" id="my-sample-form">
<input type="hidden" name="payment_method_nonce"/>
<label htmlFor="card-number">Card Number</label>
<div className="form-control" id="card-number"></div>
<label htmlFor="cvv">CVV</label>
<div className="form-control" id="cvv"></div>
<label htmlFor="expiration-date">Expiration Date</label>
<div className="form-control" id="expiration-date"></div>
<input id="my-submit" type="submit" value="Pay" disabled/>
</form>
</div>
</div>
</div>
</div>
);
}
}
export default BillingComponent;
I am able to get basic functionalities like getting nonce from card details. But i am unable to display card brand image/error message in the page as we show in Drop in UI.
How to show card brand image and error message using hosted fields?
Page created using Hosted fields:
Page created Drop in UI - Which shows error message
Page created Drop in UI - Which shows card brand

Though we do not get exact UI like Drop in UI, we can get the card type and display it ourselves by using listeners on cardTypeChange.
hostedFieldsDidCreate(err, hostedFields) {
this.setState({hostedFields: hostedFields});
if (hostedFields !== undefined) {
hostedFields.on('cardTypeChange', this.cardTypeProcessor);
hostedFields.on('validityChange', this.cardValidator);
}
this.setState({load: false});
}
cardTypeProcessor(event) {
if (event.cards.length === 1) {
const cardType = event.cards[0].type;
this.setState({cardType: cardType});
} else {
this.setState({cardType: null});
}
}
cardValidator(event) {
const fieldName = event.emittedBy;
let field = event.fields[fieldName];
let validCard = this.state.validCard;
// Remove any previously applied error or warning classes
$(field.container).removeClass('is-valid');
$(field.container).removeClass('is-invalid');
if (field.isValid) {
validCard[fieldName] = true;
$(field.container).addClass('is-valid');
} else if (field.isPotentiallyValid) {
// skip adding classes if the field is
// not valid, but is potentially valid
} else {
$(field.container).addClass('is-invalid');
validCard[fieldName] = false;
}
this.setState({validCard: validCard});
}
Got the following response from braintree support team.
Hosted fields styling can be found in our developer documentation. Regarding the logos, you can download them from the card types official websites -
Mastercard
Visa
AMEX
Discover
JCB
Or online from other vendors.
Note: Drop-In UI will automatically fetch the brand logos and provide validation errors unlike hosted fields as it is less customizable.

Related

I need to Delete any object from my DRF / django connected database through angular 13

I am getting the id which i have to delete but the last line of service.ts that is of delete method is not getting executed...
the files and code snippets I used are : -
COMPONENT.HTML
<li *ngFor="let source of sources$ | async | filter: filterTerm">
<div class="card">
<div class="card-body">
<h5 class="card-title">{{source.name}}</h5>
<p>URL:- <a href ='{{source.url}}'>{{source.url}}</a></p>
<a class="btn btn-primary" href='fetch/{{source.id}}' role="button">fetch</a>
<button class="btn btn-primary" (click)="deleteSource(source.id)">delete </button>
<br>
</div>
</div>
</li>
I tried to console the id geeting from html and the Id i am getting is correct.
//component.ts
export class SourcesComponent implements OnInit {
filterTerm!: string;
sources$ !: Observable<sources[]>;
// deletedSource !: sources;
constructor(private sourcesService: SourcesService) { }
// prepareDeleteSource(deleteSource: sources){
// this.deletedSource = deleteSource;
// }
ngOnInit(): void {
this.Source();
}
Source(){
this.sources$ = this.sourcesService.Sources()
}
deleteSource(id : string){
console.log(id)
this.sourcesService.deleteSource(id);
}
//service.ts
export class SourcesService {
API_URL = 'http://127.0.0.1:8000/sourceapi';
constructor(private http: HttpClient) { }
// let csrf = this._cookieService.get("csrftoken");
// if (typeof(csrf) === 'undefined') {
// csrf = '';
// }
/** GET sources from the server */
Sources() : Observable<sources[]> {
return this.http.get<sources[]>(this.API_URL,);
}
/** POST: add a new source to the server */
addSource(source : sources[]): Observable<sources[]>{
return this.http.post<sources[]> (this.API_URL, source);
//console.log(user);
}
deleteSource(id: string): Observable<number>{
let httpheaders=new HttpHeaders()
.set('Content-type','application/Json');
let options={
headers:httpheaders
};
console.log(id)
return this.http.delete<number>(this.API_URL +'/'+id)
}
}
Angular HTTP functions return cold observables. This means that this.http.delete<number>(this.API_URL +'/'+id) will return an observable, which will not do anything unless someone subscribes to it. So no HTTP call will be performed, since no one is watching the result.
If you do not want to use the result of this call, you have different options to trigger a subscription.
simply call subscribe on the observable:
deleteSource(id : string){
console.log(id)
this.sourcesService.deleteSource(id).subscribe();
}
Convert it to a promise and await it (or don't, if not needed) using lastValueFrom:
async deleteSource(id : string){
console.log(id)
await lastValueFrom(this.sourcesService.deleteSource(id));
}

Error: Invalid hook call when using with redux

Sorry if I am asking a beginner's level question. I am new to React.js and recently I have been trying to grasps the concepts by following this tutorial:
JustDjango
What I am trying to accomplish is creating a login form which uses redux to store the states, my code is as follows :
import React from 'react';
import { Form, Icon, Input, Button, Spin } from 'antd/lib';
import { connect } from 'react-redux';
import { NavLink } from 'react-router-dom';
import * as actions from '../store/actions/auth';
const FormItem = Form.Item;
const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;
class NormalLoginForm extends React.Component {
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
this.props.onAuth(values.userName, values.password);
this.props.history.push('/');
}
});
}
render() {
let errorMessage = null;
if (this.props.error) {
errorMessage = (
<p>{this.props.error.message}</p>
);
}
const { getFieldDecorator } = this.props.form;
return (
<div>
{errorMessage}
{
this.props.loading ?
<Spin indicator={antIcon} />
:
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem>
{getFieldDecorator('userName', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
)}
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit" style={{marginRight: '10px'}}>
Login
</Button>
Or
<NavLink
style={{marginRight: '10px'}}
to='/signup/'> signup
</NavLink>
</FormItem>
</Form>
}
</div>
);
}
}
const WrappedNormalLoginForm = Form.useForm()(NormalLoginForm);
const mapStateToProps = (state) => {
return {
loading: state.loading,
error: state.error
}
}
const mapDispatchToProps = dispatch => {
return {
onAuth: (username, password) => dispatch(actions.authLogin(username, password))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(WrappedNormalLoginForm);
The error traceback shows that the error is coming from :
76 | const WrappedNormalLoginForm = Form.useForm()(NormalLoginForm);
77 |
78 | const mapStateToProps = (state) => {
79 | return {
Some google search on this particular error shows that this error has something to do with hooks being defined in a classed based component , however i do not understand why :
const mapStateToProps = (state) => {......
is considered a hook
Will greatly appreciate anybody's help!
React hooks only used by functional components. You used class components.
Shortly, Form.useForm() the method is only used functional components, you can read it from this link below:
https://ant.design/components/form/

How to do Auth actions with Ionic 4 React with Rails

I'm at a hackathon and trying to use Ionic 4 (react) which I've never used before to connect to a Rails database that I made (auth is done on the backend) that is hosted on heroku. I really just need to connect the auth actions to it on the frontend and I'm running into so many issues, and everything I find for answers is in Angular Ionic and not for React Ionic.
The app is super simple and really just consists of 4 main pages, one is a start page, one is a resource page, one is a home page, and the other is a login page. The Login page will have a sign up and sign in button (when not authenticated) and change password and sign out (when authenticated). I'm having separate pages for sign in, sign up, and change password. I've looked in docs for examples and found none, is there any kind of example I could go off of for something similar/how do I go about learning how to do this? Any input is super helpful, thanks!
So far this is what garbage I have, mostly taken from :
import { IonContent, IonHeader, IonItem, IonLabel, IonList, IonPage, IonTitle, IonToolbar } from '#ionic/react';
// updateUserName = (event: any) => {
// this.setState({ username: event.detail.value });
// };
const SignIn: React.FC = () => {
login= () => {
let url , credentials;
if(this.state.action == 'Login'){
url = CONFIG.API_ENDPOINT + '/users/login';
credentials = {
"user": {
"email": this.state.email,
"password": this.state.password
}
}
} else {
url = CONFIG.API_ENDPOINT + '/users';
credentials = {
"user": {
"email": this.state.email,
"password": this.state.password,
"username": this.state.username
}
}
}
fetch(url, {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(credentials)
})
.then((res) => {
console.log(res);
if(res.status == 200){
return res.json();
} else {
if(this.state.action == 'SignUp') {
throw new Error("Error creating user");
} else {
throw new Error("Error Logging in")
}
}
} )
.then(
(result) => {
console.log(result);
localStorage.setItem("token",result.user.token);
localStorage.setItem("username", result.user.username);
localStorage.setItem("isLogin", "true");
localStorage.setItem("email", result.user.email);
this.event = new CustomEvent('loggedIn', {
detail: true
});
window.dispatchEvent(this.event);
},
(error) => {
console.error(error);
this.setState({toastMessage: error.toString(), toastState: true});
}
)
};
render() {
return(
<IonHeader title="Login">Sign</IonHeader>
<IonContent padding>
<div className="ion-text-center">
<img src={image} alt="logo" width="25%" />
</div>
<h1 className="ion-text-center conduit-title">conduit</h1>
<IonToast
isOpen={this.state.toastState}
onDidDismiss={() => this.setState(() => ({ toastState: false }))}
message= {this.state.toastMessage}
duration={400}
>
</IonToast>
<form action="">
<IonItem>
<IonInput onIonChange={this.updateEmail} type="email" placeholder="Email"></IonInput>
</IonItem>
{this.state.action === 'SignUp' ?
<IonItem>
<IonInput onIonChange={this.updateUserName} type="text" placeholder="Username"></IonInput>
</IonItem>
: <></>
}
<IonItem>
<IonInput onIonChange={this.updatePassword} type="password" placeholder="Password"></IonInput>
</IonItem>
</form>
<IonButton onClick={this.login}>{this.state.action}</IonButton>
</IonContent>
<IonFooter>
<IonToolbar text-center>
Click here to <a onClick={this.toggleAction}>{this.state.action === 'Login'? 'SignUp' : 'Login'}</a>
</IonToolbar>
</IonFooter>
</>
)
}
}

Opencart if product available Button show else disable that button

Hi i'm creating a application using Opencart. It fully customized, i have doubt in this.
I have filter.tpl page, in this page i need to display and hide button based on product availability
Eg:
If product available show like this
enter image description here
else button show like this enter image description here
Am trying this fowling code using ajax
filter.tpl
$('input[name=\'filter_name\']').autocomplete({
'source': function(request, response) {
$.ajax({
url: 'index.php?route=catalog/product/getProductCheck' + encodeURIComponent(request),
dataType: 'json',
success: function(json) {
response($.map(json, function(item) {
return {
label: item['name'],
value: item['product_id']
}
}));
}
});
},
'select': function(item) {
$('input[name=\'filter_name\']').val(item['label']);
}
});
In controller
product.php
public function getProductCheck()
{
/*Some code here*/
}
So you can use if ($product['quantity']) statement for example
I got the out put am using javascript following code
<div class="form-group">
<div style='display:none;' id='instock'>
<a class='instock-btn'>Product / Solution Available</a>
<input type='submit' class='btn-orng available' name='' value="Click here for more details" size='20' />
</div>
<div style='display:none;' id="outstock">
<input type='submit' class='outstock-btn' name='' value="Product / Solution Not Available" size='20' />
<input type='submit' class='btn-orng' name='' value="We will contact you at the earliest" size='20' />
</div>
</div>
script
$(document).ready(function(){
$('#dia1').on('change', function() {
//var value =
if (this.value <='320' )
{
$("#instock").show();
$("#outstock").hide();
}
else
{
$("#instock").hide();
$("#outstock").show();
}
});
$('#len1').on('change', function() {
//var value =
if (this.value <='310' )
{
$("#instock").show();
$("#outstock").hide();
}
else
{
$("#instock").hide();
$("#outstock").show();
}
});
});

How to unit test forms with Sinon and Chai

I am using Chai, Sinon, and Mocha to test.
I am using Redux-Forms, along with ReactJS.
I want to test what happens after I click submit on a Forgot Password page.
Here's my code so far:
react file:
propTypes: {
fields: React.PropTypes.object.isRequired,
message: React.PropTypes.string.isRequired,
handleSubmit: React.PropTypes.func.isRequired,
},
renderForm: function() {
const { fields: {email}, handleSubmit, isFetching } = this.props;
const iconClass = "fa fa-star-o";
return(
<form form="forgotPassword" name="forgotPassword" className="stack-input">
<ReduxFormTextInput
{...email}
floatingLabelText="Email Address" />
<div className="clearfix" />
<div className="form-footer">
<ButtonSpinner spinner={isFetching} onClick={handleSubmit} ripple={true} raised={true} primary={true} >
<i className={iconClass} />Send
</ButtonSpinner>
</div>
</form>
);
},
renderMessage: function() {
return(
<div>
<i className="fa fa-exclamation-circle" style={{marginRight: '4px'}}/>
If your email is in the system, then it will be sent.
</div>
);
},
//Checks if user has submitted email.
emailSubmit: function(){
var locus = this, props = locus.props;
if(props.message === ''){
return null;
}
else if(props.message === 'SENT'){
return true;
}
return null;
},
render(){
var locus = this, props= locus.props;
return(
<div className="page-wrap">
<div className="page-column">
<h2>Forgot Your Password</h2>
{this.emailSubmit() ? this.renderMessage(): this.renderForm()}
</div>
</div>
);
}
unittest file:
describe('ForgotPasswordForm', () => {
const component = setup({
fields: {
email: {
onChange: spy(),
onBlur: spy(),
onFocus: spy()
}
}, // React.PropTypes.object.isRequired,
message: '', // React.PropTypes.string.isRequired,
handleSubmit: spy() // React.PropTypes.func.isRequired,
//onClearMessage:spy() //, React.PropTypes.func.isRequired
}),
domRoot = TestUtils.findRenderedDOMComponentWithClass(component, 'page-wrap'),
title = TestUtils.findRenderedDOMComponentWithTag(component, 'h2'),
submitButton = TestUtils.findRenderedDOMComponentWithClass(component, 'material-D-button'),
form = TestUtils.findRenderedDOMComponentWithTag(component, 'form'),
inputs = TestUtils.scryRenderedDOMComponentsWithTag(component, 'input'),
emailInput = inputs[0];
This test keeps failing, despite multiple attempts. I am not experienced with Spy(), so I'm not sure if I am suppose to be using calledWith.
it ('should display "If your email is in the system, then it will be sent." on submit', () => {
TestUtils.Simulate.change(emailInput, {target: {value: 'test#email.com'}});
TestUtils.Simulate.click(submitButton);
expect(domColumn.text).to.equal("Forgot Your Password");
});
This is the response I get.
+"If your email is in the system, then it will be sent."
- -"Forgot Your PasswordSend"
I used innerHTML to get a sense of what's being populated after the click, and I don't think the click is even registering.
When I try to do TestUtils.Simulate.change(emailInput, {target: {value: 'test#email.com'}});, it doesn't work. I have to populate the value of the email in the component.
You should be assigning your handleSubmit spy to a constant so you can at least be able to check whether it's getting called. (Probably the same for the other spies).
const handleSubmitSpy = spy()
const component = setup({
...
handleSubmit: handleSubmitSpy
Now you can check expect(handleSubmitSpy).toHaveBeenCalled().