Skip to content

Instantly share code, notes, and snippets.

@barek2k2
Created July 21, 2017 03:39
Show Gist options
  • Save barek2k2/c2af7110c9f646d2e9eda690ae12e1ac to your computer and use it in GitHub Desktop.
Save barek2k2/c2af7110c9f646d2e9eda690ae12e1ac to your computer and use it in GitHub Desktop.
var Payment = React.createClass({
getInitialState(){
return ({
clinicians: this.props.clinicians,
currentClinician: this.props.currentClinician,
unallocatedCredit: 0.0,
patients: [],
currencyTypes: [
{name: 'United States Dollar', code: 'usd'},
{name: 'Canadian Dollar', code: 'cad'}
],
preferredCreditCardOptions: [
{name: 'Visa', label: 'Visa'},
{name: 'Mastercard', label: 'Mastercard'},
{name: 'AmericanExpress', label: 'American Express'},
{name: 'Discover', label: 'Discover'}
],
creditCardOptions: [],
isNewCard: false,
hasStripeKey: false,
payment: {
clinician_id: this.props.currentClinician.id,
patient_id: null,
payment_type_id: null,
payment_date: moment($("#payment_date").val())._d,
amount: null,
payment_number: null,
memo: null,
preferred_credit_card: null,
stripe_card_token: null,
save_patient_payment_method: false,
patient_payment_method_id: null,
currency: 'usd',
print: false,
invoice_id: null,
payment_class_id: null,
payment_invoice_events: []
},
errors: {
amount: false,
patient_id: false,
payment_type_id: false,
payment_class_id: false,
patient_payment_method_id: false
},
selectedPatient: null,
isCreditCard: false,
isPaymentNumberRequired: false,
useCredit: false
})
},
componentWillMount() {
var that = this;
},
componentDidMount() {
var that = this;
$("select.chosen").chosen();
that.loadPatients(that.state.currentClinician.id);
$("body").delegate("#payment_cl1inician_dropdown", "change", function () {
that.loadPatients($(this).val());
});
$('#payment_modal').on('shown.bs.modal', function(e) {
var target = e.relatedTarget;
if(target){
var payment = that.state.payment;
var errors = that.state.errors;
errors.patient_id = errors.payment_type_id = errors.payment_class_id = errors.amount = false;
payment.patient_id = payment.payment_type_id = payment.payment_class_id = payment.amount = payment.memo = null;
that.setState({selectedPatient: null, isNewCard: false, payment: payment, errors: errors}, function () {
$("#patient_id,#payment_type_id,#payment_class_id").val("").chosen('destroy').chosen();
$("#amount, #memo").val('');
that.refs.unpaid_invoices.fetchUnpaidInvoices(null);
})
}
});
$("body").delegate("#payment_type_id", "change", function () {
var isCreditCard = $(this).find('option:selected').text() == 'Credit Card';
var isPaymentNumberRequired = that.isPaymentNumberRequired();
that.setState({isCreditCard: isCreditCard, isPaymentNumberRequired: isPaymentNumberRequired}, function () {
$("select.chosen, #patient_payment_method_id").chosen();
})
});
$("body").delegate("#patient_id", "change", function () {
var payment = that.state.payment;
var errors = that.state.errors;
errors.amount = false;
payment.amount = null;
var json = {payment: payment, errors: errors};
if($(this).val() == '') json['selectedPatient'] = null;
var patientId = $(this).val();
that.setState(json, function () {
that.refs.unpaid_invoices.fetchUnpaidInvoices(patientId);
$("#amount").val('');
$(".payment-errors").text('')
});
if (that.hasStripeKey()) {
$.ajax({
method: 'GET',
type: 'json',
async: true,
url: "/api/patient_payment_methods.json?patient_id=" + $(this).val(),
success: function (response) {
var patientPaymentMethods = response.patient_payment_methods;
var payment = that.state.payment;
patientPaymentMethods = patientPaymentMethods.concat([{id: 'new_card', name: "New Card"}]);
var patientPaymentMethodId = patientPaymentMethods.length == 1 ? 'new_card' : patientPaymentMethods[0].id;
$("#patient_payment_method_id").val(patientPaymentMethodId);
payment.patient_payment_method_id = patientPaymentMethodId;
var isNewCard = payment.patient_payment_method_id == 'new_card';
that.setState({creditCardOptions: patientPaymentMethods, payment: payment, isNewCard: isNewCard}, function () {
$("#patient_payment_method_id").chosen('destroy').chosen();
})
}
});
}
$("#patient_payment_method_id").chosen();
});
$('.date').datepicker({autoclose: true, forceParse: false}).on('changeDate', function (e) {
var date = moment(e.date);
});
$("body").delegate(".form_field", "change keyup", function (e) {
that.handleFieldChanged(e)
});
$("body").delegate("#patient_payment_method_id", "change", function () {
that.setState({isNewCard: $(this).val() == 'new_card'})
})
$("body").delegate("input#amount", "keyup", function (e) {
that.refs.unpaid_invoices.calculateUnallocatedCredit($(this))
});
$("body").delegate("#use_credit", "click", function (e) {
var payment = that.state.payment;
var errors = that.state.errors;
if($(this).is(":checked")){
var paymentTypeId = $('#payment_type_id option').filter(function () { return $(this).html() == "Credit"; }).val();
var paymentClassId = $('#payment_class_id option').filter(function () { return $(this).html() == "Patient Payment"; }).val();
$('#payment_type_id').val(paymentTypeId).chosen('destroy').chosen().trigger("chosen:updated");
$('#payment_class_id').val(paymentClassId).chosen('destroy').chosen().trigger("chosen:updated");
payment.payment_type_id = paymentTypeId;
payment.payment_class_id = paymentClassId;
}
else{
$('#payment_type_id,#payment_class_id').val('').chosen('destroy').chosen().trigger("chosen:updated");
payment.payment_type_id = payment.payment_class_id = null;
errors.payment_type_id = errors.payment_class_id = false;
}
that.setState({payment: payment, errors: errors, useCredit: $(this).is(":checked")})
});
var hasStripeKey = that.hasStripeKey();
var payment = that.state.payment;
if(hasStripeKey){
payment.preferred_credit_card = null
}
else{
payment.preferred_credit_card = 'Visa'
}
that.setState({hasStripeKey: hasStripeKey, payment: payment})
},
selectedPatientHandler(patient){
var that = this;
that.setState({selectedPatient: patient}, function () {
$("#currency,#preferred_credit_card").chosen()
})
},
loadPatients(clinicianId){
var that = this;
$.ajax({
url: "/api/v2/patients?clinician_id=" + clinicianId,
type: 'GET',
success: function (response) {
that.setState({patients: response.patients}, function () {
$("#patient_id").chosen('destroy');
$("#patient_id").chosen();
});
}
});
},
isPaymentNumberRequired(){
var that = this;
var type = $("#payment_type_id").find('option:selected').text();
return type == 'Check' || type == 'Cash' || (type == 'Credit Card' && !that.hasStripeKey());
},
isCreditCard(){
return this.get('payment_type.name') == 'Credit Card';
},
hasStripeKey(){
var that = this;
var payment_status = that.state.currentClinician.payment_status;
if (payment_status == 'Trial' || payment_status == 'Paid' || payment_status == 'Unpaid' || payment_status == 'Past Due') {
if (that.state.currentClinician.stripe_publishable_key != '') {
return true;
} else {
return false;
}
} else {
return false;
}
},
handleFieldChanged(e){
var that = this;
if (that.isMounted()) {
var payment = that.state.payment;
var field = $(e.target);
var value = e.target.value;
attrName = field.attr('name');
if (field.is(':checkbox')) {
value = field.is(':checked')
}
var validAttributes = Object.keys(payment);
if (validAttributes.indexOf(attrName) > -1) {
payment[attrName] = value;
var errors = that.state.errors;
var errorAttributes = Object.keys(errors);
if (errorAttributes.indexOf(attrName) > -1) {
errors[attrName] = value == ''
}
that.setState({payment: payment, errors: errors})
}
}
},
stripeTokenHandler(token=null){
var that = this;
if(token){
var payment = that.state.payment;
payment.stripe_card_token = token;
that.setState({payment: payment}, function () {
that.savePayment()
});
}
},
preparePayment(){
var that = this;
var errors = that.state.errors;
var hasError = false;
Object.keys(errors).forEach(function (key) {
var element = $("#" + key);
if (element.length > 0 && (element.val() == '' || element.val() == undefined)) {
errors[key] = true;
hasError = true;
}
});
if (hasError) {
that.setState({errors: errors})
return false;
}
var payment = that.state.payment;
var paymentInvoiceEvents = [];
$(".money-control").each(function () {
var amount = $(this).val();
if (amount > 0) {
paymentInvoiceEvents.push({
invoice_id: $(this).attr('id').replace('amount_', ''),
payment_id: null,
amount: amount,
id: null
})
}
});
payment.payment_invoice_events = paymentInvoiceEvents;
payment.payment_date = moment(payment.payment_date)._d;
if($("#patient_payment_method_id").val() == 'new_card'){
that.refs.stripe_form.createStripeToken();
}
else{
payment.stripe_card_token = null;
payment.save_patient_payment_method = null;
that.savePayment();
}
},
savePayment(){
var that = this;
var payment = that.state.payment;
$.ajax({
type: 'POST',
url: "/api/v2/payments",
data: {payment: payment},
beforeSend: function () {
$("img.saving_payment").show();
$("#payment_modal div.modal-footer").hide();
$('.payment_error_message .payment-errors').text('').show();
},
success: function (response) {
$("#payment_modal").modal('hide');
$("img.saving_payment").hide();
$('#payment_modal').scrollTop(0);
$("#calendar").fullCalendar('refetchEvents');
$('#success_flash span').text('Payment for ' + that.state.selectedPatient.firstname + ' ' + that.state.selectedPatient.lastname + ' was successfully saved!').show().parent().fadeIn().delay(5000).fadeOut('slow', function(){
$('#success_flash span').text('');
});
},
error: function (xhr,status,error) {
var errorMessage = JSON.parse(xhr.responseText).message;
$('#payment_modal').scrollTop(0);
$('.payment_error_message .payment-errors').text("Error: "+errorMessage).show();
$("img.saving_payment").hide();
$("#payment_modal div.modal-footer").show()
}
})
},
render: function () {
var that = this;
clinicianOptions = that.state.clinicians.map(function (clinician) {
return (<option key={clinician.id} value={clinician.id}>{clinician.name}</option>)
});
patientsOptions = that.state.patients.map(function (patient) {
return (<option key={patient.id} value={patient.id}>{patient.name}</option>)
});
paymentTypeOptions = that.state.currentClinician.payment_types.map(function (payment_type) {
return (<option key={payment_type.id} value={payment_type.id}>{payment_type.name}</option>)
});
paymentClassOptions = that.state.currentClinician.payment_classes.map(function (payment_class) {
return (<option key={payment_class.id} value={payment_class.id}>{payment_class.name}</option>)
});
currencyTypes = that.state.currencyTypes.map(function (currencyType) {
return (<option key={currencyType.code} value={currencyType.code}>{currencyType.name}</option>)
});
preferredCreditCardOptions = that.state.preferredCreditCardOptions.map(function (creditCardOption) {
return (<option key={creditCardOption.name} value={creditCardOption.name}>{creditCardOption.label}</option>)
});
creditCardOptions = that.state.creditCardOptions.map(function (creditCardOption) {
return (<option key={creditCardOption.id} value={creditCardOption.id}>{creditCardOption.name}</option>)
});
return (
<div id="payment_modal" className="modal fade">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 className="modal-title">Payment</h4>
</div>
<div className="modal-body">
<form className="form-horizontal" id="payment_form" role="form">
<div className="form-group">
<div className="form-row">
<label className="form-labels control-label">Clinician</label>
<div className="form-main">
<select name="clinician_id" defaultValue={that.state.currentClinician.id}
className="chosen form_field" id="payment_clinician_dropdown">
<option >Select</option>
{clinicianOptions}
</select>
</div>
</div>
</div>
<div className={that.state.errors.patient_id ? "form-group has-error" : "form-group" }>
<div className="form-row">
<label className="form-labels control-label">Patient</label>
<div className="form-main">
<select name="patient_id" className="chosen form_field" id="patient_id">
<option value="">Select</option>
{patientsOptions}
</select>
</div>
</div>
{that.state.errors.patient_id &&
<div className="form-row">
<div className="form-labels"></div>
<div className="help-block form-main">Patient is required</div>
</div>
}
</div>
<div className="form-group">
<div className="form-row">
<label className="form-labels control-label">Payment Date</label>
<div className="form-main-together">
<div className="date input-group">
<input name="payment_date" id="payment_date" className="form-control form_field date"
defaultValue={moment(that.props.date).format("MM/DD/YYYY")} type="text"/>
<span className="input-group-addon btn"><i className="glyphicon glyphicon-calendar"></i></span>
</div>
</div>
</div>
</div>
{ that.state.selectedPatient && that.state.selectedPatient.credits > 0 &&
<div className="form-group">
<div className="form-row">
<label className="form-labels control-label">Credit</label>
<div className="form-main">
<p className="form-control-static">
{that.state.selectedPatient.credits.formatCurrency()}
<span style={{marginLeft: '10px'}}>
<input id="use_credit" className="" type="checkbox"/>
<label htmlFor="use_credit" style={{fontWeight: 'normal', cursor: 'pointer', marginLeft: '5px'}}> Use Credit</label>
</span>
</p>
</div>
</div>
</div>
}
{ that.state.selectedPatient && that.state.useCredit &&
<div style={{marginLeft: '147px'}}>
To add money to the payment, choose a different payment type.
</div>
}
<div className={that.state.errors.payment_type_id ? "form-group has-error" : "form-group" }>
<div className="form-row">
<label className="form-labels control-label">Payment Type</label>
<div className="form-main">
<select name="payment_type_id" id="payment_type_id" className="chosen form_field">
<option value="">Select Payment Type</option>
{paymentTypeOptions}
</select>
</div>
</div>
{that.state.errors.payment_type_id &&
<div className="form-row">
<div className="form-labels"></div>
<div className="help-block form-main">Payment type is required</div>
</div>
}
</div>
<div className={that.state.errors.payment_class_id ? "form-group has-error" : "form-group" }>
<div className="form-row">
<label className="form-labels control-label">Payment Class</label>
<div className="form-main">
<select name="payment_class_id" id="payment_class_id" className="chosen form_field">
<option value="">Select Payment Class</option>
{paymentClassOptions}
</select>
</div>
</div>
{that.state.errors.payment_class_id &&
<div className="form-row">
<div className="form-labels"></div>
<div className="help-block form-main">Payment class is required</div>
</div>
}
</div>
{ that.state.selectedPatient &&
<div className="form-group">
<div className="form-row">
<label className="form-labels control-label">Currency</label>
<div className="form-main">
<select name="currency" id="currency" className="chosen form_field">
{currencyTypes}
</select>
</div>
</div>
</div>
}
<div className={that.state.errors.amount ? 'form-group has-error' : 'form-group'}>
<div className="form-row">
<label className="form-labels control-label">Amount</label>
<div className="form-main form-main-left">
<input name="amount" className="form-control form_field" id="amount" placeholder="$"
type="number"/>
</div>
</div>
{that.state.errors.amount &&
<div className="form-row">
<div className="form-labels"></div>
<div className="help-block form-main">Amount is required</div>
</div>
}
</div>
{ that.state.selectedPatient && that.state.hasStripeKey && that.state.isCreditCard &&
<div className={that.state.errors.patient_payment_method_id ? 'form-group has-error' : 'form-group'}>
<div className="form-row">
<label className="form-labels control-label">Credit Card*</label>
<div className="form-main">
<select name="patient_payment_method_id" id="patient_payment_method_id" className="form_field">
{creditCardOptions}
</select>
</div>
</div>
{that.state.errors.patient_payment_method_id &&
<div className="form-row">
<div className="form-labels"></div>
<div className="help-block form-main">Credit Card is required</div>
</div>
}
</div>
}
{ that.state.selectedPatient && !that.state.hasStripeKey &&
<div className="form-group">
<div className="form-row">
<label className="form-labels control-label">Credit Card</label>
<div className="form-main">
<select name="preferred_credit_card" id="preferred_credit_card" className="chosen form_field">
{preferredCreditCardOptions}
</select>
</div>
</div>
</div>
}
{ that.state.selectedPatient && that.state.hasStripeKey &&
<div className="form-group payment_error_message">
<div className="form-row">
<label className="form-labels control-label"></label>
<div className="form-main">
<p className="payment-errors"></p>
</div>
</div>
</div>
}
{that.state.isNewCard && that.state.isCreditCard &&
<StripeForm ref="stripe_form" stripeTokenHandler={that.stripeTokenHandler} currentClinician={that.state.currentClinician} />
}
{ that.state.isPaymentNumberRequired &&
<div className="form-group">
<div className="form-row">
<label className="form-labels control-label">Check/Payment #</label>
<div className="form-main">
<input name="payment_number" id="check_payment_number" className="form-control form_field"
type="text"/>
</div>
</div>
</div>
}
<div className="form-group">
<div className="form-row">
<label className="form-labels control-label">
Memo
</label>
<div className="form-main">
<textarea rows="4" id="memo" className="form-control form_field" name="memo"/>
</div>
</div>
</div>
{ that.state.selectedPatient &&
<p className="right" style={{'marginRight': '15px'}}>Total Amount
Due: {that.state.selectedPatient.patient_balance.formatCurrency()}</p>
}
<UnpaidInvoices ref="unpaid_invoices" selectedPatientHandler={that.selectedPatientHandler} />
</form>
</div>
<p style={{'textAlign': 'center'}}>
<img className="saving_payment" style={{'display': 'none'}}
src={that.props.loadingImagePath}/>
</p>
<div className="modal-footer">
<button type="button" className="btn btn-default cancel" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary save" onClick={that.preparePayment}>Save</button>
</div>
</div>
</div>
</div>
);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment