2016-04-21 14:23:29 +00:00
context = window
rest = context . JK . Rest ( )
logger = context . JK . logger
2016-05-19 04:03:22 +00:00
SessionActions = context . SessionActions
2016-04-21 14:23:29 +00:00
UserStore = context . UserStore
2016-05-18 20:18:38 +00:00
LessonTimerStore = context . LessonTimerStore
LessonTimerActions = context . LessonTimerActions
2016-04-21 14:23:29 +00:00
@JamClassScreen = React . createClass ( {
mixins: [
@ ICheckMixin ,
@ PostProcessorMixin ,
Reflux . listenTo ( AppStore , " onAppInit " ) ,
2016-05-18 20:18:38 +00:00
Reflux . listenTo ( UserStore , " onUserChanged " ) ,
Reflux . listenTo ( LessonTimerStore , " onLessonTimersChanged " )
2016-04-21 14:23:29 +00:00
]
2016-05-23 18:22:26 +00:00
lookup: {
name_specified: { name: ' Profile ' , profile: ' ' } ,
experiences_teaching: { name: ' Experience ' , teacher_profile: " experience " } ,
experiences_education: { name: ' Experience ' , teacher_profile: " experience " } ,
experiences_award: { name: ' Experience ' , teacher_profile: " experience " } ,
has_stripe_account: { name: ' Stripe ' , text: " Press the ' Stripe Connect ' button in the bottom-left of the page " } ,
has_teacher_bio: { name: ' Introduction ' , teacher_profile: " introduction " } ,
intro_video: { name: ' Introduction ' , teacher_profile: " introduction " } ,
years_teaching: { name: ' Introduction ' , teacher_profile: " introduction " } ,
years_playing: { name: ' Introduction ' , teacher_profile: " introduction " } ,
instruments_or_subject: { name: ' Basics ' , teacher_profile: " basics " } ,
genres: { name: ' Basics ' , teacher_profile: " basics " } ,
languages: { name: ' Basics ' , teacher_profile: " basics " } ,
teaches_ages_specified: { name: ' Basics ' , teacher_profile: " basics " } ,
2016-04-21 14:23:29 +00:00
teaching_level_specified: { name: ' Basics ' , teacher_profile: " basics " } ,
2016-05-23 18:22:26 +00:00
has_pricing_specified: { name: ' Pricing ' , teacher_profile: " pricing " }
2016-04-21 14:23:29 +00:00
}
2016-05-20 19:31:05 +00:00
needsFetching: false
fetchLessons: () ->
if @ needsFetching
if @ state . user ? . id ?
@needsFetching = false
rest . getLessonSessions ( { as_teacher: @ viewerTeacher ( ) } ) . done ( (response) => @ jamClassLoaded ( response ) ) . fail ( (jqXHR) => @ failedJamClassLoad ( jqXHR ) )
2016-04-21 14:23:29 +00:00
onAppInit: (@app) ->
@ app . bindScreen ( ' jamclass ' ,
{ beforeShow: @ beforeShow , afterShow: @ afterShow , beforeHide: @ beforeHide } )
onUserChanged: (userState) ->
@ setState ( { user: userState ? . user } )
2016-05-18 20:18:38 +00:00
onLessonTimersChanged: (lessons) ->
@ setState ( { lessonTimes: lessons } )
2016-04-21 14:23:29 +00:00
componentDidMount: () ->
@root = $ ( @ getDOMNode ( ) )
2016-05-18 20:18:38 +00:00
componentWillUpdate: (nextProps, nextState) ->
# associate time info from LessonTimerStore with our lesson info
if nextState . lessonTimes ? && nextState . lesson_sessions ? . entries ?
for lesson in nextState . lesson_sessions . entries
lessonWithTime = nextState . lessonTimes [ lesson . id ]
if lessonWithTime ?
lesson.times = lessonWithTime . times
2016-04-21 14:23:29 +00:00
componentDidUpdate: () ->
2016-05-20 19:31:05 +00:00
@ fetchLessons ( )
2016-04-21 14:23:29 +00:00
items = @ root . find ( ' .jamtable tbody td.actionsColumn .lesson-session-actions-btn ' )
$ . each ( items , (i, node) => (
$node = $ ( node )
lesson = @ findLesson ( $node . attr ( ' data-lesson-id ' ) )
2016-05-24 22:31:14 +00:00
$node . lessonSessionActions ( lesson ) . off ( context . JK . EVENTS . LESSON_SESSION_ACTION ) . on ( context . JK . EVENTS . LESSON_SESSION_ACTION , @ lessonSessionActionSelected )
2016-04-21 14:23:29 +00:00
) )
2016-05-18 01:52:25 +00:00
context . JK . popExternalLinks ( @ root )
2016-04-21 14:23:29 +00:00
lessonSessionActionSelected: (e, data) ->
lessonId = data . options . id
lesson = @ findLesson ( lessonId )
if data . lessonAction == ' status '
# show the status of the lesson
window . location.href = ' /client # /jamclass/lesson-booking/ ' + lessonId
else if data . lessonAction == ' messages '
@ app . layout . showDialog ( ' chat-dialog ' , { d1: ' lesson_ ' + lessonId } )
else if data . lessonAction == ' cancel '
@ cancelLesson ( lesson )
2016-05-23 18:22:26 +00:00
# @@app.layout.showDialog('cancel-lesson-dialog', {d1: lessonId})
2016-04-21 14:23:29 +00:00
else if data . lessonAction == ' join '
2016-05-19 04:03:22 +00:00
SessionActions . enterSession ( lesson . music_session . id )
2016-04-21 14:23:29 +00:00
else if data . lessonAction == ' reschedule '
@ rescheduleLesson ( lesson )
2016-05-25 20:26:45 +00:00
else if data . lessonAction == ' attach-recording '
2018-01-16 20:27:20 +00:00
window . AttachmentActions . startAttachRecording . trigger ( lesson . id )
2016-05-25 20:26:45 +00:00
else if data . lessonAction == ' attach-notation '
2018-01-16 20:27:20 +00:00
window . AttachmentActions . startAttachNotation . trigger ( lesson . id )
2016-05-25 20:26:45 +00:00
else if data . lessonAction == ' attach-audio '
2018-01-16 20:27:20 +00:00
window . AttachmentActions . startAttachAudio . trigger ( lesson . id )
2016-04-21 14:23:29 +00:00
else if data . lessonAction == ' start-5-min '
2016-05-23 18:22:26 +00:00
rest . lessonStartTime ( { id: lessonId , minutes: 5 } ) . done ( (response) => ( @ app . layout . notify ( {
title: ' Start Time Set ' ,
text: " Start time for session set to 5 mins from now "
} ) ) )
2016-05-26 23:10:05 +00:00
else if data . lessonAction == ' start-65-ago '
2016-05-23 18:22:26 +00:00
rest . lessonStartTime ( {
id: lessonId ,
2016-05-26 23:10:05 +00:00
minutes: - 65
2016-05-23 18:22:26 +00:00
} ) . done ( (response) => ( @ app . layout . notify ( {
title: ' Start Time Set ' ,
2016-05-26 23:10:05 +00:00
text: " Start time for session set to 65 mins ago "
2016-05-23 18:22:26 +00:00
} ) ) )
2016-04-21 14:23:29 +00:00
else if data . lessonAction == ' enter-payment '
2016-06-03 04:32:09 +00:00
if lesson . lesson_booking . test_drive_package_choice_id ?
window . location.href = " /client # /jamclass/lesson-payment/package_ #{ lesson . lesson_booking . test_drive_package_choice_id } "
else
window . location.href = " /client # /jamclass/lesson-payment/lesson-booking_ #{ lessonId } "
2016-04-21 14:23:29 +00:00
else
context . JK . showAlert ( ' unknown lesson action ' , ' The option in the menu is unknown ' )
findLesson: (lessonId) ->
for lesson in @ lessons ( )
if lessonId == lesson . id
return lesson
return null
rescheduleSelected: (lesson, recurring) ->
rest . checkLessonReschedule ( { id: lesson . id , update_all: recurring } )
. done ( (response) => (
if recurring
2016-05-30 21:43:55 +00:00
window . location.href = ' /client # /jamclass/lesson-booking/ ' + lesson . lesson_booking_id + " _rescheduling "
2016-04-21 14:23:29 +00:00
else
2016-05-30 21:43:55 +00:00
window . location.href = ' /client # /jamclass/lesson-booking/ ' + lesson . id + " _rescheduling "
2016-04-21 14:23:29 +00:00
) )
. fail ( (jqXHR) => (
if jqXHR . status == 422
if recurring
if @ viewerStudent ( )
2016-05-23 18:22:26 +00:00
context . JK . Banner . showAlert ( " Policy Issue " ,
2017-07-17 00:38:40 +00:00
" <p>We’ re sorry, but you cannot reschedule this recurring lesson right now because it is less than 24 hours before the lesson start time.<br/></br>This is not allowed in the <a href= \" /corp/terms \" target= \" _blank \" >terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost. You may reschedule this recurring lesson anytime starting from the end of this next scheduled lesson, so please plan to do it then.</p> " )
2016-04-21 14:23:29 +00:00
else
2016-05-23 18:22:26 +00:00
context . JK . Banner . showAlert ( " Policy Issue " ,
2017-07-17 00:38:40 +00:00
" <p>We’ re sorry, but you cannot reschedule this recurring lesson right now because it is less than 24 hours before the lesson start time.<br/></br>This is not allowed in the <a href= \" /corp/terms \" target= \" _blank \" >terms of service</a>. You may reschedule this recurring lesson anytime starting from the end of this next scheduled lesson, so please plan to do it then.</p> " )
2016-04-21 14:23:29 +00:00
else
if @ viewerStudent ( )
2016-05-23 18:22:26 +00:00
context . JK . Banner . showAlert ( " Policy Issue " ,
2017-07-17 00:38:40 +00:00
" <p>We’ re sorry, but you cannot reschedule a lesson less than 24 hours before the lesson start time.<br/></br>This is not allowed in the <a href= \" /corp/terms \" target= \" _blank \" >terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.</p> " )
2016-04-21 14:23:29 +00:00
else
2016-05-23 18:22:26 +00:00
context . JK . Banner . showAlert ( " Policy Issue " ,
2017-07-17 00:38:40 +00:00
" <p>We’ re sorry, but you cannot reschedule a lesson less than 24 hours before the lesson start time.<br/></br>This is not allowed in the <a href= \" /corp/terms \" target= \" _blank \" >terms of service</a>.</p> " )
2016-04-21 14:23:29 +00:00
else
@ app . ajaxError ( jqXHR )
) )
refreshLesson: (lessonId) ->
rest . getLesson ( { id: lessonId } ) . done ( (response) => @ refreshLessonDone ( response ) ) . fail ( (jqXHR) => @ refreshLessonFail ( jqXHR ) )
refreshLessonDone: (lesson_session) ->
@ updateLessonState ( lesson_session )
refreshLessonFail: (jqXHR) ->
@ app . ajaxError ( jqXHR )
issueCancelLesson: (lesson, update_all) ->
request = { }
request.message = ' '
request.id = lesson . lesson_booking_id
request.lesson_session_id = lesson . id
request.update_all = update_all
2016-05-23 18:22:26 +00:00
rest . cancelLessonBooking ( request ) . done ( (response) => @ cancelLessonBookingDone ( response ,
lesson ) ) . fail ( (response) => @ cancelLessonBookingFail ( response ) )
2016-04-21 14:23:29 +00:00
cancelLessonBookingDone: (booking, lesson) ->
if booking . focused_lesson . teacher_short_canceled
if @ teacherViewing ( )
2016-05-23 18:22:26 +00:00
context . JK . Banner . showAlert ( ' late cancellation warning ' ,
' Cancelling a lesson less than 24 hours before it’ s scheduled to start should be avoided, as it’ s an inconvenience to the student. Repeated violations of this policy will negatively affect your teacher score. ' )
2016-04-21 14:23:29 +00:00
2016-05-30 21:43:55 +00:00
lessonsFromBooking = [ ]
for check in @ lessons ( )
if check . lesson_booking_id == lesson . lesson_booking_id
lessonsFromBooking . push ( check )
for check in lessonsFromBooking
@ refreshLesson ( check . id )
2016-04-21 14:23:29 +00:00
cancelLessonBookingFail: (jqXHR) ->
@ app . ajaxError ( jqXHR )
2017-07-17 00:38:40 +00:00
cancelSelected: (lesson, update_all) ->
rest . checkLessonCancel ( { id: lesson . id , update_all: update_all } )
. done ( (response) => @ issueCancelLesson ( lesson , update_all ) )
. fail ( (jqXHR) => @ cancelSelectedFail ( jqXHR , lesson , update_all ) )
2016-04-21 14:23:29 +00:00
2017-07-17 00:38:40 +00:00
cancelSelectedFail: (jqXHR, lesson, update_all) ->
2016-04-21 14:23:29 +00:00
if jqXHR . status == 422
2017-07-17 00:38:40 +00:00
if lesson . recurring && update_all
2016-04-21 14:23:29 +00:00
if @ viewerStudent ( )
buttons = [ ]
buttons . push ( { name: ' CLOSE ' , buttonStyle: ' button-grey ' } )
2016-05-23 18:22:26 +00:00
buttons . push ( {
name: ' CANCEL RECURRING LESSONS ' ,
buttonStyle: ' button-orange ' ,
click: ( () => ( @ issueCancelLesson ( lesson , true ) ) )
} )
context . JK . Banner . show ( {
title: " Policy Issue " ,
2017-07-17 00:38:40 +00:00
html: " You may cancel this recurring series of lessons, but it is too late to cancel the next scheduled lesson because it is less than 24 hours before the lesson start time.<br/><br/>This is not allowed in the <a href= \" /corp/terms \" target= \" _blank \" >terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost. " ,
2016-05-23 18:22:26 +00:00
buttons: buttons
} )
2016-04-21 14:23:29 +00:00
else
# path should not be taken
2016-05-23 18:22:26 +00:00
context . JK . Banner . showAlert ( " Policy Issue " ,
2017-07-17 00:38:40 +00:00
" <p>We’ re sorry, but you cannot cancel a lesson less than 24 hours before the lesson start time.<br/><br/>This is not allowed in the <a href= \" /corp/terms \" target= \" _blank \" >terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.</p> " )
2016-04-21 14:23:29 +00:00
else
if @ viewerStudent ( )
2016-05-23 18:22:26 +00:00
context . JK . Banner . showAlert ( " Policy Issue " ,
2017-07-17 00:38:40 +00:00
" <p>We’ re sorry, but you cannot cancel a lesson less than 24 hours before the lesson start time.<br/><br/>This is not allowed in the <a href= \" /corp/terms \" target= \" _blank \" >terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.</p> " )
2016-04-21 14:23:29 +00:00
else
# path should not be taken
2016-05-23 18:22:26 +00:00
context . JK . Banner . showAlert ( " Policy Issue " ,
2017-07-17 00:38:40 +00:00
" <p>We’ re sorry, but you cannot cancel a lesson less than 24 hours before the lesson start time.<br/><br/>This is not allowed in the <a href= \" /corp/terms \" target= \" _blank \" >terms of service</a>.</p> " )
2016-04-21 14:23:29 +00:00
else
@ app . ajaxError ( jqXHR )
rescheduleLesson: (lesson) ->
if lesson . recurring
buttons = [ ]
2017-07-10 02:21:29 +00:00
buttons . push ( {
name: ' CANCEL ' ,
buttonStyle: ' button-grey ' ,
click: ( () => ( logger . debug ( " cancelling out of reschedule dialog " ) ) )
} )
2016-05-23 18:22:26 +00:00
buttons . push ( {
2016-05-30 21:43:55 +00:00
name: ' THIS LESSON ' ,
2016-05-23 18:22:26 +00:00
buttonStyle: ' button-orange ' ,
click: ( () => ( @ rescheduleSelected ( lesson , false ) ) )
} )
buttons . push ( {
2016-05-30 21:43:55 +00:00
name: ' ALL LESSONS ' ,
2016-05-23 18:22:26 +00:00
buttonStyle: ' button-orange ' ,
click: ( () => ( @ rescheduleSelected ( lesson , true ) ) )
} )
context . JK . Banner . show ( {
title: ' Rescheduling Selection ' ,
html: ' Do you wish to all reschedule all lessons or just the one selected? ' ,
buttons: buttons
} )
2016-04-21 14:23:29 +00:00
else
@ rescheduleSelected ( lesson , false )
cancelLesson: (lesson) ->
2016-05-27 01:32:58 +00:00
if lesson . isRequested && @ viewerTeacher ( )
2016-04-21 14:23:29 +00:00
confirmTitle = ' Confirm Decline '
verbLower = ' decline '
else
confirmTitle = ' Confirm Cancelation '
verbLower = ' cancel '
2017-07-17 00:38:40 +00:00
if ! lesson . isRequested && lesson . recurring
2016-04-21 14:23:29 +00:00
buttons = [ ]
2016-05-30 21:43:55 +00:00
buttons . push ( { name: ' CLOSE ' , buttonStyle: ' button-grey ' } )
2016-05-23 18:22:26 +00:00
buttons . push ( {
2016-05-30 21:43:55 +00:00
name: ' CANCEL THIS LESSON ' ,
2016-05-23 18:22:26 +00:00
buttonStyle: ' button-orange ' ,
click: ( () => ( @ cancelSelected ( lesson , false ) ) )
} )
2016-05-30 21:43:55 +00:00
buttons . push ( { name: ' CANCEL ALL LESSONS ' , buttonStyle: ' button-orange ' , click: ( () => ( @ cancelSelected ( lesson , true ) ) ) } )
2016-05-23 18:22:26 +00:00
context . JK . Banner . show ( {
title: ' Select One ' ,
html: " Do you wish to all #{ verbLower } all lessons or just the one selected? " ,
buttons: buttons
} )
2016-04-21 14:23:29 +00:00
else
2016-05-23 18:22:26 +00:00
context . JK . Banner . showYesNo ( {
title: confirmTitle ,
html: " Are you sure you want to #{ verbLower } this lesson? " ,
yes : () => ( @ cancelSelected ( lesson , lesson . recurring ) )
} )
2016-04-21 14:23:29 +00:00
getInitialState: () ->
{
user: null ,
}
beforeHide: (e) ->
beforeShow: (e) ->
afterShow: (e) ->
@ checkStripeSuccessReturn ( )
@ setState ( { updating: true } )
2016-05-20 19:31:05 +00:00
@needsFetching = true
@ fetchLessons ( )
2016-04-21 14:23:29 +00:00
checkStripeSuccessReturn: () ->
if $ . QueryString [ ' stripe-success ' ] ?
if $ . QueryString [ ' stripe-success ' ] == ' true '
2016-05-23 18:22:26 +00:00
context . JK . Banner . showNotice ( ' stripe connected ' ,
' Congratulations, you have successfully connected your Stripe account, so payments for student lessons can now be processed. ' )
2016-04-21 14:23:29 +00:00
if window . history . replaceState #ie9 proofing
window . history . replaceState ( { } , " " , " /client # /jamclass " )
resetState: () ->
@ setState ( { updating: false , lesson: null } )
jamClassLoaded: (response) ->
@ setState ( { updating: false } )
@ postProcess ( response )
2016-05-18 20:18:38 +00:00
LessonTimerActions . loadLessons ( response )
2016-04-21 14:23:29 +00:00
@ setState ( { lesson_sessions: response } )
failedJamClassLoad: (jqXHR) ->
@ setState ( { updating: false } )
if jqXHR . status == 404
@ app . layout . notify ( { title: " Unable to load JamClass info " , text: " Try refreshing the web page " } )
lessons: () ->
if @ state . lesson_sessions ?
@ state . lesson_sessions . entries
else
[ ]
postProcess: (data) ->
for lesson in data . entries
# calculate:
# .other (user object),
# .me (user object),
# other/me.musician_profile (link to musician profile)
# other/me.resolved_photo_url
# .hasUnreadMessages
# .isRequested (doesn't matter if countered or not). but can't be done
# .isScheduled (doesn't matter if countered or not).
@ postProcessLesson ( lesson )
onReadMessage: (lesson_session, e) ->
e . preventDefault ( )
data = { id: lesson_session . id }
data [ " #{ this . myRole ( ) } _unread_messages " ] = false
rest . updateLessonSessionUnreadMessages ( data ) . done ( (response) => @ updatedLessonSessionReadDone ( response ) ) . fail ( (jqXHR) => @ updatedLessonSessionReadFail ( jqXHR ) )
updateLessonState: (lesson_session) ->
@ postProcessLesson ( lesson_session )
for lesson in @ lessons ( )
if lesson . id == lesson_session . id
$ . extend ( lesson , lesson_session )
@ setState ( { lesson_sessions: this . state . lesson_sessions } )
updatedLessonSessionReadDone: (lesson_session) ->
# update lesson session data in local state
@ updateLessonState ( lesson_session )
2016-05-20 15:31:43 +00:00
# if this is a not-confirmed lesson, send them to the view statu screen
if lesson_session . isRequested
2016-05-20 19:31:05 +00:00
window . location.href = ' /client # /jamclass/lesson-booking/ ' + lesson_session . id
2016-05-20 15:31:43 +00:00
else
@ app . layout . showDialog ( ' chat-dialog ' , { d1: ' lesson_ ' + lesson_session . id } )
2016-04-21 14:23:29 +00:00
updatedLessonSessionReadFail: (jqXHR) ->
@ app . ajaxError ( jqXHR )
openMenu: (lesson, e) ->
$this = $ ( e . target )
if ! $this . is ( ' .lesson-session-actions-btn ' )
$this = $this . closest ( ' .lesson-session-actions-btn ' )
$this . btOn ( )
constructMissingLinks: (user) ->
links = [ ]
matches = { }
2016-04-26 03:01:15 +00:00
if user . teacher ?
for problem , isPresent of user . teacher . profile_pct_summary
data = @ lookup [ problem ]
if data ? && ! isPresent
matches [ data . name ] = data
for name , data of matches
if ! data . text ?
2016-05-23 18:22:26 +00:00
links . push ( ` < a key = { data . name } className = " missing-profile "
onClick = { this . missingProfileClick . bind ( this , data ) } > { data . name } < / a > ` )
2016-04-26 03:01:15 +00:00
for name , data of matches
if data . text ?
2016-05-23 18:22:26 +00:00
links . push ( ` < a key = { data . name } onClick = { this . onProfileHelp . bind ( this , data ) }
className = " missing-profile " > { data . name } < / a > ` )
2016-04-26 03:01:15 +00:00
` < ul className = " missing-profile-list " > { links } < / ul > `
else
null
2016-04-21 14:23:29 +00:00
onProfileHelp: (data, e) ->
e . preventDefault ( )
@ app . layout . notify ( { title: data . name , text: data . text } )
missingProfileClick: (data, e) ->
if data . profile ?
window . ProfileActions . startProfileEdit ( data . profile , true )
else if data . teacher_profile ?
window . ProfileActions . startTeacherEdit ( data . teacher_profile , true )
else
throw " unknown type in data " + JSON . stringify ( data )
viewTeacherProfile: (e) ->
e . preventDefault ( )
window . ProfileActions . viewTeacherProfile ( this . state . user , ' /client # /jamclass ' , ' BACK TO JAMCLASS HOME ' )
2016-05-19 01:43:07 +00:00
joinLessonNow: (lesson, e) ->
e . preventDefault ( ) ;
2016-05-19 04:03:22 +00:00
SessionActions . enterSession ( lesson . music_session . id )
2016-04-21 14:23:29 +00:00
render: () ->
disabled = @ state . updating
if ! @ state . user ? . id
return ` < div > Loading < / div > `
if @ viewerStudent ( )
searchTeachers = ` < div className = " search-teachers " >
< h2 > search teachers < / h2 >
< p > JamClass instructors are each individually screened to ensure that they are highly qualified music
teachers ,
2016-05-18 01:52:25 +00:00
and are equipped with the right gear to teach effectively online .
2016-04-21 14:23:29 +00:00
< / p >
< div className = " actions " >
2016-05-19 01:49:57 +00:00
< a href = " /client # /jamclass/searchOptions " className = " button-orange " > SEARCH TEACHERS < / a >
2016-04-21 14:23:29 +00:00
< / div >
< / div > `
2016-04-27 03:22:49 +00:00
if @ state . user ? [ ' can_buy_test_drive? ' ]
2016-05-23 18:22:26 +00:00
rightContent = ` < div className = " jamclass-section student-right-content " >
2016-04-21 14:23:29 +00:00
2016-04-27 03:22:49 +00:00
< p className = " test-drive-main " >
2016-05-23 18:24:20 +00:00
JamClass is the best way to take online music lessons .
2016-04-27 03:22:49 +00:00
< / p >
2016-05-23 18:22:26 +00:00
< ul >
< li > Connect with the best teacher for you vs . the closest < / li >
< li > TestDrive multiple teachers to find your ideal match < / li >
< li > Avoid the time and hassle of travel to / from lessons < / li >
< li > Enjoy studio quality audio in lessons < / li >
< li > Play live in sync with your teacher in lesson sessions < / li >
< li > Record lessons to refer back to them any time < / li >
< / ul >
< p > TestDrive lets you try : < / p >
< ul >
< li > 4 teachers for just $12 . 50 each , or
< / li >
< li > 2 teachers for just $14 . 99 each , or
< / li >
< li > 1 teacher for just $14 . 99
< / li >
< / ul >
< p > To get started , click the Search Teachers button to the left . When you find a teacher you like , click the Book TestDrive Lesson button , and follow the on - screen instructions to choose the 4 - , 2 - , or 1 - teacher offer . < / p >
2016-04-27 03:22:49 +00:00
< / div > `
else
rightContent = ` < div className = " jamclass-section " >
2016-05-23 18:22:26 +00:00
< p > Read our < a
href = " https://jamkazam.desk.com/customer/en/portal/topics/926073-jamclass-online-music-lessons---for-students/articles "
rel = " external " > JamClass user guide for students < / a > to learn how to get the most out of your online lessons !
< / p >
< p > If you have any problems , please email us at < a href = " mailto:support@jamkazam.com " > support @ jamkazam . com < / a > .
We ' re here to help make your lessons a great experience.</p>
< / div > `
2016-04-21 14:23:29 +00:00
else
searchTeachers = ` < div className = " search-teachers " >
< h2 > stripe status < / h2 >
2016-05-23 18:22:26 +00:00
2016-04-21 14:23:29 +00:00
< div className = " field stripe-connect " >
< StripeConnect purpose = ' jamclass-home ' user = { this . state . user } / >
< / div >
< / div > `
if this . state . user ?
teacherProfileUri = " /client # /profile/teacher/ #{ this . state . user . id } "
pct = Math . round ( this . state . user . teacher ? . profile_pct )
2016-04-26 03:01:15 +00:00
if ! pct ?
pct = 0
2016-04-21 14:23:29 +00:00
if pct == 100
pctCompleteMsg = ` < p className = " pct-complete " > Your teacher profile is { pct } % complete . < / p > `
else
2016-05-23 18:22:26 +00:00
pctCompleteMsg = ` < p className = " pct-complete " > Your teacher profile is { pct } % complete . The following sections
of your profile are missing information . Click any of these links to view and add missing information : < / p > `
2016-04-21 14:23:29 +00:00
missingLinks = @ constructMissingLinks ( this . state . user )
2016-04-27 03:22:49 +00:00
rightContent = ` < div className = " jamclass-section " >
2016-04-21 14:23:29 +00:00
{ pctCompleteMsg }
{ missingLinks }
< a className = " button-orange view-teacher-profile " onClick = { this . viewTeacherProfile } > VIEW TEACHER PROFILE < / a >
2016-05-23 18:22:26 +00:00
2016-04-27 03:22:49 +00:00
< p >
2016-05-23 18:22:26 +00:00
Read our < a
href = " https://jamkazam.desk.com/customer/en/portal/topics/926076-jamclass-online-music-lessons---for-teachers/articles "
rel = " external " > JamClass user guide for teachers < / a > to learn how to get the most out of the JamClass
technology and marketplace .
2016-04-27 03:22:49 +00:00
< / p >
2016-05-23 18:22:26 +00:00
2016-04-27 03:22:49 +00:00
< p >
2016-05-23 18:22:26 +00:00
If you have any problems , please email us < a href = " mailto:support@jamkazam.com " rel = " external " > support @ jamkazam . com < / a > .
We ' re here to help you build your lesson business.
< / p >
2016-04-21 14:23:29 +00:00
< / div > `
classes = [ ]
if @ state . updating
classes = [ ` < tr key = " loading " >
< td className = " loading " colSpan = " 5 " > Loading . . . < / td >
< / tr > ` ]
else
for lessonData in @ lessons ( )
if lessonData . hasUnreadMessages
2016-05-23 18:22:26 +00:00
unreadMessages = ` < a onClick = { this . onReadMessage . bind ( this , lessonData ) } > < img
src = " /assets/content/icon_unread_mail.png " / > < / a > `
2016-04-21 14:23:29 +00:00
else
unreadMessages = null
2016-05-18 20:18:38 +00:00
2016-06-03 04:32:09 +00:00
if lessonData . lesson_booking . no_slots
timeStmt = ' No time has been scheduled yet '
else if lessonData . status == ' countered '
2016-05-30 21:43:55 +00:00
timeStmt = lessonData . counter_slot . pretty_scheduled_start_with_timezone
else
timeStmt = lessonData . music_session . pretty_scheduled_start_with_timezone
2016-05-18 20:18:38 +00:00
2016-05-19 01:43:07 +00:00
if lessonData . times ? && lessonData . displayStatus == ' Scheduled '
2016-05-18 20:18:38 +00:00
if lessonData . times . startingSoon
2016-05-24 22:31:14 +00:00
if lessonData . times . until . minutes == 0
timeDesc = " Starts in less than a minute "
else
timeDesc = " Starts in #{ lessonData . times . until . minutes } minutes. "
2017-07-17 00:38:40 +00:00
timeStmt = ` < span > { timeDesc } < br / > < a
2016-05-23 18:22:26 +00:00
onClick = { this . joinLessonNow . bind ( this , lessonData ) } > join lesson now < / a > < / span > `
2016-05-24 20:19:11 +00:00
else if lessonData . times . inThePast
2016-05-18 20:18:38 +00:00
minutes = - lessonData . times . until . minutes
2016-05-19 04:03:22 +00:00
if minutes == 1 || minutes == 0
2016-05-23 18:22:26 +00:00
timeStmt = ` < span > This lesson just started . < a onClick = { this . joinLessonNow . bind ( this , lessonData ) } > join
lesson now < / a > < / span > `
2016-05-18 20:18:38 +00:00
else
2016-05-23 18:22:26 +00:00
timeStmt = ` < span > Started { minutes } minutes ago . < a onClick = { this . joinLessonNow . bind ( this , lessonData ) } > join
lesson now < / a > < / span > `
2016-05-19 01:43:07 +00:00
2016-04-21 14:23:29 +00:00
lesson = ` < tr key = { lessonData . id } className = " lesson-session " data - lesson - session - id = { lessonData . id } >
2016-05-23 18:22:26 +00:00
< td className = " userColumn " >
< div className = " avatar " > < img src = { lessonData . other . resolved_photo_url } / > < / div >
< a href = { lessonData . other . best_profile } > < span
className = " first_name " > { lessonData . other . first_name } < /span><br/ > < span
className = " last_name " > { lessonData . other . last_name } < / span > < / a > < / td >
2016-05-18 20:18:38 +00:00
< td className = " startTimeColumn " > { timeStmt } < / td >
2016-04-21 14:23:29 +00:00
< td className = " displayStatusColumn " > { lessonData . displayStatus } < / td >
< td className = " unreadColumn " > { unreadMessages } < / td >
2016-05-23 18:22:26 +00:00
< td className = " actionsColumn " > < a data - lesson - id = { lessonData . id } className = " lesson-session-actions-btn "
onClick = { this . openMenu . bind ( this , lessonData ) } > menu
< div className = " details-arrow arrow-down " / >
< / a > < / td >
2016-04-21 14:23:29 +00:00
< / tr > `
classes . push ( lesson )
if classes . length == 0
classes = [ ` < tr key = " none " >
< td className = " none " colSpan = " 5 " > No Lessons Yet < / td >
< / tr > ` ]
` < div className = " content-body-scroller " >
< div className = " column column-left " >
< h2 > my lessons < / h2 >
2016-05-25 20:26:45 +00:00
< AttachmentStatus / >
2016-04-21 14:23:29 +00:00
< div className = " my-lessons jamclass-section " >
< table className = " jamtable " >
< thead >
< tr >
< th className = " role userColumn " > { this . otherRole ( ) } < / th >
< th className = " startTimeColumn " > DATE / TIME < / th >
< th className = " displayStatusColumn " > STATUS < / th >
< th className = " unreadColumn " > < / th >
< th className = " actionsColumn " > ACTIONS < / th >
< / tr >
< / thead >
< tbody >
{ classes }
< / tbody >
< / table >
< div style = { { display : ' none ' } } className = " calender-integration-notice " >
Don ' t miss a lesson! <a>Integrate your lessons into your calendar.</a>
< / div >
< / div >
{ searchTeachers }
< / div >
< div className = " column column-right " >
2016-05-23 18:22:26 +00:00
{ rightContent }
2016-04-21 14:23:29 +00:00
< / div >
< br className = " clearall " / >
< / div > `
viewerStudent: () ->
! @ viewerTeacher ( )
viewerTeacher: () ->
this . state . user ? . is_a_teacher
myRole: () ->
if @ viewerStudent ( )
' student '
else
' teacher '
otherRole: () ->
if @ viewerStudent ( )
' teacher '
else
' student '
} )