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

1144 lines
33 KiB
CoffeeScript
Raw Permalink Normal View History

context = window
rest = context.JK.Rest()
logger = context.JK.logger
UserStore = context.UserStore
@LessonBooking = React.createClass({
mixins: [
@PostProcessorMixin,
Reflux.listenTo(AppStore, "onAppInit"),
Reflux.listenTo(UserStore, "onUserChanged")
]
onAppInit: (@app) ->
@app.bindScreen('jamclass/lesson-booking',
{beforeShow: @beforeShow, afterShow: @afterShow, beforeHide: @beforeHide, navName: 'Lesson Booking'})
onUserChanged: (userState) ->
@setState({user: userState?.user})
onSlotDecision: (slot_decision) ->
@setState({slot_decision: slot_decision?.slot_decision})
onUpdateAllDecision: (update_all) ->
@setState({update_all: update_all?.update_all})
componentWillMount: () ->
componentDidMount: () ->
@checkboxes = [{selector: 'input.slot-decision', stateKey: 'slot-decision'}]
@root = $(@getDOMNode())
componentDidUpdate: () ->
# add friendly helpers to a slot
processSlot: (slot, booking) ->
if !slot?
return
slot.slotTime = @slotTime(slot, booking)
2017-07-10 02:21:29 +00:00
slot.is_recurring = slot.slot_type == 'recurring'
if slot['is_teacher_created?']
slot.creatorRole = 'teacher'
slot.creatorRoleRelative = 'teacher'
else
slot.creatorRole = 'student'
slot.creatorRoleRelative = 'student'
if context.JK.currentUserId == slot.proposer_id
slot.creatorRoleRelative = "your"
slot.mySlot = @mySlot(slot)
# for a test drive packaged delai, while we do create a slot to satisfy certain aspects of the backend, it's not 'real'. So we say 'noSlots' until someone has proposed something
noSlots: () ->
@state.booking?.no_slots
processBooking:(booking) ->
booking.neverAccepted = booking.accepter_id?
booking.isCounter = booking.counter_slot? && booking.status != 'canceled' && booking.status != 'suspended'
booking.studentViewing = booking.user_id == context.JK.currentUserId
booking.teacherViewing = !booking.studentViewing
booking.isRequested = booking.status == 'requested' && !booking.isCounter
booking.isCanceled = booking.status == 'canceled'
booking.isSuspended = booking.status == 'suspended'
if booking.isCounter
if booking.counter_slot['is_teacher_created?']
booking.countererId = booking.teacher_id
else
booking.countererId = booking.user_id
selfLastToAct = false
if booking.isRequested
selfLastToAct = booking.studentViewing
else if booking.isCounter
selfLastToAct = booking.countererId == context.JK.currentUserId
else if booking.isCanceled
selfLastToAct = booking.canceler_id == context.JK.currentUserId
else if booking.isSuspended
selfLastToAct = booking.studentViewing
else
selfLastToAct = false
booking.selfLastToAct = selfLastToAct
multipleOptions = false
if booking.neverAccepted
multipleOptions = !(!booking.isCounter && booking.selfLastToAct)
else if booking.isCounter
multipleOptions = !booking.selfLastToAct
else
multipleOptions = false
onlyOption = !multipleOptions
booking.onlyOption = onlyOption
#nextProps.slot_decision = 'counter'
componentWillUpdate: (nextProps, nextState) ->
if nextState.booking?
booking = nextState.booking
if !booking.post_processed
booking.post_processed = true
for slot in booking.slots
@processSlot(slot, booking)
@processSlot(booking.counter_slot, booking)
@processSlot(booking.default_slot, booking)
@processSlot(booking.alt_slot, booking)
2017-07-17 00:38:40 +00:00
if booking.focused_lesson?
@processSlot(booking.focused_lesson.counter_slot, booking)
onlyOption:() ->
#(this.props.initial && !this.props.selfLastToAct )|| !(this.props.counter && !this.props.selfLastToAct)
#@initialRequestSlotsVisible() || !@counteredSlotVisible()
#(this.props.initial && this.props.selfLastToAct ) || !(this.props.counter && !this.props.selfLastToAct)
#(@neverAccepted() && @selfLastToAct()) || !(@isCounter() && !@selfLastToAct())
!@multipleOptions()
multipleOptions: () ->
if @neverAccepted()
!(!@isCounter() && @selfLastToAct())
else if this.props.counter
!@selfLastToAct()
else
false
initialRequestSlotsVisible: () ->
console.log("initialRequestSlotsVisible: " + this.neverAccepted() )
#this.neverAccepted() && this.selfLastToAct()
# is there a counter slot showing
counteredSlotVisible: () ->
console.log("isCounter " + this.isCounter() + ", this.selfLastToAct()" + this.selfLastToAct())
this.isCounter() && !this.selfLastToAct()
counterSlotVisible: () ->
true
getInitialState: () ->
{
user: null,
booking: null,
updating: false,
updatingLesson: false
}
beforeHide: (e) ->
beforeShow: (e) ->
parseId: (id) ->
result = {purpose: null}
bits = id.split('_')
if bits.length == 1
result.id = id
else if bits.length > 1
result.id =bits[0]
result.purpose = bits[1]
else
result.id = id
result
afterShow: (e) ->
parsed = @parseId(e.id)
@setState({updating: true, counterErrors: null, cancelErrors: null, purpose: parsed.purpose})
rest.getLessonBooking({
id: parsed.id,
}).done((response) => @getLessonBookingDone(response)).fail(@app.ajaxError)
2017-07-17 00:38:40 +00:00
hasFocusedLesson: (booking = this.state?.booking) ->
@focusedLesson(booking)?
2017-07-17 00:38:40 +00:00
focusedLesson: (booking = this.state?.booking) ->
booking?.focused_lesson
updateBookingState: (booking) ->
console.log("updating booking state", booking)
2017-07-17 00:38:40 +00:00
slot_update_all = false
counter_slot = @counteredSlot(booking)
if counter_slot?
startSlotDecision = counter_slot.id
slot_update_all = counter_slot['is_recurring?']
else
2016-05-31 13:35:04 +00:00
if booking.accepter_id?
startSlotDecision = 'counter'
else
startSlotDecision = booking.default_slot.id
2017-07-17 00:38:40 +00:00
slot_update_all = booking.default_slot['is_recurring?']
2017-07-17 00:38:40 +00:00
update_all = slot_update_all || !booking.focused_lesson?.id?
if booking.focused_lesson?
#booking.focused_lesson.lesson_booking = booking
@postProcessLesson(booking.focused_lesson)
if booking.next_lesson?
#booking.next_lesson.lesson_booking = booking
@postProcessLesson(booking.next_lesson)
@processBooking(booking)
2016-05-31 13:35:04 +00:00
if booking.onlyOption
# you see two options (accept, and propose new) if it's a counter and you are not the last to act
# the only choice possible in most cases is to propose a new time
2016-05-31 13:35:04 +00:00
#nextState.slot_decision = 'counter'
startSlotDecision = 'counter'
@setState({booking: booking, updating: false, slot_decision: startSlotDecision, updatingLesson: false, update_all: update_all})
getLessonBookingDone: (response) ->
@updateBookingState(response)
toJamClassMain: (e) ->
e.preventDefault()
window.location.href = '/client#/jamclass'
onCancel: () ->
# what to do?
window.location.href = '/client#/jamclass'
onAccept: () ->
@setState({updatingLesson: true, counterErrors: null, cancelErrors: null})
if @state.slot_decision == 'counter'
request = @getSlotData(0)
request.id = this.state.booking.id
request.timezone = window.jstz.determine().name()
request.message = @getMessage()
request.lesson_session_id = @focusedLesson()?.id
rest.counterLessonBooking(request).done((response) => @counterLessonBookingDone(response)).fail((response) => @counterLessonBookingFail(response))
else if @state.slot_decision == 'decline'
request = {}
request.message = @getMessage()
request.id = this.state.booking.id
request.lesson_session_id = @focusedLesson()?.id
rest.cancelLessonBooking(request).done((response) => @cancelLessonBookingDone(response)).fail((response) => @cancelLessonBookingFail(response))
else if @state.slot_decision
request = {}
request.message = @getMessage()
request.id = this.state.booking.id
request.slot = this.state.slot_decision
request.lesson_session_id = @focusedLesson()?.id
rest.acceptLessonBooking(request).done((response) => @acceptLessonBookingDone(response)).fail((response) => @acceptLessonBookingFail(response))
# {"errors":{"lesson_booking_slots":["is invalid"]},"_children":{"lesson_booking_slots":[{"errors":{}},{"errors":{}},{"errors":{"day_of_week":["must be specified"]}}]}}
dayOfWeekMissing: (errors) ->
console.log("errors", errors)
childErrors = errors._children
if childErrors
for key, errorData of childErrors
for slotErrors in errorData
if slotErrors.errors?.day_of_week?
return true
return false
acceptLessonBookingDone: (response ) ->
logger.debug("accept lesson booking done")
@updateBookingState(response)
window.location.href = '/client#/jamclass'
cancelLessonBookingDone: (response ) ->
context.JK.Banner.showNotice("Lesson Canceled", "Your lesson has been canceled.<br/><br/>We've taken you back to the JamClass home page.")
logger.debug("cancel lesson booking done")
@updateBookingState(response)
window.location.href = '/client#/jamclass'
counterLessonBookingDone: (response ) ->
context.JK.Banner.showNotice("Lesson Change Requested", "Your request for a time has been sent.<br/><br/>We've taken you back to the JamClass home page.")
logger.debug("counter lesson booking done")
@updateBookingState(response)
window.location.href = '/client#/jamclass'
counterLessonBookingFail: (jqXHR ) ->
@setState({updatingLesson: false})
logger.debug("counter lesson booking failed")
handled = false
if jqXHR.status == 422
errors = JSON.parse(jqXHR.responseText)
if @dayOfWeekMissing(errors)
handled = true
@setState({counterErrors: {errors: {day_of_week: ["must be specified"]}}})
if !handled
@app.ajaxError(arguments[0], arguments[1], arguments[2])
acceptLessonBookingFail: (response ) ->
@setState({updatingLesson: false})
2016-05-16 16:39:20 +00:00
logger.debug("accept lesson booking failed " + response.responseText)
@app.ajaxError(arguments[0], arguments[1], arguments[2])
cancelLessonBookingFail: (jqXHR) ->
@setState({updatingLesson: false})
logger.debug("cancel lesson booking failed", jqXHR)
handled = false
if jqXHR.status == 422
errors = JSON.parse(jqXHR.responseText)
if errors.errors?.base?
handled = true
window.JK.Banner.showAlert("Unable to Cancel Lesson", errors.errors?.base[0])
if !handled
@app.ajaxError(arguments[0], arguments[1], arguments[2])
getMessage: () ->
@root.find('textarea.message').val()
getSlotData: (position) ->
$slot = @root.find('.slot-' + (position + 1))
picker = $slot.find('.date-picker')
hour = $slot.find('.hour').val()
minute = $slot.find('.minute').val()
am_pm = $slot.find('.am_pm').val()
#update_all = $slot.find('input.update-all').is(':checked') && @isRecurring()
update_all = @state.update_all && @isRecurring()
if hour? and hour != ''
hour = new Number(hour)
if am_pm == 'PM'
hour += 12
else
hour = null
if minute? and minute != ''
minute = new Number(minute)
else
minute = null
if !update_all
date = picker.datepicker("getDate")
if date?
date = context.JK.formatDateYYYYMMDD(date)
else
day_of_week = $slot.find('.day_of_week').val()
{hour: hour, minute: minute, date: date, day_of_week: day_of_week, update_all: update_all}
student: () ->
@state.booking?.user
teacher: () ->
@state.booking?.teacher
otherRole: () ->
if @teacherViewing()
'student'
else
'teacher'
other: () ->
if @teacherViewing()
@student()
else if @studentViewing()
@teacher()
else
null
myself: () ->
if @teacherViewing()
@teacher()
else if @studentViewing()
@student()
else
null
neverAccepted: () ->
!this.state.booking?.accepter_id?
defaultSlot: () ->
@state.booking?.default_slot
2017-07-17 00:38:40 +00:00
counteredSlot: (booking = @state.booking) ->
slot = null
if @hasFocusedLesson(booking)
focused = @focusedLesson(booking)
if focused.status == 'countered'
slot = focused.counter_slot
if !slot?
# only consider the booking slot if it's present and if it's marked is_recurring?
if booking?.counter_slot?['is_recurring?']
slot = booking?.counter_slot
slot
canceler: () ->
if @student().id == this.state.booking?.canceler_id
@student()
else
@teacher()
counterer: () ->
if @counteredSlot()?['is_teacher_created?']
@teacher()
else
@student()
otherCountered: () ->
@myself().id == @counterer().id
adminCanceled: () ->
this.state.booking?.canceled_by_admin?
studentCanceled: () ->
@canceler()?.id == @student().id
selfCanceled: () ->
@canceler()?.id == @myself().id
studentMadeDefaultSlot: () ->
@student()?.id == @defaultSlot()?.proposer_id
teacherViewing: () ->
!@studentViewing()
studentViewing: () ->
@state.booking? && @state.booking.user_id == context.JK.currentUserId
isActive: () ->
@state.booking?.active == true
isRequested: () ->
@state.booking?.status == 'requested' && !@isCounter()
isSuccessful: () ->
@displayableLesson().success
isCounter: () ->
@counteredSlot()? && !@isCanceled() && !@isSuspended()
isInitialCounter: () ->
@isCounter() && !@isActive()
isActiveCounter: () ->
@isCounter() && @isActive()
isCompleted: () ->
if @state.booking?
@displayableLesson().status == 'completed'
else
false
isApproved: () ->
2017-07-10 02:21:29 +00:00
if @hasFocusedLesson()
@focusedLesson().status == 'approved'
else
@state.booking?.status == 'approved'
isCanceled: () ->
2017-07-10 02:21:29 +00:00
cancelled = @state.booking?.status == 'canceled'
if cancelled
# if the booking is canceelled, lessons are done too. No need to check the focused lesson
return true
else
if @hasFocusedLesson()
return @focusedLesson().status == 'canceled'
else
cancelled
isSuspended: () ->
@state.booking?.status == 'suspended'
2018-02-15 04:16:32 +00:00
isUnconfirmed: () ->
@state.booking?.status == 'unconfirmed'
isStudentCountered: () ->
@counteredSlot()?['is_student_created?']
isTeacherCountered: () ->
@counteredSlot()?['is_teacher_created?']
isTestDrive: () ->
@state.booking?.lesson_type == 'test-drive'
isRecurring: (booking = this.state.booking) ->
booking?.recurring
lessonLength: () ->
@state.booking?.lesson_length
lessonDesc: () ->
if @isRecurring()
lessonType = "weekly recurring #{this.lessonLength()}-minute lesson"
else
lessonType = "single #{this.lessonLength()}-minute lesson"
bookedPrice: () ->
price = this.state.booking?.booked_price
if price?
if typeof price == "string"
price = new Number(price)
return price.toFixed(2)
else
return price
lessonPaymentAmt: () ->
console.log("lessonPaymentAmt")
if @state.booking?.payment_style == 'elsewhere'
'$10'
else if @state.booking?.payment_style == 'single'
"$#{this.bookedPrice()}"
else if @state.booking?.payment_style == 'weekly'
"at $#{this.bookedPrice()} per lesson"
else if @state.booking?.payment_style == 'monthly'
"monthly at $#{this.bookedPrice()} per month"
else
"$???"
selfLastToAct: () ->
if @isRequested()
if @isCounter()
@counterer().id == @myself().id
else
@studentViewing()
else if @isCounter()
@counterer().id == @myself().id
else if @isCanceled()
@canceler()?.id == @myself().id
else if @isSuspended()
@studentViewing()
else
false
mySlot: (slot) ->
slot.proposer_id == context.JK.currentUserId
slotsDescription: (defaultSlot, altSlot) ->
text = "Preferred day/time for lesson is #{this.slotTime(defaultSlot)}. Secondary option is #{this.slotTime(altSlot)}."
slotTime: (slot, booking = this.state.booking) ->
2017-07-10 02:21:29 +00:00
if @hasFocusedLesson() || slot.slot_type == 'single' #!@isRecurring(booking)
slot.pretty_start_time
else
"#{this.dayOfWeek(slot)} at #{this.dayTime(slot)}"
slotTimePhrase: (slot) ->
2017-07-10 02:21:29 +00:00
console.log("SLOT", slot)
if slot.slot_type == 'recurring'
# if @isRecurring()
"each " + @slotTime(slot)
else
@slotTime(slot)
slotMessage: (slot, qualifier = '') ->
@messageBlock(slot.mySlot,slot[qualifier + 'message'] )
messageBlock: (selfWroteMessage, message) ->
if typeof selfWroteMessage == 'string'
whoSaid = selfWroteMessage + ' said:'
else if selfWroteMessage
whoSaid = "You said:"
else
whoSaid = "Message from #{this.other().first_name}:"
if message && message.length > 0
description = `<table>
<tbody>
<td className="description">{whoSaid}</td>
<td className="message">{message}</td>
</tbody>
</table>`
description
dayTime: (slot) ->
if slot.hour > 11
hour = slot.hour - 12
if hour == 0
hour = 12
am_pm = 'pm'
else
hour = slot.hour
if hour == 0
hour = 12
am_pm = 'am'
"#{context.JK.padString(hour.toString(), 2)}:#{context.JK.padString(slot.minute.toString(), 2)}#{am_pm} (#{slot.pretty_timezone})"
displayableLesson: () ->
lesson = @focusedLesson()
if !lesson?
lesson = @state.booking.next_lesson
lesson
isStartingSoonOrNow: () ->
# 60 minutes before
startTime = new Date(@displayableLesson().scheduled_start).getTime()
endTime = (startTime + @lessonLength() * 60)
now = new Date().getTime()
now > startTime && now < endTime
isNow: () ->
startTime = new Date(@displayableLesson().scheduled_start).getTime()
endTime = (startTime + @lessonLength() * 60)
now = new Date().getTime()
now > startTime && now < endTime
isPast: () ->
new Date().getTime() > new Date(@displayableLesson().scheduled_start).getTime()
isMissed: () ->
@displayableLesson().missed
sessionLink: () ->
link = "/client#/session/#{this.displayableLesson().music_session_id}"
`<a href={link}>JOIN SESSION</a>`
nextLessonSummaryWithAvatar: () ->
`<div className="row">
{this.userHeader(this.other())}
{this.nextLessonSummary()}
</div>`
nextLessonSummaryRow: () ->
if @isActive()
if @isNow()
data =`<p>You should join this session immediately: {this.sessionLink()}</p>`
else if @isPast()
data =`<p>This lesson is over.</p>`
else
data = `<p>This lesson is scheduled to start at {this.displayableLesson().pretty_scheduled_start}</p>`
else if @isRequested()
data = `<p>This lesson is scheduled to start at {this.displayableLesson().pretty_scheduled_start}</p>`
`<div className="row">
{data}
</div>`
nextLessonSummary: () ->
if @isActive()
if @isNow()
`<p>You should join this session immediately: {this.sessionLink()}</p>`
else if @isPast()
`<p>This lesson is over.</p>`
else
`<p>This lesson is scheduled to start at {this.displayableLesson().pretty_scheduled_start}</p>`
else if @isRequested()
`<p>This lesson is scheduled to start at {this.displayableLesson().pretty_scheduled_start}</p>`
renderCancelLesson: () ->
`<div>
<h3>Cancel this Lesson</h3>
<p>If you would like to cancel this lesson, you have to do so 24 hours in advance.</p>
<a className="button-orange cancel-lesson" onClick={this.onCancelLesson}>CANCEL LESSON</a>
</div>`
dayOfWeek: (slot) ->
switch slot.day_of_week
when 0 then "Sunday"
when 1 then "Monday"
when 2 then "Tuesday"
when 3 then "Wednesday"
when 4 then "Thursday"
when 5 then "Friday"
when 6 then "Saturday"
userHeader: (user) ->
photo_url = user?.photo_url
if !photo_url?
photo_url = '/assets/shared/avatar_generic.png'
if user?
name = user.name
else
name = 'System'
`<div className="user-header">
<div className="avatar">
<img src={photo_url}/>
</div>
<div className="user-name">
{name}
</div>
</div>`
decisionProps: (slots) ->
{
onSlotDecision: this.onSlotDecision,
onUpdateAllDecision: this.onUpdateAllDecision,
initial: this.neverAccepted(),
counter: this.isCounter(),
is_recurring: this.isRecurring(),
slot_decision: this.state.slot_decision,
update_all: this.state.update_all,
slots: slots,
otherRole: this.otherRole(),
onUserDecision: this.onAccept,
onUserCancel: this.onCancel,
disabled: this.state.updatingLesson,
selfLastToAct: this.selfLastToAct(),
counterErrors: this.state.counterErrors,
cancelErrors: this.state.cancelErrors,
focusedLesson: this.focusedLesson(),
noSlots: this.noSlots()
}
render: () ->
if @state.updating
return @renderLoading()
else if @teacherViewing()
return @renderTeacher()
else if @studentViewing()
return @renderStudent()
else
return @renderLoading()
completedHeader: () ->
if @isNow()
header = 'the lesson is scheduled for right now!'
else
if @isMissed()
header = "this lesson was #{this.displayableLesson().displayStatus.toLowerCase()}"
else if @isSuspended()
header = 'this lesson was suspended due to billing issues'
else
header = 'this lesson is over'
approvedHeader: () ->
if @isCompleted()
if @isMissed()
header = "this lesson was #{this.displayableLesson().displayStatus.toLowerCase()}"
else if @isSuspended()
header = 'this lesson was suspended due to billing issues'
else
header = 'this lesson is over'
else if @isNow()
header = 'the lesson is scheduled for right now!'
else if @isPast()
header = 'this lesson is over'
else
header = 'this lesson is coming up soon'
header
renderTeacher: () ->
if @isRequested()
header = 'respond to lesson request'
content = @renderTeacherRequested()
else if @isCounter()
if @isTeacherCountered()
header = 'your proposed alternate day/time is still pending'
else
header = 'student has proposed an alternate day/time'
content = @renderTeacherCountered()
2017-07-17 00:38:40 +00:00
else if @isApproved()
header = @approvedHeader()
content = @renderTeacherApproved()
else if @isCompleted()
header = @completedHeader()
content = @renderTeacherComplete()
else if @isCanceled()
header = "this lesson was #{this.displayableLesson()?.displayStatus?.toLowerCase()}"
content = @renderTeacherCanceled()
else if @isSuspended()
header = 'This lesson has been suspended'
content = @renderTeacherSuspended()
2018-02-15 04:16:32 +00:00
else if @isUnconfirmed()
header = 'This lesson has been automatically canceled'
content = @renderTeacherUnconfirmed()
return `<div className="content-body-scroller">
<Nav/>
<h2>{header}</h2>
{content}
<br className="clearall"/>
</div>`
renderStudent: () ->
if @isRequested()
header = 'your lesson has been requested'
content = @renderStudentRequested()
else if @isCounter()
if @isTeacherCountered()
header = 'teacher has proposed an alternate day/time'
else
header = 'your proposed alternate day/time is still pending'
content = @renderTeacherCountered()
2017-07-17 00:38:40 +00:00
else if @isApproved()
header = @approvedHeader()
content = @renderStudentApproved()
else if @isCompleted()
header = @completedHeader()
content = @renderStudentComplete()
else if @isCanceled()
if @neverAccepted() && @studentViewing() && !@studentCanceled()
header = "we're sorry, but your lesson request has been declined"
else
header = "this lesson was #{this.displayableLesson()?.displayStatus?.toLowerCase()}"
content = @renderStudentCanceled()
2018-02-15 04:16:32 +00:00
else if @isUnconfirmed()
header = 'this lesson has been automatically canceled'
content = @renderStudentUnconfirmed()
else if @isSuspended()
header = 'this lesson has been suspended'
content = @renderStudentSuspended()
`<div className="content-body-scroller">
<Nav/>
<h2>{header}</h2>
{content}
<br className="clearall"/>
</div>`
renderLoading: () ->
header = 'Loading ...'
`<div className="content-body-scroller">
<Nav/>
<h2>{header}</h2>
<br className="clearall"/>
</div>`
renderStudentRequested: () ->
`<div className="contents">
<div className="row request-sent">
{this.userHeader(this.myself())}
Your request has been sent. You will receive an email when {this.teacher().name} responds.
{this.createDetail()}
</div>
<LessonBookingDecision {...this.decisionProps([])} />
</div>`
joinSessionNow: (e) ->
e.preventDefault()
SessionActions.enterSession(@displayableLesson().music_session.id)
updateCreditCard: (e) ->
window.location.href="/client#/account/paymentHistory"
createDetail: () ->
if @hasFocusedLesson() || !@isRecurring()
if @onlyOption() && @rescheduling()
if @noSlots()
detail = `<p className="proposing-new-time no-slot">You are proposing a date/time for this lesson.</p>`
else
detail = `<p className="proposing-new-time">You are proposing to change the date/time of the lesson currently scheduled for {this.slotTime(this.state.booking.default_slot)}</p>`
else
if @noSlots()
detail = `<p className="generic-time-stmt no-slot">Your lesson has no scheduled time yet.</p>`
else
detail = `<p className="generic-time-stmt">Your {this.lessonDesc()} will take place this {this.slotTime(this.state.booking.default_slot)}</p>`
else
if @onlyOption() && @rescheduling()
detail = `<p className="proposing-new-time">You are proposing to change the date/time of the lesson currently scheduled for {this.slotTime(this.state.booking.default_slot)}</p>`
else
detail = `<p className="generic-time-stmt">Your {this.lessonDesc()} will take place each {this.slotTime(this.state.booking.default_slot)}</p>`
detail
rescheduling: () ->
@state.purpose == 'rescheduling'
renderStudentComplete: () ->
@renderStudentApproved()
renderTeacherComplete: () ->
@renderTeacherApproved()
renderStudentApproved: () ->
if @isCompleted()
if @isMissed()
whatNow = null
summary = `<div className="row">
{this.userHeader(this.displayableLesson().missedUser)}
<p>This lesson was missed by {this.displayableLesson().missedRole}.</p>
</div>`
else if @isSuspended()
whatNow = `<div className="row">
<h3>What Now?</h3>
<p>You should update your credit card info. <a onClick={this.updateCreditCard}>update credit card</a></p>
</div>`
else
summary = null
else if @isNow()
if @studentMadeDefaultSlot()
message = this.slotMessage(this.state.booking.default_slot, 'accept')
detail = @createDetail()
summary = `<div className="row">
{this.userHeader(this.teacher())}
<p>Has accepted your lesson request.</p>
{detail}
{message}
</div>`
whatNow = `<div className="row">
<h3>What Now?</h3>
<p>You should join the lesson session as soon as possible. <a onClick={this.joinSessionNow}>join session now</a></p>
{this.nextLessonSummary()}
</div>`
else if @isPast()
if @studentMadeDefaultSlot()
message = this.slotMessage(this.state.booking.default_slot, 'accept')
detail = @createDetail()
summary = `<div className="row">
{this.userHeader(this.teacher())}
<p>Has accepted your lesson request.</p>
{detail}
{message}
</div>`
else
if @studentMadeDefaultSlot()
message = this.slotMessage(this.state.booking.default_slot, 'accept')
detail = @createDetail()
summary = `<div className="row">
{this.userHeader(this.teacher())}
<p>Has accepted your lesson request.</p>
{detail}
{message}
</div>`
decision = `<LessonBookingDecision {...this.decisionProps([])} />`
`<div className="contents">
{summary}
{whatNow}
{decision}
</div>`
renderStudentCanceled: () ->
@renderCanceled()
renderStudentSuspended: () ->
# <p className="description">Message from {this.other().first_name}:</p>
# <div className="message"></div>
2018-02-15 04:16:32 +00:00
renderStudentUnconfirmed: () ->
@renderUnconfirmed()
renderStudentCountered: () ->
@renderCountered()
renderTeacherRequested: () ->
if @isTestDrive()
action = `<p className="action">Has requested a TestDrive {this.lessonLength()}-minute lesson, for which you will be paid $10.</p>`
else
action = `<p className="action">Has requested a {this.lessonDesc()} lesson, for which you will be paid {this.lessonPaymentAmt()}.</p>`
if @noSlots()
slots = []
else
slots = [this.state.booking.default_slot]
if this.state.booking.alt_slot?
slots.push(this.state.booking.alt_slot)
`<div className="contents">
<div className="row">
{this.userHeader(this.other())}
{action}
{this.slotMessage(this.state.booking.default_slot)}
</div>
<LessonBookingDecision {...this.decisionProps(slots)} />
</div>`
renderTeacherApproved: () ->
if @isCompleted()
if @isMissed()
whatNow = null
summary = `<div className="row">
{this.userHeader(this.displayableLesson().missedUser)}
<p>This lesson was missed by {this.displayableLesson().missedRole}.</p>
</div>`
else if @isSuspended()
whatNow = `<div className="row">
<h3>What Now?</h3>
<p>You should update your credit card info. <a onClick={this.updateCreditCard}>update credit card</a></p>
</div>`
else
summary = null
else if @isNow()
if @studentMadeDefaultSlot()
message = this.slotMessage(this.state.booking.default_slot, 'accept')
detail = @createDetail()
summary = `<div className="row">
{this.userHeader(this.student())}
<p>Is ready to take the lesson.</p>
{detail}
{message}
</div>`
whatNow = `<div className="row">
<h3>What Now?</h3>
<p>You should join the lesson session as soon as possible. <a onClick={this.joinSessionNow}>join session now</a></p>
{this.nextLessonSummary()}
</div>`
else if @isPast()
else
if @studentMadeDefaultSlot()
message = this.slotMessage(this.state.booking.default_slot, 'accept')
detail = @createDetail()
summary = `<div className="row">
{this.userHeader(this.teacher())}
<p>Has accepted your lesson request.</p>
{detail}
{message}
</div>`
decision = `<LessonBookingDecision {...this.decisionProps([])} />`
`<div className="contents">
{summary}
{whatNow}
{decision}
</div>`
renderTeacherCanceled: () ->
@renderCanceled()
renderTeacherSuspended: () ->
2018-02-15 04:16:32 +00:00
renderTeacherUnconfirmed: () ->
@renderUnconfirmed()
renderTeacherCountered: () ->
@renderCountered()
2018-02-15 04:16:32 +00:00
renderUnconfirmed: () ->
action = `<p>The JamKazam system has canceled this request because it was never acknowledged after too long of a time.</p>`
renderCanceled: () ->
canceler = @canceler()
myself = @myself()
initial = @neverAccepted()
if initial
if @adminCanceled()
action = `<p>A JamKazam administrator canceled this lesson request.</p>`
else if @studentViewing()
if @studentCanceled()
action = `<p>You canceled this lesson request.</p>`
else
action = `<p>Has declined your lesson request.</p>`
else
if @studentCanceled()
action = `<p>Has canceled this lesson request.</p>`
else
action = `<p>You declined this lesson request.</p>`
2018-02-15 04:16:32 +00:00
if @studentViewing()
if @adminCanceled() || @studentCanceled()
blurb = `<p>We're sorry this scheduling attempt did not working out for you. Please search our community of instructors to find someone else who looks like a good fit for you, and submit a new lesson request</p>`
else
blurb = `<p>We're sorry this instructor has declined your request. Please search our community of instructors to find someone else who looks like a good fit for you, and submit a new lesson request</p>`
whatNow =
`<div className="row">
<h3>What Now?</h3>
{blurb}
<a href="/client#/jamclass/searchOptions" className="search-for-more-teachers">SEARCH INSTRUCTORS NOW</a>
</div>`
cancelerUser = null
if this.adminCanceled()
cancelerUser = 'System'
else
cancelerUser = this.selfCanceled()
`<div className="contents">
<div className="row">
{this.userHeader(canceler)}
{action}
{this.messageBlock(cancelerUser, this.state.booking.cancel_message)}
</div>
{whatNow}
</div>`
renderCountered: () ->
counterer = @counterer()
myself = @myself()
phrase = this.slotTimePhrase(this.counteredSlot())
action = `<p>Has suggested a different time for your lesson.</p>`
detail = `<p className="counter-stmt">Proposed alternate day/time is {phrase}</p>`
`<div className="contents">
<div className="row">
{this.userHeader(counterer)}
{action}
{detail}
{this.slotMessage(this.counteredSlot())}
</div>
2017-07-17 00:38:40 +00:00
<LessonBookingDecision {...this.decisionProps([this.counteredSlot()])} />
</div>`
})