jam-cloud/web/app/assets/javascripts/react-components/BookLessonFree.js.jsx.coffee

275 lines
9.1 KiB
CoffeeScript

context = window
rest = context.JK.Rest()
logger = context.JK.logger
UserStore = context.UserStore
@BookLessonFree = React.createClass({
mixins: [
Reflux.listenTo(AppStore, "onAppInit"),
Reflux.listenTo(UserStore, "onUserChanged")
]
onAppInit: (@app) ->
@app.bindScreen('jamclass/book-lesson-free',
{beforeShow: @beforeShow, afterShow: @afterShow, beforeHide: @beforeHide})
onUserChanged: (userState) ->
@setState({user: userState?.user})
componentDidMount: () ->
@root = $(@getDOMNode())
@slot1Date = @root.find('.slot-1 .date-picker')
@slot2Date = @root.find('.slot-2 .date-picker')
@slot1Date.datepicker({
dateFormat: "D M d yy",
onSelect: ((e) => @toggleDate(e))
})
@slot2Date.datepicker({
dateFormat: "D M d yy",
onSelect: ((e) => @toggleDate(e))
})
toggleDate: (e) ->
beforeHide: (e) ->
logger.debug("LessonBookingFree: beforeHide")
@resetErrors()
beforeShow: (e) ->
logger.debug("LessonBookingFree: beforeShow", e.id)
afterShow: (e) ->
logger.debug("LessonBookingFree: afterShow", e.id)
@setState({teacherId: e.id})
@resetErrors()
rest.getUserDetail({
id: e.id,
show_teacher: true
}).done((response) => @userDetailDone(response)).fail(@app.ajaxError)
userDetailDone: (response) ->
if response.id == @state.teacherId
@setState({teacher: response, isSelf: response.id == context.JK.currentUserId})
else
logger.debug("BookLessonFree: ignoring teacher details", response.id, @state.teacherId)
getInitialState: () ->
{
user: null,
teacher: null,
teacherId: null,
generalErrors: null,
descriptionErrors: null,
slot1Errors: null,
slot2Errors: null
updating: false
}
jamclassPolicies: (e) ->
e.preventDefault()
context.JK.popExternalLink($(e.target).attr('href'))
getSlotData: (position) ->
$slot = @root.find('.slot-' + (position + 1))
picker = $slot.find('.date-picker')
date = picker.datepicker("getDate")
hour = $slot.find('.hour').val()
minute = $slot.find('.minute').val()
am_pm = $slot.find('.am_pm').val()
if hour? and hour != ''
hour = new Number(hour)
if am_pm == 'PM'
hour += 12
hour -= 1
else
hour = null
if minute? and minute != ''
minute = new Number(minute)
else
minute = null
day = null
if date?
day = context.JK.formatDateYYYYMMDD(date)
{hour: hour, minute: minute, day: day}
resetErrors: () ->
@setState({generalErrors: null, slot1Errors: null, slot2Errors: null, descriptionErrors: null})
onBookFreeLesson: (e) ->
e.preventDefault()
if $(e.target).is('.disabled')
return
options = {}
options.teacher = this.state.teacher.id
options.payment_style = 'elsewhere'
options.lesson_type = 'single-free'
options.slots = [@getSlotData(0), @getSlotData(1)]
options.timezone = Ajstz.determine().name()
description = @root.find('textarea.user-description').val()
if description == ''
description == null
options.description = description
@resetErrors()
@setState({updating: true})
rest.bookLesson(options).done((response) => @booked(response)).fail((jqXHR) => @failedBooking(jqXHR))
booked: (response) ->
@setState({updating: false})
if response.user['has_stored_credit_card?']
context.location = '/client#/home'
else
context.location = '/client#/jamclass/payment'
failedBooking: (jqXHR) ->
@setState({updating: false})
if jqXHR.status == 422
body = JSON.parse(jqXHR.responseText)
generalErrors = {errors: {}}
for errorType, errors of body.errors
if errorType == 'description'
@setState({descriptionErrors: errors})
else if errorType == 'lesson_booking_slots'
# do nothing. these are handled better by the _children errors
else
generalErrors.errors[errorType] = errors
for childErrorType, childErrors of body._children
if childErrorType == 'lesson_booking_slots'
slot1Errors = childErrors[0]
slot2Errors = childErrors[1]
if Object.keys(slot1Errors["errors"]).length > 0
@setState({slot1Errors: slot1Errors})
if Object.keys(slot2Errors["errors"]).length > 0
@setState({slot2Errors: slot2Errors})
if Object.keys(generalErrors.errors).length > 0
@setState({generalErrors: generalErrors})
onCancel: (e) ->
e.preventDefault()
render: () ->
photo_url = teacher?.photo_url
if !photo_url?
photo_url = '/assets/shared/avatar_generic.png'
teacher = @state.teacher
if teacher?
name = `<div className="teacher-name">{teacher.name}</div>`
teacher_first_name = teacher.first_name
else
name = `<div className="teacher-name">Loading...</div>`
teacher_first_name = '...'
hours = []
for hour in ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
hours.push(`<option key={hour} value={hour}>{hour}</option>`)
minutes = []
for minute in ['00', '15', '30', '45']
minutes.push(`<option key={minute} value={minute}>{minute}</option>`)
am_pm = [`<option key="AM" value="AM">AM</option>`, `<option key="PM" value="PM">PM</option>`]
bookLessonClasses = classNames({"button-orange": true, disabled: !this.state.teacher? && !@state.updating})
cancelClasses = classNames({"button-grey": true, disabled: !this.state.teacher? && !@state.updating})
descriptionErrors = context.JK.reactSingleFieldErrors('description', @state.descriptionErrors)
slot1Errors = context.JK.reactErrors(@state.slot1Errors, {preferred_day: 'Date'})
slot2Errors = context.JK.reactErrors(@state.slot2Errors, {preferred_day: 'Date'})
generalErrors = context.JK.reactErrors(@state.generalErrors, {user: 'You'})
descriptionClasses = classNames({description: true, error: descriptionErrors?})
slot1Classes = classNames({slot: true, 'slot-1': true, error: slot1Errors?})
slot2Classes = classNames({slot: true, 'slot-2': true, error: slot2Errors?})
generalClasses = classNames({general: true, error: generalErrors?})
`<div className="content-body-scroller">
<div className="lesson-booking">
<div className="column column-left">
<h2>book free lesson</h2>
<div className="slots">
<div className={slot1Classes}>
<div className="slot-prompt">What date/time do you prefer for your lesson?</div>
<div className="field date">
<label>Date:</label>
<input className="date-picker" type="text" data-slot="1"></input>
</div>
<div className="field time">
<label>Time:</label>
<select className="hour">{hours}</select> : <select className="minute">{minutes}</select> <select
className="am_pm">{am_pm}</select>
</div>
{slot1Errors}
</div>
<div className={slot2Classes}>
<div className="slot-prompt">What is a second date/time option if preferred not available?</div>
<div className="field date">
<label>Date:</label>
<input className="date-picker" type="text" data-slot="2"></input>
</div>
<div className="field time">
<label>Time:</label>
<select className="hour">{hours}</select> : <select className="minute">{minutes}</select> <select
className="am_pm">{am_pm}</select>
</div>
{slot2Errors}
</div>
</div>
<div className={descriptionClasses}>
<div className="description-prompt">Tell {teacher_first_name} a little about yourself as a student.</div>
<textarea className="user-description" defaultValue=""/>
{descriptionErrors}
</div>
</div>
<div className="column column-right">
<div className="teacher-header">
<div className="avatar">
<img src={photo_url}/>
</div>
{name}
</div>
<div className="booking-info">
<p>You are purchasing a single free 30-minute JamClass session.</p>
<p>To book this lesson, you will need to enter your credit card information.
You will absolutely not be charged for this free lesson, and you have no further
commitment to purchase anything. We have to collect a credit card to prevent abuse
by some users who would otherwise set up multiple free accounts to get multiple free lessons.<br/>
<div className="jamclass-policies"><a href="/corp/terms" rel="external" onClick={this.jamclassPolicies}>jamclass
policies</a></div>
</p>
</div>
</div>
<br className="clearall"/>
<div className={generalClasses}>
{generalErrors}
</div>
<div className="actions">
<a className={bookLessonClasses} onClick={this.onBookFreeLesson}>BOOK FREE LESSON</a>
<a className={cancelClasses} onClick={this.onCancel}>CANCEL</a>
</div>
</div>
</div>`
})