jam-cloud/web/app/assets/javascripts/react-components/AccountRetailerScreen.js.js...

390 lines
12 KiB
CoffeeScript

context = window
rest = context.JK.Rest()
logger = context.JK.logger
AppStore = context.AppStore
SchoolActions = context.RetailerActions
SchoolStore = context.RetailerStore
UserStore = context.UserStore
profileUtils = context.JK.ProfileUtils
@AccountRetailerScreen = React.createClass({
mixins: [
ICheckMixin,
Reflux.listenTo(AppStore, "onAppInit"),
Reflux.listenTo(RetailerStore, "onRetailerChanged")
Reflux.listenTo(UserStore, "onUserChanged")
]
shownOnce: false
screenVisible: false
TILE_ACCOUNT: 'account'
TILE_TEACHERS: 'teachers'
TILE_SALES: 'sales'
TILE_AGREEMENT: 'agreement'
TILES: ['account', 'teachers', 'sales', 'agreement']
onAppInit: (@app) ->
@app.bindScreen('account/retailer', {beforeShow: @beforeShow, afterShow: @afterShow, beforeHide: @beforeHide})
onSchoolChanged: (retailerState) ->
@setState(retailerState)
onUserChanged: (userState) ->
@noRetailerCheck(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
beforeShow: (e) ->
noRetailerCheck: (user) ->
if user?.id? && @screenVisible
if !user.owned_retailer_id?
window.JK.Banner.showAlert("You are not the owner of a retailer in our systems. If you are, please contact support@jamkazam.com and we'll update your account.")
return false
else
if !@shownOnce
@shownOnce = true
RetailerActions.refresh(user.owned_retailer_id)
return true
else
return false
afterShow: (e) ->
@screenVisible = true
logger.debug("AccountRetailerScreen: afterShow")
logger.debug("after show", @state.user)
@noRetailerCheck(@state.user)
getInitialState: () ->
{
retailer: null,
user: null,
selected: 'account',
updateErrors: null,
retailerName: null,
teacherInvitations: null,
updating: false
}
nameValue: () ->
if this.state.retailerName?
this.state.retailerName
else
this.state.retailer.name
nameChanged: (e) ->
$target = $(e.target)
val = $target.val()
@setState({retailerName: 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()
@setState(updating: true)
rest.updateRetailer({
id: this.state.retailer.id,
name: name,
}).done((response) => @onUpdateDone(response)).fail((jqXHR) => @onUpdateFail(jqXHR))
onUpdateDone: (response) ->
@setState({retailer: response, retailerName: null, updateErrors: null, updating: false})
@app.layout.notify({title: "update success", text: "Your retailer 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-retailer-user', {d1: true})
resendInvitation: (id, e) ->
e.preventDefault()
rest.resendRetailerInvitation({
id: this.state.retailer.id, invitation_id: id
}).done((response) => @resendInvitationDone(response)).fail((jqXHR) => @resendInvitationFail(jqXHR))
resendInvitationDone: (response) ->
@app.layout.notify({title: 'invitation resent', text: 'Invitation was resent to ' + response.email})
resendInvitationFail: (jqXHR) ->
@app.ajaxError(jqXHR)
deleteInvitation: (id, e) ->
e.preventDefault()
rest.deleteRetailerInvitation({
id: this.state.retailer.id, invitation_id: id
}).done((response) => @deleteInvitationDone(id, response)).fail((jqXHR) => @deleteInvitationFail(jqXHR))
deleteInvitationDone: (id, response) ->
context.RetailerActions.deleteInvitation(id)
deleteInvitationFail: (jqXHR) ->
@app.ajaxError(jqXHR)
removeFromRetailer: (id, isTeacher, e) ->
if isTeacher
rest.deleteRetailerTeacher({id: this.state.retailer.id, teacher_id: id}).done((response) => @removeFromRetailerDone(response)).fail((jqXHR) => @removeFromSchoolFail(jqXHR))
removeFromRetailerDone: (retailer) ->
context.JK.Banner.showNotice("User removed", "User was removed from your retailer.")
context.RetailerActions.updateRetailer(retailer)
removeFromSchoolFail: (jqXHR) ->
@app.ajaxError(jqXHR)
renderUser: (user, isTeacher) ->
photo_url = user.photo_url
if !photo_url?
photo_url = '/assets/shared/avatar_generic.png'
`<div className="retailer-user">
<div className="avatar">
<img src={photo_url} />
</div>
<div className="usersname">
{user.name}
</div>
<div className="user-actions">
<a onClick={this.removeFromRetailer.bind(this, user.id, isTeacher)}>remove from retailer</a>
</div>
</div>`
renderInvitation: (invitation) ->
`<div key={invitation.id} className="retailer-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.retailer.teachers? && this.state.retailer.teachers.length > 0
for teacher in this.state.retailer.teachers
teachers.push(@renderUser(teacher.user, true))
else
teachers = `<p>No teachers</p>`
teachers
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
mainContent: () ->
if !@state.user? || !@state.retailer?
`<div className="loading">Loading...</div>`
else if @state.selected == @TILE_ACCOUNT
@account()
else if @state.selected == @TILE_TEACHERS
@teachers()
else if @state.selected == @TILE_SALES
@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
})
cancelClasses = { "button-grey": true, "cancel" : true, disabled: this.state.updating }
updateClasses = { "button-orange": true, "update" : true, disabled: this.state.updating }
`<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>
<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>
<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>`
teachers: () ->
teachers = @renderTeachers()
teacherInvitations = @renderTeacherInvitations()
`<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>
<br className="clearall" />
</div>
<div className="teacher-invites">
{teacherInvitations}
</div>
<div className="teachers">
{teachers}
</div>
</div>
</div>`
earnings: () ->
`<div className="earnings-block info-block">
<p>Coming soon</p>
</div>`
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 retailer 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">retailer:</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>`
})