2016-04-06 02:23:15 +00:00
context = window
rest = context . JK . Rest ( )
logger = context . JK . logger
AppStore = context . AppStore
SchoolActions = context . SchoolActions
SchoolStore = context . SchoolStore
UserStore = context . UserStore
profileUtils = context . JK . ProfileUtils
@AccountSchoolScreen = React . createClass ( {
mixins: [
ICheckMixin ,
Reflux . listenTo ( AppStore , " onAppInit " ) ,
Reflux . listenTo ( SchoolStore , " onSchoolChanged " )
Reflux . listenTo ( UserStore , " onUserChanged " )
]
shownOnce: false
screenVisible: false
TILE_ACCOUNT: ' account '
TILE_MEMBERS: ' members '
TILE_EARNINGS: ' earnings '
TILE_AGREEMENT: ' agreement '
TILES: [ ' account ' , ' members ' , ' earnings ' , ' agreement ' ]
onAppInit: (@app) ->
@ app . bindScreen ( ' account/school ' , { beforeShow: @ beforeShow , afterShow: @ afterShow , beforeHide: @ beforeHide } )
onSchoolChanged: (schoolState) ->
@ setState ( schoolState )
onUserChanged: (userState) ->
@ noSchoolCheck ( userState ? . user )
@ setState ( { user: userState ? . user } )
componentDidMount: () ->
@checkboxes = [ { selector: ' input.slot-decision ' , stateKey: ' slot-decision ' } ]
@root = $ ( @ getDOMNode ( ) )
@ iCheckify ( )
componentDidUpdate: () ->
@ iCheckify ( )
checkboxChanged: (e) ->
checked = $ ( e . target ) . is ( ' :checked ' )
value = $ ( e . target ) . val ( )
@ setState ( { userSchedulingComm: value } )
beforeHide: (e) ->
#ProfileActions.viewTeacherProfileDone()
@screenVisible = false
2016-09-09 18:17:46 +00:00
return true
2016-04-06 02:23:15 +00:00
beforeShow: (e) ->
noSchoolCheck: (user) ->
if user ? . id ? && @ screenVisible
if ! user . owned_school_id ?
window . JK . Banner . showAlert ( " You are not the owner of a school in our systems. If you are, please contact support@jamkazam.com and we ' ll update your account. " )
return false
else
if ! @ shownOnce
@shownOnce = true
SchoolActions . refresh ( user . owned_school_id )
return true
else
return false
afterShow: (e) ->
@screenVisible = true
logger . debug ( " AccountSchoolScreen: afterShow " )
logger . debug ( " after show " , @ state . user )
@ noSchoolCheck ( @ state . user )
getInitialState: () ->
{
school: null ,
user: null ,
selected: ' account ' ,
userSchedulingComm: null ,
updateErrors: null ,
schoolName: null ,
studentInvitations: null ,
teacherInvitations: null ,
2016-09-08 10:59:58 +00:00
updating: false ,
distributions: [ ]
2016-04-06 02:23:15 +00:00
}
isSchoolManaged: () ->
if this . state . userSchedulingComm ?
this . state . userSchedulingComm == ' school '
else
this . state . school . scheduling_communication == ' school '
nameValue: () ->
if this . state . schoolName ?
this . state . schoolName
else
this . state . school . name
nameChanged: (e) ->
$target = $ ( e . target )
val = $target . val ( )
@ setState ( { schoolName: val } )
onCancel: (e) ->
e . preventDefault ( )
context.location.href = ' /client # /account '
onUpdate: (e) ->
e . preventDefault ( )
if this . state . updating
return
name = @ root . find ( ' input[name= " name " ] ' ) . val ( )
if @ isSchoolManaged ( )
scheduling_communication = ' school '
else
scheduling_communication = ' teacher '
correspondence_email = @ root . find ( ' input[name= " correspondence_email " ] ' ) . val ( )
@ setState ( updating: true )
rest . updateSchool ( {
id: this . state . school . id ,
name: name ,
scheduling_communication: scheduling_communication ,
correspondence_email: correspondence_email
} ) . done ( (response) => @ onUpdateDone ( response ) ) . fail ( (jqXHR) => @ onUpdateFail ( jqXHR ) )
onUpdateDone: (response) ->
@ setState ( { school: response , userSchedulingComm: null , schoolName: null , updateErrors: null , updating: false } )
@ app . layout . notify ( { title: " update success " , text: " Your school information has been successfully updated " } )
onUpdateFail: (jqXHR) ->
handled = false
@ setState ( { updating: false } )
if jqXHR . status == 422
errors = JSON . parse ( jqXHR . responseText )
handled = true
@ setState ( { updateErrors: errors } )
if ! handled
@ app . ajaxError ( jqXHR , null , null )
inviteTeacher: () ->
@ app . layout . showDialog ( ' invite-school-user ' , { d1: true } )
inviteStudent: () ->
@ app . layout . showDialog ( ' invite-school-user ' , { d1: false } )
resendInvitation: (id, e) ->
e . preventDefault ( )
2016-04-06 12:06:52 +00:00
rest . resendSchoolInvitation ( {
id: this . state . school . id , invitation_id: id
2016-04-06 02:23:15 +00:00
} ) . done ( (response) => @ resendInvitationDone ( response ) ) . fail ( (jqXHR) => @ resendInvitationFail ( jqXHR ) )
resendInvitationDone: (response) ->
2016-04-06 12:06:52 +00:00
@ app . layout . notify ( { title: ' invitation resent ' , text: ' Invitation was resent to ' + response . email } )
2016-04-06 02:23:15 +00:00
resendInvitationFail: (jqXHR) ->
@ app . ajaxError ( jqXHR )
deleteInvitation: (id, e) ->
e . preventDefault ( )
rest . deleteSchoolInvitation ( {
2016-04-06 12:06:52 +00:00
id: this . state . school . id , invitation_id: id
2016-04-06 02:23:15 +00:00
} ) . done ( (response) => @ deleteInvitationDone ( id , response ) ) . fail ( (jqXHR) => @ deleteInvitationFail ( jqXHR ) )
deleteInvitationDone: (id, response) ->
context . SchoolActions . deleteInvitation ( id )
deleteInvitationFail: (jqXHR) ->
@ app . ajaxError ( jqXHR )
removeFromSchool: (id, isTeacher, e) ->
if isTeacher
2016-09-08 10:59:58 +00:00
rest . deleteSchoolTeacher ( {
id: this . state . school . id ,
teacher_id: id
} ) . done ( (response) => @ removeFromSchoolDone ( response ) ) . fail ( (jqXHR) => @ removeFromSchoolFail ( jqXHR ) )
2016-04-06 02:23:15 +00:00
else
2016-09-08 10:59:58 +00:00
rest . deleteSchoolStudent ( {
id: this . state . school . id ,
student_id: id
} ) . done ( (response) => @ removeFromSchoolDone ( response ) ) . fail ( (jqXHR) => @ removeFromSchoolFail ( jqXHR ) )
2016-04-06 02:23:15 +00:00
removeFromSchoolDone: (school) ->
context . JK . Banner . showNotice ( " User removed " , " User was removed from your school. " )
context . SchoolActions . updateSchool ( school )
removeFromSchoolFail: (jqXHR) ->
@ app . ajaxError ( jqXHR )
renderUser: (user, isTeacher) ->
photo_url = user . photo_url
if ! photo_url ?
photo_url = ' /assets/shared/avatar_generic.png '
2016-09-09 14:53:38 +00:00
mailto = " mailto: #{ user . email } "
2016-04-06 02:23:15 +00:00
` < div className = " school-user " >
< div className = " avatar " >
2016-09-08 10:59:58 +00:00
< img src = { photo_url } / >
2016-04-06 02:23:15 +00:00
< / div >
< div className = " usersname " >
2016-09-09 14:53:38 +00:00
< span className = " just-name " > { user . name } < / span >
< span className = " just-email " > < a href = { mailto } > { user . email } < / a > < / span >
2016-04-06 02:23:15 +00:00
< / div >
< div className = " user-actions " >
< a onClick = { this . removeFromSchool . bind ( this , user . id , isTeacher ) } > remove from school < / a >
< / div >
< / div > `
renderInvitation: (invitation) ->
` < div key = { invitation . id } className = " school-invitation " >
< table >
< tbody >
< td className = " description " > { invitation . first_name } { invitation . last_name } < / td >
< td className = " message " >
< div className = " detail-block " > has not yet accepted invitation < br / >
< a className = " resend " onClick = { this . resendInvitation . bind ( this , invitation . id ) } > resend invitation < / a >
< a className = " delete " onClick = { this . deleteInvitation . bind ( this , invitation . id ) } > delete < / a >
< / div >
< / td >
< / tbody >
< / table >
< / div > `
renderTeachers: () ->
teachers = [ ]
if this . state . school . teachers ? && this . state . school . teachers . length > 0
for teacher in this . state . school . teachers
2016-09-08 10:59:58 +00:00
if teacher . user
teachers . push ( @ renderUser ( teacher . user , true ) )
2016-04-06 02:23:15 +00:00
else
teachers = ` < p > No teachers < / p > `
teachers
renderStudents: () ->
students = [ ]
if this . state . school . students ? && this . state . school . students . length > 0
for student in this . state . school . students
students . push ( @ renderUser ( student , false ) )
else
students = ` < p > No students < / p > `
students
renderTeacherInvitations: () ->
invitations = [ ]
if this . state . teacherInvitations ? && this . state . teacherInvitations . length > 0
for invitation in this . state . teacherInvitations
invitations . push ( @ renderInvitation ( invitation ) )
else
invitations = ` < p > No pending invitations < / p > `
invitations
renderStudentInvitations: () ->
invitations = [ ]
if this . state . studentInvitations ? && this . state . studentInvitations . length > 0
for invitation in this . state . studentInvitations
invitations . push ( @ renderInvitation ( invitation ) )
else
invitations = ` < p > No pending invitations < / p > `
invitations
mainContent: () ->
if ! @ state . user ? || ! @ state . school ?
` < div className = " loading " > Loading . . . < / div > `
else if @ state . selected == @ TILE_ACCOUNT
@ account ( )
else if @ state . selected == @ TILE_MEMBERS
@ members ( )
else if @ state . selected == @ TILE_EARNINGS
@ earnings ( )
else if @ state . selected == @ TILE_AGREEMENT
@ agreement ( )
else
@ account ( )
account: () ->
ownerEmail = this . state . school . owner . email
correspondenceEmail = this . state . school . correspondence_email
correspondenceDisabled = ! @ isSchoolManaged ( )
nameErrors = context . JK . reactSingleFieldErrors ( ' name ' , @ state . updateErrors )
correspondenceEmailErrors = context . JK . reactSingleFieldErrors ( ' correspondence_email ' , @ state . updateErrors )
nameClasses = classNames ( { name: true , error: nameErrors ? , field: true } )
correspondenceEmailClasses = classNames ( {
correspondence_email: true ,
error: correspondenceEmailErrors ? ,
field: true
} )
2016-09-08 10:59:58 +00:00
cancelClasses = { " button-grey " : true , " cancel " : true , disabled: this . state . updating }
updateClasses = { " button-orange " : true , " update " : true , disabled: this . state . updating }
if this . state . school . education
management = null
else
management = ` < div >
< h4 > Management Preference < / h4 >
< div className = " field scheduling_communication " >
< div className = " scheduling_communication school " >
< input type = " radio " name = " scheduling_communication " readOnly = { true } value = " school "
checked = { this . isSchoolManaged ( ) } / > < label > School owner will manage scheduling of student lessons
sourced
by JamKazam < / label >
< / div >
< div className = " scheduling_communication teacher " >
< input type = " radio " name = " scheduling_communication " readOnly = { true } value = " teacher "
checked = { ! this . isSchoolManaged ( ) } / > < label > Teacher will manage scheduling of lessons < / label >
< / div >
< / div >
< div className = { correspondenceEmailClasses } >
< label > Correspondence Email : < / label >
< input type = " text " name = " correspondence_email " placeholder = { ownerEmail } defaultValue = { correspondenceEmail }
disabled = { correspondenceDisabled } / >
< div className = " hint " > All emails relating to lesson scheduling will go to this email if school owner manages
scheduling .
< / div >
{ correspondenceEmailErrors }
< / div >
< / div > `
2016-04-06 02:23:15 +00:00
` < div className = " account-block info-block " >
< div className = { nameClasses } >
< label > School Name : < / label >
< input type = " text " name = " name " value = { this . nameValue ( ) } onChange = { this . nameChanged } / >
{ nameErrors }
< / div >
< div className = " field logo " >
< label > School Logo : < / label >
< AvatarEditLink target = { this . state . school } target_type = " school " / >
< / div >
2016-09-08 10:59:58 +00:00
{ management }
2016-04-06 02:23:15 +00:00
< h4 > Payments < / h4 >
< div className = " field stripe-connect " >
< StripeConnect purpose = ' school ' user = { this . state . user } / >
< / div >
< div className = " actions " >
< a className = { classNames ( cancelClasses ) } onClick = { this . onCancel } > CANCEL < / a >
< a className = { classNames ( updateClasses ) } onClick = { this . onUpdate } > UPDATE < / a >
< / div >
< / div > `
members: () ->
teachers = @ renderTeachers ( )
teacherInvitations = @ renderTeacherInvitations ( )
students = @ renderStudents ( )
studentInvitations = @ renderStudentInvitations ( )
` < div className = " members-block info-block " >
< div className = " column column-left " >
< div >
< h3 > teachers : < / h3 >
< a onClick = { this . inviteTeacher } className = " button-orange invite-dialog " > INVITE TEACHER < / a >
2016-09-08 10:59:58 +00:00
< br className = " clearall " / >
2016-04-06 02:23:15 +00:00
< / div >
< div className = " teacher-invites " >
{ teacherInvitations }
< / div >
< div className = " teachers " >
{ teachers }
< / div >
< / div >
< div className = " column column-right " >
< div >
< h3 > students : < / h3 >
< a onClick = { this . inviteStudent } className = " button-orange invite-dialog " > INVITE STUDENT < / a >
< br className = " clearall " / >
< / div >
< div className = " student-invites " >
{ studentInvitations }
< / div >
< div className = " students " >
{ students }
< / div >
< / div >
< / div > `
earnings: () ->
` < div className = " earnings-block info-block " >
< p > Coming soon < / p >
< / div > `
2016-09-08 10:59:58 +00:00
paymentsToYou: () ->
rows = [ ]
for paymentHistory in this . state . distributions
paymentMethod = ' Stripe '
if paymentHistory . distributed
date = paymentHistory . teacher_payment . teacher_payment_charge . last_billing_attempt_at
status = ' Paid '
else
date = paymentHistory . created_at
if paymentHistory . not_collectable
status = ' Uncollectible '
else if ! paymentHistory . teacher ? . teacher ? . stripe_account_id ?
status = ' No Stripe Acct '
else
status = ' Collecting '
date = context . JK . formatDate ( date , true )
description = paymentHistory . description
if paymentHistory . teacher_payment ?
amt = paymentHistory . teacher_payment . real_distribution_in_cents
else
amt = paymentHistory . real_distribution_in_cents
displayAmount = ' $ ' + ( amt / 100 ) . toFixed ( 2 )
amountClasses = { status: status }
row =
` < tr >
< td > { date } < / td >
< td className = " capitalize " > { paymentMethod } < / td >
< td > { description } < / td >
< td className = " capitalize " > { status } < / td >
< td className = { classNames ( amountClasses ) } > { displayAmount } < / td >
< / tr > `
rows . push ( row )
` < div >
< table className = " payment-table " >
< thead >
< tr >
< th > DATE < / th >
< th > METHOD < / th >
< th > DESCRIPTION < / th >
< th > STATUS < / th >
< th > AMOUNT < / th >
< / tr >
< / thead >
< tbody >
{ rows }
< / tbody >
< / table >
< a className = " btn-next-pager " href = " /api/sales?page=1 " > Next < / a >
< div className = " end-of-payments-list end-of-list " > No more payment history < / div >
< div className = " input-aligner " >
< a className = " back button-grey " onClick = { this . onBack } > BACK < / a >
< / div >
< br className = " clearall " / >
< / div > `
2016-04-06 02:23:15 +00:00
agreement: () ->
` < div className = " agreement-block info-block " >
< p > The agreement between your music school and JamKazam is part of JamKazam ' s terms of service. You can find the
complete terms of service < a href = " /corp/terms " target = " _blank " > here < / a > . And you can find the section that is
most specific to the music school terms < a href = " /corp/terms " target = " _blank " > here < / a > . < / p >
< / div > `
selectionMade: (selection, e) ->
e . preventDefault ( )
@ setState ( { selected: selection } )
createTileLink: (i, tile) ->
active = this . state . selected == tile
classes = classNames ( { last: i == @ TILES . length - 1 , activeTile: active } )
return ` < div key = { i } className = " profile-tile " > < a className = { classes }
onClick = { this . selectionMade . bind ( this , tile ) } > { tile } < / a > < / div > `
onCustomBack: (customBack, e) ->
e . preventDefault ( )
context.location = customBack
render: () ->
mainContent = @ mainContent ( )
profileSelections = [ ]
for tile , i in @ TILES
profileSelections . push ( @ createTileLink ( i , tile , profileSelections ) )
profileNav = ` < div className = " profile-nav " >
{ profileSelections }
< / div > `
` < div className = " content-body-scroller " >
< div className = " profile-header profile-head " >
< div className = " store-header " > school : < / div >
{ profileNav }
< div className = " clearall " > < / div >
< / div >
< div className = " profile-body " >
< div className = " profile-wrapper " >
< div className = " main-content " >
{ mainContent }
< br / >
< / div >
< / div >
< / div >
< / div > `
} )