2016-01-07 11:12:11 +00:00
|
|
|
context = window
|
|
|
|
|
rest = context.JK.Rest()
|
2016-01-13 02:37:00 +00:00
|
|
|
logger = context.JK.logger
|
2016-05-17 18:31:53 +00:00
|
|
|
EVENTS = context.JK.EVENTS;
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
SubjectStore = context.SubjectStore
|
|
|
|
|
InstrumentStore = context.InstrumentStore
|
|
|
|
|
LanguageStore = context.LanguageStore
|
|
|
|
|
GenreStore = context.GenreStore
|
|
|
|
|
UserStore = context.UserStore
|
|
|
|
|
AppStore = context.AppStore
|
2016-01-28 19:55:17 +00:00
|
|
|
ProfileActions = context.ProfileActions
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
profileUtils = context.JK.ProfileUtils
|
2016-01-07 11:12:11 +00:00
|
|
|
|
2016-01-13 02:37:00 +00:00
|
|
|
proficiencyCssMap = {
|
|
|
|
|
"1": "proficiency-beginner",
|
|
|
|
|
"2": "proficiency-intermediate",
|
|
|
|
|
"3": "proficiency-expert"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
proficiencyDescriptionMap = {
|
|
|
|
|
"1": "BEGINNER",
|
|
|
|
|
"2": "INTERMEDIATE",
|
|
|
|
|
"3": "EXPERT"
|
|
|
|
|
};
|
2016-01-07 11:12:11 +00:00
|
|
|
|
|
|
|
|
@TeacherProfile = React.createClass({
|
|
|
|
|
|
2016-01-13 02:37:00 +00:00
|
|
|
mixins: [
|
2016-05-05 02:20:38 +00:00
|
|
|
PostProcessorMixin,
|
2016-01-13 02:37:00 +00:00
|
|
|
Reflux.listenTo(AppStore, "onAppInit"),
|
|
|
|
|
Reflux.listenTo(UserStore, "onUserChanged"),
|
|
|
|
|
Reflux.listenTo(SubjectStore, "onSubjectsChanged"),
|
|
|
|
|
Reflux.listenTo(GenreStore, "onGenresChanged"),
|
|
|
|
|
Reflux.listenTo(InstrumentStore, "onInstrumentsChanged"),
|
|
|
|
|
Reflux.listenTo(LanguageStore, "onLanguagesChanged")
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
TILE_ABOUT: 'about'
|
|
|
|
|
TILE_EXPERIENCE: 'experience'
|
|
|
|
|
TILE_SAMPLES: 'samples'
|
|
|
|
|
TILE_RATINGS: 'ratings'
|
|
|
|
|
TILE_PRICES: 'prices'
|
2016-05-01 03:12:25 +00:00
|
|
|
visible: false
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
TILES: ['about', 'experience', 'samples', 'ratings', 'prices']
|
2016-01-07 11:12:11 +00:00
|
|
|
|
2016-01-08 23:29:58 +00:00
|
|
|
onAppInit: (@app) ->
|
2016-01-28 19:55:17 +00:00
|
|
|
@app.bindScreen('profile/teacher', {beforeShow: @beforeShow, afterShow: @afterShow, beforeHide: @beforeHide})
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
onSubjectsChanged: () ->
|
|
|
|
|
@setState({subjects: true})
|
|
|
|
|
|
|
|
|
|
onInstrumentsChanged: () ->
|
|
|
|
|
@setState({instruments: true})
|
|
|
|
|
|
|
|
|
|
onGenresChanged: () ->
|
|
|
|
|
@setState({genres: true})
|
|
|
|
|
|
|
|
|
|
onLanguagesChanged: () ->
|
|
|
|
|
@setState({languages: true})
|
2016-01-08 23:29:58 +00:00
|
|
|
|
2016-01-14 21:23:11 +00:00
|
|
|
componentDidMount: () ->
|
|
|
|
|
@root = $(@getDOMNode())
|
2016-05-01 03:12:25 +00:00
|
|
|
@screen = $('#teacher-profile')
|
2016-01-14 21:23:11 +00:00
|
|
|
@starbox()
|
|
|
|
|
|
|
|
|
|
componentDidUpdate:() ->
|
|
|
|
|
@starbox()
|
|
|
|
|
|
2016-04-27 03:22:49 +00:00
|
|
|
context.JK.popExternalLinks(@root)
|
|
|
|
|
|
2016-01-14 21:23:11 +00:00
|
|
|
starbox:() ->
|
|
|
|
|
$ratings = @root.find('.ratings-box')
|
|
|
|
|
$ratings.each((i, value) =>
|
|
|
|
|
$element = $(value)
|
|
|
|
|
rating = $element.attr('data-ratings')
|
|
|
|
|
rating = parseFloat(rating)
|
|
|
|
|
|
|
|
|
|
#$element.starbox('destroy')
|
|
|
|
|
|
|
|
|
|
$element.starbox({
|
|
|
|
|
average: rating,
|
|
|
|
|
changeable: false,
|
|
|
|
|
autoUpdateAverage: false,
|
|
|
|
|
ghosting: false
|
|
|
|
|
}).show()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
userDetailDone: (response) ->
|
|
|
|
|
if response.id == @state.userId
|
2016-05-05 02:20:38 +00:00
|
|
|
console.log("teacher markup", response)
|
|
|
|
|
@postProcessUser(response)
|
2016-01-15 20:51:22 +00:00
|
|
|
@setState({user: response, isSelf: response.id == context.JK.currentUserId})
|
|
|
|
|
else
|
|
|
|
|
logger.debug("ignoring userDetailDone", response.id, @state.userId)
|
|
|
|
|
|
2016-05-05 02:20:38 +00:00
|
|
|
@showSideBubbleWhenReady()
|
|
|
|
|
|
|
|
|
|
showSideBubbleWhenReady: () ->
|
|
|
|
|
if @user? && @state.user?
|
|
|
|
|
if @visible
|
2016-05-25 02:05:31 +00:00
|
|
|
setTimeout((() => (
|
|
|
|
|
if @visible
|
|
|
|
|
@showSideBubble()
|
|
|
|
|
)), 5000)
|
2016-05-01 03:12:25 +00:00
|
|
|
|
2016-01-28 19:55:17 +00:00
|
|
|
beforeHide: (e) ->
|
2016-05-01 03:12:25 +00:00
|
|
|
@visible = false
|
2016-05-02 01:35:51 +00:00
|
|
|
@hideSideBubble();
|
2016-01-28 19:55:17 +00:00
|
|
|
logger.debug("TeacherProfile: beforeHide")
|
|
|
|
|
ProfileActions.viewTeacherProfileDone()
|
|
|
|
|
|
|
|
|
|
beforeShow: (e) ->
|
|
|
|
|
logger.debug("TeacherProfile: beforeShow")
|
|
|
|
|
|
2016-05-01 03:12:25 +00:00
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
afterShow: (e) ->
|
2016-05-26 21:25:51 +00:00
|
|
|
UserActions.refresh()
|
2016-05-01 03:12:25 +00:00
|
|
|
@visible = true
|
2016-01-28 19:55:17 +00:00
|
|
|
logger.debug("TeacherProfile: afterShow")
|
2016-01-13 02:37:00 +00:00
|
|
|
@setState({userId: e.id, user: null})
|
2016-05-17 18:31:53 +00:00
|
|
|
@updateProfileInfo(e.id)
|
|
|
|
|
|
|
|
|
|
if $.QueryString['tile']?
|
|
|
|
|
rewrite = true
|
|
|
|
|
@setState({selected: $.QueryString['tile']})
|
|
|
|
|
|
|
|
|
|
if rewrite
|
|
|
|
|
if window.history.replaceState #ie9 proofing
|
|
|
|
|
window.history.replaceState({}, "", "/client#/profile/teacher/#{e.id}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateProfileInfo: (id) ->
|
2016-01-13 02:37:00 +00:00
|
|
|
rest.getUserDetail({
|
2016-05-17 18:31:53 +00:00
|
|
|
id: id,
|
2016-01-13 02:37:00 +00:00
|
|
|
show_teacher: true,
|
|
|
|
|
show_profile: true
|
|
|
|
|
}).done((response) => @userDetailDone(response)).fail(@app.ajaxError)
|
|
|
|
|
|
2016-05-01 03:12:25 +00:00
|
|
|
showSideBubble: () ->
|
|
|
|
|
# :remaining_test_drives, :can_buy_test_drive?
|
2016-05-23 18:22:26 +00:00
|
|
|
if @state.user?['has_booked_test_drive_with_student']
|
2016-05-01 03:12:25 +00:00
|
|
|
@showBuyNormalLessonBubble()
|
2016-05-23 18:22:26 +00:00
|
|
|
else
|
|
|
|
|
if @user['remaining_test_drives'] > 0
|
|
|
|
|
@showUseRemainingTestDrivesBubble()
|
|
|
|
|
else if @user['can_buy_test_drive?']
|
|
|
|
|
@showBuyTestDriveBubble()
|
|
|
|
|
else
|
|
|
|
|
@showBuyNormalLessonBubble()
|
2016-05-01 03:12:25 +00:00
|
|
|
|
|
|
|
|
hideSideBubble: () ->
|
|
|
|
|
if @screen.btOff
|
|
|
|
|
@screen.btOff()
|
|
|
|
|
|
|
|
|
|
showUseRemainingTestDrivesBubble: ( ) ->
|
2016-05-05 02:20:38 +00:00
|
|
|
context.JK.HelpBubbleHelper.showUseRemainingTestDrives(@screen, @screen, @user, (() => @useRemainingTestDrives()))
|
2016-05-01 03:12:25 +00:00
|
|
|
|
|
|
|
|
showBuyTestDriveBubble: () ->
|
2016-05-05 02:20:38 +00:00
|
|
|
context.JK.HelpBubbleHelper.showBuyTestDrive(@screen, @screen, @user, (() => @buyTestDrive()))
|
2016-05-01 03:12:25 +00:00
|
|
|
|
|
|
|
|
showBuyNormalLessonBubble: () ->
|
2016-05-05 02:20:38 +00:00
|
|
|
context.JK.HelpBubbleHelper.showBuyNormalLesson(@screen, @screen, @state.user, (() => @buyNormalLesson()))
|
|
|
|
|
|
|
|
|
|
useRemainingTestDrives: () ->
|
|
|
|
|
window.location.href = "/client#/jamclass/book-lesson/test-drive_#{@state.user.id}"
|
|
|
|
|
buyTestDrive: () ->
|
|
|
|
|
window.location.href = "/client#/jamclass/test-drive-selection/#{@state.user.id}"
|
2016-05-01 03:12:25 +00:00
|
|
|
|
|
|
|
|
|
2016-05-05 02:20:38 +00:00
|
|
|
buyNormalLesson: () ->
|
|
|
|
|
window.location.href = "/client#/jamclass/book-lesson/normal_#{@state.user.id}"
|
2016-05-01 03:12:25 +00:00
|
|
|
|
2016-01-07 11:12:11 +00:00
|
|
|
getInitialState: () ->
|
2016-01-13 02:37:00 +00:00
|
|
|
{
|
|
|
|
|
userId: null,
|
|
|
|
|
user: null,
|
2016-01-15 20:51:22 +00:00
|
|
|
selected: 'about' ,
|
2016-01-13 02:37:00 +00:00
|
|
|
isSelf: false,
|
|
|
|
|
subjects: false,
|
|
|
|
|
instruments: false,
|
|
|
|
|
genres: false,
|
|
|
|
|
languages: false
|
|
|
|
|
}
|
2016-01-07 11:12:11 +00:00
|
|
|
|
|
|
|
|
onUserChanged: (userState) ->
|
|
|
|
|
@user = userState?.user
|
2016-05-05 02:20:38 +00:00
|
|
|
@showSideBubbleWhenReady()
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
editProfile: (selected, e) ->
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
logger.debug("edit profile requested for state " + selected)
|
|
|
|
|
ProfileActions.startTeacherEdit(selected, true)
|
|
|
|
|
|
|
|
|
|
editMusicProfile: (selected, e) ->
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
logger.debug("edit music profile requested " + selected)
|
|
|
|
|
ProfileActions.startProfileEdit(selected, true)
|
|
|
|
|
|
|
|
|
|
editProfileLink: (text, selected) ->
|
|
|
|
|
if @state.isSelf
|
|
|
|
|
`<a className="edit-link" onClick={this.editProfile.bind(this, selected)}>{text}</a>`
|
|
|
|
|
|
|
|
|
|
editMusicProfileLink: (text, selected) ->
|
|
|
|
|
if @state.isSelf
|
|
|
|
|
`<a className="edit-link" onClick={this.editMusicProfile.bind(this, selected)}>{text}</a>`
|
|
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
editTeacherProfile: (e) ->
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
|
|
|
|
|
ProfileActions.startTeacherEdit(null, false)
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
teacherBio: (user, teacher) ->
|
|
|
|
|
if teacher.biography?
|
|
|
|
|
biography = teacher.biography
|
|
|
|
|
else
|
|
|
|
|
biography = 'No bio defined yet'
|
|
|
|
|
|
|
|
|
|
biography = biography.replace(/\n/g, "<br/>")
|
|
|
|
|
|
|
|
|
|
`<div className="section bio">
|
|
|
|
|
<h3>Teacher Profile {this.editProfileLink('edit profile', 'introduction')}</h3>
|
|
|
|
|
<div className="section-content">
|
|
|
|
|
<div dangerouslySetInnerHTML={{__html: biography}}></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>`
|
|
|
|
|
|
2016-01-19 00:41:53 +00:00
|
|
|
getYoutubeId:(url) ->
|
|
|
|
|
regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
|
|
|
|
|
match = url.match(regExp)
|
2016-01-13 02:37:00 +00:00
|
|
|
|
2016-01-19 00:41:53 +00:00
|
|
|
if match && match[2].length >= 9
|
|
|
|
|
return match[2]
|
|
|
|
|
else
|
|
|
|
|
return 'unknown'
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
|
2016-01-19 00:41:53 +00:00
|
|
|
sampleVideo: (user, teacher) ->
|
|
|
|
|
if teacher.introductory_video? && teacher.introductory_video.length > 0
|
|
|
|
|
videoUrl = teacher.introductory_video
|
|
|
|
|
|
|
|
|
|
# http://stackoverflow.com/a/21607897
|
|
|
|
|
embedId = @getYoutubeId(videoUrl)
|
|
|
|
|
embedUrl = "//www.youtube.com/embed/#{embedId}"
|
2016-01-13 02:37:00 +00:00
|
|
|
|
2016-04-27 03:22:49 +00:00
|
|
|
video = `<a className="video-thumbnail" href={videoUrl} rel="external">
|
|
|
|
|
<img className="play" src="/assets/content/icon_youtube_play.png" />
|
|
|
|
|
</a>`
|
|
|
|
|
|
2016-01-13 02:37:00 +00:00
|
|
|
return `<div className="section introductory-video">
|
|
|
|
|
<h3>Intro Video</h3>
|
|
|
|
|
|
|
|
|
|
<div className="section-content">
|
2016-04-27 03:22:49 +00:00
|
|
|
{video}
|
2016-01-13 02:37:00 +00:00
|
|
|
</div>
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
teachesInfo: (user, teacher) ->
|
|
|
|
|
teachesInfo = []
|
|
|
|
|
|
|
|
|
|
instruments = teacher.instruments.map((id) -> InstrumentStore.display(id))
|
|
|
|
|
instrumentData = instruments.join(', ')
|
2016-01-15 20:51:22 +00:00
|
|
|
teachesInfo.push(`<tr key="instruments">
|
2016-01-13 02:37:00 +00:00
|
|
|
<td>Instruments</td>
|
|
|
|
|
<td>{instrumentData}</td>
|
|
|
|
|
</tr>`)
|
|
|
|
|
|
|
|
|
|
subjects = teacher.subjects.map((id) -> SubjectStore.display(id))
|
|
|
|
|
subjectsData = subjects.join(', ')
|
2016-01-15 20:51:22 +00:00
|
|
|
teachesInfo.push(`<tr key="subjects">
|
2016-01-13 02:37:00 +00:00
|
|
|
<td>Subjects</td>
|
|
|
|
|
<td>{subjectsData}</td>
|
|
|
|
|
</tr>`)
|
|
|
|
|
|
|
|
|
|
genres = teacher.genres.map((id) -> GenreStore.display(id))
|
|
|
|
|
genresData = genres.join(', ')
|
2016-01-15 20:51:22 +00:00
|
|
|
teachesInfo.push(`<tr key="genres">
|
2016-01-13 02:37:00 +00:00
|
|
|
<td>Genres</td>
|
|
|
|
|
<td>{genresData}</td>
|
|
|
|
|
</tr>`)
|
|
|
|
|
|
|
|
|
|
levels = []
|
|
|
|
|
if teacher.teaches_beginner
|
|
|
|
|
levels.push('Beginner')
|
|
|
|
|
if teacher.teaches_intermediate
|
|
|
|
|
levels.push('Intermediate')
|
|
|
|
|
if teacher.teaches_advanced
|
|
|
|
|
levels.push('Advanced')
|
|
|
|
|
levelsData = levels.join(', ')
|
2016-01-15 20:51:22 +00:00
|
|
|
teachesInfo.push(`<tr key="levels">
|
2016-01-13 02:37:00 +00:00
|
|
|
<td>Levels</td>
|
|
|
|
|
<td>{levelsData}</td>
|
|
|
|
|
</tr>`)
|
|
|
|
|
|
|
|
|
|
ageData = '?'
|
|
|
|
|
if teacher.teaches_age_lower == 0 && teacher.teaches_age_upper == 0
|
|
|
|
|
ageData = 'Any'
|
|
|
|
|
else if teacher.teaches_age_lower != 0 && teacher.teaches_age_upper != 0
|
|
|
|
|
ageData = "#{teacher.teaches_age_lower} to #{teacher.teaches_age_upper}"
|
|
|
|
|
else if teacher.teaches_age_lower == 0
|
|
|
|
|
ageData = "Age #{teacher.teaches_age_upper} and younger"
|
|
|
|
|
else if teacher.teaches_age_upper == 0
|
|
|
|
|
ageData = "Ages #{teacher.teaches_age_lower} and up"
|
2016-01-15 20:51:22 +00:00
|
|
|
teachesInfo.push(`<tr key="ages">
|
2016-01-13 02:37:00 +00:00
|
|
|
<td>Ages</td>
|
|
|
|
|
<td>{ageData}</td>
|
|
|
|
|
</tr>`)
|
|
|
|
|
|
|
|
|
|
languages = teacher.languages.map((id) -> LanguageStore.display(id))
|
|
|
|
|
languagesData = languages.join(', ')
|
2016-01-15 20:51:22 +00:00
|
|
|
teachesInfo.push(`<tr key="languages">
|
2016-01-13 02:37:00 +00:00
|
|
|
<td>Languages</td>
|
|
|
|
|
<td>{languagesData}</td>
|
|
|
|
|
</tr>`)
|
|
|
|
|
`<div className="section teachers">
|
|
|
|
|
<h3>{this.state.user.first_name} Teaches {this.editProfileLink('edit teaching', 'basics')}</h3>
|
|
|
|
|
|
|
|
|
|
<div className="section-content">
|
2016-04-06 02:23:15 +00:00
|
|
|
<table className="jamtable" cellSpacing="0" cellPadding="0" border="0">
|
2016-01-13 02:37:00 +00:00
|
|
|
<tbody>
|
|
|
|
|
{teachesInfo}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
musicianBio: (user, teacher) ->
|
|
|
|
|
|
|
|
|
|
if user.biography?
|
|
|
|
|
musicianBio = user.biography
|
|
|
|
|
else
|
|
|
|
|
musicianBio = 'None specified.'
|
|
|
|
|
|
|
|
|
|
musicianBio = musicianBio.replace(/\n/g, "<br/>")
|
|
|
|
|
|
|
|
|
|
`<div className="section musician-bio">
|
|
|
|
|
<h3>Musical Profile {this.editMusicProfileLink('update bio', '')}</h3>
|
|
|
|
|
|
|
|
|
|
<div className="section-content" dangerouslySetInnerHTML={{__html: musicianBio}}></div>
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
plays: (user, teacher) ->
|
|
|
|
|
if user.profile.concert_count > 0
|
|
|
|
|
gigs = "Has played #{profileUtils.gigMap[user.profile.concert_count]} concert gigs"
|
|
|
|
|
else
|
|
|
|
|
gigs = "Has played an unknown # of concert gigs"
|
|
|
|
|
|
|
|
|
|
if user.profile.studio_session_count > 0
|
|
|
|
|
studioSessions = "Has played #{profileUtils.gigMap[user.profile.studio_session_count]} studio sessions"
|
|
|
|
|
else
|
|
|
|
|
studioSessions = "Has played an unknown # of studio sessions"
|
|
|
|
|
|
|
|
|
|
|
2016-04-27 03:22:49 +00:00
|
|
|
gigTable =
|
|
|
|
|
`<div className="giginfo">
|
|
|
|
|
<div className="gigs">{gigs}</div>
|
|
|
|
|
<div>{studioSessions}</div>
|
|
|
|
|
</div>`
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
display_instruments = []
|
|
|
|
|
for instrument in user.instruments
|
|
|
|
|
|
|
|
|
|
description = InstrumentStore.display(instrument.instrument_id)
|
|
|
|
|
proficiency = instrument.proficiency_level;
|
|
|
|
|
instrument_icon_url = context.JK.getInstrumentIcon256(instrument.instrument_id);
|
2016-01-15 20:51:22 +00:00
|
|
|
display_instruments.push(`<div className="profile-instrument" key={instrument.instrument_id}>
|
2016-01-13 02:37:00 +00:00
|
|
|
<img src={instrument_icon_url} width="70" height="70"/><br />
|
|
|
|
|
<span>{description}</span><br />
|
|
|
|
|
<span className={proficiencyCssMap[proficiency]}>{proficiencyDescriptionMap[proficiency]}</span>
|
|
|
|
|
</div>`)
|
|
|
|
|
|
|
|
|
|
`<div className="section plays">
|
|
|
|
|
<h3>{this.state.user.first_name} Plays {this.editMusicProfileLink('update instruments', 'experience')}</h3>
|
|
|
|
|
|
|
|
|
|
<div className="section-content">
|
|
|
|
|
{display_instruments}
|
|
|
|
|
{gigTable}
|
|
|
|
|
</div>
|
|
|
|
|
<br className="clearall"/>
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
createPresence: (className, url, img) ->
|
2016-01-15 20:51:22 +00:00
|
|
|
`<div key={className} className={className + "-presence logo online-presence-option"}>
|
2016-04-27 03:22:49 +00:00
|
|
|
<a href={url} rel="external"><img className="logo" src={img}/></a>
|
2016-01-13 02:37:00 +00:00
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onlinePresences: (user, teacher) ->
|
|
|
|
|
online_presences = user.profile.online_presences
|
|
|
|
|
|
|
|
|
|
presences = []
|
|
|
|
|
|
|
|
|
|
if user.profile.website
|
|
|
|
|
# make sure website is rooted
|
|
|
|
|
website = user.profile.website
|
|
|
|
|
if website.indexOf('http') == -1
|
|
|
|
|
website = 'http://' + website
|
|
|
|
|
presences.push(@createPresence("user-website", website, "/assets/content/website-logo.png"))
|
|
|
|
|
|
|
|
|
|
matches = profileUtils.soundCloudPresences(online_presences)
|
|
|
|
|
if matches.length > 0
|
|
|
|
|
presences.push(@createPresence("soundcloud", "http://www.soundcloud.com/#{matches[0].username}",
|
|
|
|
|
"/assets/content/soundcloud-logo.png"))
|
|
|
|
|
|
|
|
|
|
matches = profileUtils.reverbNationPresences(online_presences)
|
|
|
|
|
if matches.length > 0
|
|
|
|
|
presences.push(@createPresence("reverbnation", "http://www.reverbnation.com/#{matches[0].username}",
|
|
|
|
|
"/assets/content/reverbnation-logo.png"))
|
|
|
|
|
|
|
|
|
|
matches = profileUtils.bandCampPresences(online_presences)
|
|
|
|
|
if matches.length > 0
|
|
|
|
|
presences.push(@createPresence("bandcamp", 'http://' + matches[0].username + '.bandcamp.com/',
|
|
|
|
|
"/assets/content/bandcamp-logo.png"))
|
|
|
|
|
|
|
|
|
|
matches = profileUtils.fandalismPresences(online_presences)
|
|
|
|
|
if matches.length > 0
|
|
|
|
|
presences.push(@createPresence("fandalism", 'http://www.fandalism.com/' + matches[0].username,
|
|
|
|
|
"/assets/content/fandalism-logo.png"))
|
|
|
|
|
|
|
|
|
|
matches = profileUtils.youTubePresences(online_presences)
|
|
|
|
|
if matches.length > 0
|
|
|
|
|
presences.push(@createPresence("youtube", 'http://www.youtube.com/' + matches[0].username,
|
|
|
|
|
"/assets/content/youtube-logo.png"))
|
|
|
|
|
|
|
|
|
|
matches = profileUtils.facebookPresences(online_presences)
|
|
|
|
|
if matches.length > 0
|
|
|
|
|
presences.push(@createPresence("facebook", 'http://www.facebook.com/' + matches[0].username,
|
|
|
|
|
"/assets/content/facebook-logo.png"))
|
|
|
|
|
|
|
|
|
|
matches = profileUtils.twitterPresences(online_presences)
|
|
|
|
|
if matches.length > 0
|
|
|
|
|
presences.push(@createPresence("twitter", 'http://www.twitter.com/' + matches[0].username,
|
|
|
|
|
"/assets/content/twitter-logo.png"))
|
|
|
|
|
|
|
|
|
|
if presences.length == 0
|
|
|
|
|
presences = `<div className="no-online-presence">None specified</div>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
`<div className="section plays">
|
|
|
|
|
<h3>Online Presence {this.editMusicProfileLink('update presence', 'samples')}</h3>
|
|
|
|
|
|
|
|
|
|
<div className="section-content">
|
|
|
|
|
{presences}
|
|
|
|
|
</div>
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
about: () ->
|
|
|
|
|
user = @state.user
|
|
|
|
|
teacher = user.teacher
|
|
|
|
|
|
|
|
|
|
`<div className="about-block info-block">
|
|
|
|
|
{this.sampleVideo(user, teacher)}
|
|
|
|
|
|
|
|
|
|
{this.teacherBio(user, teacher)}
|
|
|
|
|
|
|
|
|
|
{this.teachesInfo(user, teacher)}
|
|
|
|
|
|
|
|
|
|
{this.musicianBio(user, teacher)}
|
|
|
|
|
|
|
|
|
|
{this.plays(user, teacher)}
|
|
|
|
|
|
|
|
|
|
{this.onlinePresences(user, teacher)}
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
experiences: (title, attr, update, user, teacher) ->
|
|
|
|
|
teachingExperiences = []
|
|
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
for teachingExperience, i in teacher['experiences_' + attr]
|
2016-01-13 02:37:00 +00:00
|
|
|
years = ''
|
|
|
|
|
if teachingExperience.start_year > 0
|
|
|
|
|
if teachingExperience.end_year && teachingExperience.end_year > 0
|
|
|
|
|
years = "#{teachingExperience.start_year} - #{teachingExperience.end_year}"
|
|
|
|
|
else
|
2016-01-19 00:41:53 +00:00
|
|
|
years = "#{teachingExperience.start_year} - Present"
|
2016-01-13 02:37:00 +00:00
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
teachingExperiences.push(`<div key={i} className="experience">
|
2016-01-13 02:37:00 +00:00
|
|
|
<div className="years">{years}</div>
|
|
|
|
|
<h4>{teachingExperience.name}</h4>
|
|
|
|
|
|
|
|
|
|
<div className="org">{teachingExperience.organization}</div>
|
|
|
|
|
</div>`)
|
|
|
|
|
|
|
|
|
|
if update?
|
|
|
|
|
updateLink = this.editProfileLink('update ' + update, 'experience')
|
|
|
|
|
|
|
|
|
|
if teachingExperiences.length == 0
|
|
|
|
|
teachingExperiences = `<div>None specified</div>`
|
|
|
|
|
`<div className="section teaching-experience">
|
|
|
|
|
<h3>{title} {updateLink}</h3>
|
|
|
|
|
|
|
|
|
|
<div className="section-content">
|
|
|
|
|
{teachingExperiences}
|
|
|
|
|
</div>
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
sampleClicked: (e) ->
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
context.JK.popExternalLink($(e.target).attr('href'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
musicSamples: (user, teacher) ->
|
|
|
|
|
performance_samples = user.profile.performance_samples
|
|
|
|
|
|
|
|
|
|
jamkazamSamples = []
|
|
|
|
|
samples = profileUtils.jamkazamSamples(performance_samples);
|
|
|
|
|
for sample in samples
|
2016-01-15 20:51:22 +00:00
|
|
|
jamkazamSamples.push(`<a key={sample.claimed_recording.id} className="jamkazam-playable playable" href={"/recordings/" + sample.claimed_recording.id} onClick={this.sampleClicked}>{sample.claimed_recording.name}</a>`)
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
soundCloudSamples= []
|
|
|
|
|
samples = profileUtils.soundCloudSamples(performance_samples);
|
|
|
|
|
for sample in samples
|
2016-01-15 20:51:22 +00:00
|
|
|
soundCloudSamples.push(`<a key={sample.url} className="sound-cloud-playable playable" href={sample.url} onClick={this.sampleClicked}>{sample.description}</a>`)
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
youTubeSamples = []
|
|
|
|
|
samples = profileUtils.youTubeSamples(performance_samples);
|
|
|
|
|
for sample in samples
|
2016-01-15 20:51:22 +00:00
|
|
|
youTubeSamples.push(`<a key={sample.url} className="youtube-playable playable" href={sample.url} onClick={this.sampleClicked}>{sample.description}</a>`)
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
sampleJsx = []
|
|
|
|
|
|
|
|
|
|
if jamkazamSamples.length > 0
|
2016-01-15 20:51:22 +00:00
|
|
|
sampleJsx.push(`<div key="jamkazam-samples" className="jamkazam-samples logo performance-sample-option">
|
2016-01-13 02:37:00 +00:00
|
|
|
<img className="logo" src="/assets/header/logo.png" />
|
|
|
|
|
{jamkazamSamples}
|
|
|
|
|
</div>`)
|
|
|
|
|
|
|
|
|
|
if soundCloudSamples.length > 0
|
2016-01-15 20:51:22 +00:00
|
|
|
sampleJsx.push(`<div key="soundcloud-samples" className="soundcloud-samples logo performance-sample-option">
|
2016-01-13 02:37:00 +00:00
|
|
|
<img className="logo" src="/assets/content/soundcloud-logo.png" />
|
|
|
|
|
{soundCloudSamples}
|
|
|
|
|
</div>`)
|
|
|
|
|
|
|
|
|
|
if youTubeSamples.length > 0
|
2016-01-15 20:51:22 +00:00
|
|
|
sampleJsx.push(`<div key="youtube-samples" className="youtube-samples logo performance-sample-option">
|
2016-01-13 02:37:00 +00:00
|
|
|
<img className="logo" src="/assets/content/youtube-logo.png" />
|
|
|
|
|
{youTubeSamples}
|
|
|
|
|
</div>`)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
`<div className="section samples">
|
|
|
|
|
<h3>Performance Samples {this.editMusicProfileLink('update samples', 'samples')}</h3>
|
|
|
|
|
|
|
|
|
|
<div className="section-content">
|
|
|
|
|
{sampleJsx}
|
|
|
|
|
</div>
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
experience: () ->
|
|
|
|
|
user = @state.user
|
|
|
|
|
teacher = user.teacher
|
|
|
|
|
|
|
|
|
|
`<div className="experience-block info-block">
|
|
|
|
|
{this.experiences('Teaching Experience', 'teaching', 'experience', user, teacher)}
|
|
|
|
|
|
|
|
|
|
{this.experiences('Music Education', 'education', null, user, teacher)}
|
|
|
|
|
|
|
|
|
|
{this.experiences('Music Awards', 'award', null, user, teacher)}
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
samples: () ->
|
|
|
|
|
user = @state.user
|
|
|
|
|
teacher = user.teacher
|
|
|
|
|
|
|
|
|
|
`<div className="samples-block info-block">
|
|
|
|
|
{this.musicSamples(user, teacher)}
|
|
|
|
|
</div>`
|
|
|
|
|
|
2016-05-17 18:31:53 +00:00
|
|
|
rateTeacher: (e) ->
|
|
|
|
|
@app.layout.showDialog('rate-user-dialog', {d1: "teacher_#{@state.user.id}"}).one(EVENTS.DIALOG_CLOSED, (e, data) =>
|
|
|
|
|
if !data.canceled
|
|
|
|
|
@updateProfileInfo(@state.userId)
|
|
|
|
|
)
|
|
|
|
|
|
2016-01-13 02:37:00 +00:00
|
|
|
ratings: () ->
|
|
|
|
|
user = @state.user
|
|
|
|
|
teacher = user.teacher
|
|
|
|
|
|
2016-01-14 21:23:11 +00:00
|
|
|
summary = teacher.review_summary || {avg_rating: 0, review_count: 0}
|
|
|
|
|
|
|
|
|
|
if summary.review_count == 1
|
|
|
|
|
reviewCount = '1 review'
|
|
|
|
|
else
|
2016-01-19 00:41:53 +00:00
|
|
|
reviewCount = summary.review_count + ' reviews'
|
2016-01-14 21:23:11 +00:00
|
|
|
reviews = []
|
|
|
|
|
|
|
|
|
|
for review in teacher.recent_reviews
|
|
|
|
|
photo_url = review.user.photo_url
|
|
|
|
|
if !photo_url?
|
|
|
|
|
photo_url = '/assets/shared/avatar_generic.png'
|
|
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
name = `<div key={review.id} className="reviewer-name">{review.user.name}</div>`
|
2016-01-14 21:23:11 +00:00
|
|
|
reviews.push(`<div className="review">
|
|
|
|
|
<div className="review-header">
|
|
|
|
|
<div className="avatar small">
|
|
|
|
|
<img src={photo_url} />
|
|
|
|
|
</div>
|
|
|
|
|
{name}
|
|
|
|
|
<div className="ratings-box hidden" data-ratings={review.rating / 5 }/>
|
|
|
|
|
<div className="review-time">{context.JK.formatDateShort(review.created_at)}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="review-content" dangerouslySetInnerHTML={{__html: review.description}}></div>
|
|
|
|
|
</div>`)
|
2016-01-13 02:37:00 +00:00
|
|
|
`<div className="ratings-block info-block">
|
2016-01-14 21:23:11 +00:00
|
|
|
<h3>Ratings & Reviews</h3>
|
|
|
|
|
|
2016-05-17 18:31:53 +00:00
|
|
|
<h4>{user.first_name} Summary Rating: <div data-ratings={summary.avg_rating / 5} className="ratings-box hidden"/> <div className="review-count">({reviewCount})</div> <a onClick={this.rateTeacher} className="button-orange rate-teacher-btn">RATE TEACHER</a></h4>
|
|
|
|
|
|
2016-01-14 21:23:11 +00:00
|
|
|
|
|
|
|
|
{reviews}
|
2016-01-13 02:37:00 +00:00
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
prices: () ->
|
|
|
|
|
user = @state.user
|
|
|
|
|
teacher = user.teacher
|
|
|
|
|
|
|
|
|
|
rows = []
|
|
|
|
|
|
|
|
|
|
for minutes in [30, 45, 60, 90, 120]
|
|
|
|
|
lesson_price = teacher["price_per_lesson_#{minutes}_cents"]
|
|
|
|
|
monthly_price = teacher["price_per_month_#{minutes}_cents"]
|
|
|
|
|
duration_enabled = teacher["lesson_duration_#{minutes}"]
|
|
|
|
|
|
|
|
|
|
if duration_enabled && teacher.prices_per_lesson && lesson_price? && lesson_price > 0
|
|
|
|
|
lessonPriceFormatted = '$ ' + (lesson_price / 100).toFixed(2)
|
|
|
|
|
else
|
|
|
|
|
lessonPriceFormatted = 'N/A'
|
|
|
|
|
|
|
|
|
|
if duration_enabled && teacher.prices_per_month && monthly_price? && monthly_price > 0
|
|
|
|
|
monthlyPriceFormatted = '$ ' + (monthly_price / 100).toFixed(2)
|
|
|
|
|
else
|
|
|
|
|
monthlyPriceFormatted = 'N/A'
|
|
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
rows.push(`<tr key={minutes} ><td>{minutes + " Minutes"}</td><td>{lessonPriceFormatted}</td><td>{monthlyPriceFormatted}</td></tr>`)
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
`<div className="prices-block info-block">
|
|
|
|
|
<h3>Lesson Prices {this.editProfileLink('update prices', 'pricing')}</h3>
|
|
|
|
|
|
|
|
|
|
<div className="section-content">
|
|
|
|
|
<table className="jamtable price-table">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr><th>LESSON LENGTH</th><th>PRICE PER LESSON</th><th>PRICE PER MONTH</th></tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
{rows}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
mainContent: () ->
|
|
|
|
|
if @state.selected == @TILE_ABOUT
|
|
|
|
|
@about()
|
|
|
|
|
else if @state.selected == @TILE_EXPERIENCE
|
|
|
|
|
@experience()
|
|
|
|
|
else if @state.selected == @TILE_SAMPLES
|
|
|
|
|
@samples()
|
|
|
|
|
else if @state.selected == @TILE_RATINGS
|
|
|
|
|
@ratings()
|
|
|
|
|
else if @state.selected == @TILE_PRICES
|
|
|
|
|
@prices()
|
|
|
|
|
|
|
|
|
|
profileLeft: () ->
|
2016-04-27 03:22:49 +00:00
|
|
|
|
|
|
|
|
if this.state.user.age?
|
|
|
|
|
age = `<div className="age">{this.state.user.age} years old</div>`
|
|
|
|
|
else
|
|
|
|
|
age = null
|
|
|
|
|
|
2016-01-13 02:37:00 +00:00
|
|
|
`<div className="profile-about-left">
|
|
|
|
|
<div className="left-content">
|
|
|
|
|
<div className="location">
|
|
|
|
|
<div className="city">{this.state.user.city}</div>
|
|
|
|
|
<div className="state">{this.state.user.state}</div>
|
|
|
|
|
<div className="country">{this.state.user.country}</div>
|
2016-04-27 03:22:49 +00:00
|
|
|
{age}
|
2016-01-13 02:37:00 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="activity">
|
|
|
|
|
<div className="last-signed-in">Last Signed In:</div>
|
|
|
|
|
<div>{"very recently"}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>`
|
|
|
|
|
|
|
|
|
|
selectionMade: (selection, e) ->
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
|
|
|
|
|
@setState({selected: selection})
|
2016-01-07 11:12:11 +00:00
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
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>`
|
|
|
|
|
|
2016-01-28 19:55:17 +00:00
|
|
|
onCustomBack: (customBack, e) ->
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
context.location = customBack
|
|
|
|
|
|
2016-01-07 11:12:11 +00:00
|
|
|
render: () ->
|
2016-01-13 02:37:00 +00:00
|
|
|
if @state.user?
|
|
|
|
|
avatar = context.JK.resolveAvatarUrl(@state.user.photo_url);
|
2016-06-01 00:20:03 +00:00
|
|
|
if @state.user?
|
|
|
|
|
if @state.user.teacher?
|
|
|
|
|
mainContent = @mainContent()
|
|
|
|
|
profileLeft = @profileLeft()
|
2016-01-15 20:51:22 +00:00
|
|
|
else
|
2016-06-01 00:20:03 +00:00
|
|
|
if context.JK.currentUserId? && @state.user?.id == context.JK.currentUserId
|
|
|
|
|
noTeacherProfile = `<div className="no-teacher-profile">You have no teacher profile defined yet. <a onClick={this.editTeacherProfile}>Start making one now.</a></div>`
|
|
|
|
|
else
|
|
|
|
|
noTeacherProfile = `<div className="no-teacher-profile">This user has no teacher profile.</div>`
|
|
|
|
|
|
|
|
|
|
mainContent = `<div className="">
|
|
|
|
|
{noTeacherProfile}
|
|
|
|
|
</div>`
|
|
|
|
|
else
|
|
|
|
|
noTeacherProfile = `<div><div className="loading-profile">Loading profile...</div><div className="spinner spinner-large"></div></div>`
|
2016-01-15 20:51:22 +00:00
|
|
|
mainContent = `<div className="">
|
|
|
|
|
{noTeacherProfile}
|
|
|
|
|
</div>`
|
2016-01-13 02:37:00 +00:00
|
|
|
|
2016-01-28 19:55:17 +00:00
|
|
|
if ProfileStore.customBack
|
|
|
|
|
actionButtons = `<div className="right profileNavActions">
|
|
|
|
|
<a className="button-orange" onClick={this.onCustomBack.bind(this, ProfileStore.customBack)}>{ProfileStore.customBackDisplay}</a>
|
|
|
|
|
</div>`
|
2016-01-13 02:37:00 +00:00
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
profileSelections = []
|
2016-01-13 02:37:00 +00:00
|
|
|
for tile, i in @TILES
|
2016-01-15 20:51:22 +00:00
|
|
|
profileSelections.push(@createTileLink(i, tile, profileSelections))
|
2016-01-13 02:37:00 +00:00
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
profileNav = `<div className="profile-nav">
|
|
|
|
|
{profileSelections}
|
|
|
|
|
</div>`
|
2016-01-07 11:12:11 +00:00
|
|
|
`<div className="content-body-scroller">
|
2016-01-13 02:37:00 +00:00
|
|
|
<div className="profile-header profile-head">
|
2016-06-01 00:20:03 +00:00
|
|
|
<JamClassSearchHeader teacher={this.state.user}/>
|
2016-01-13 02:37:00 +00:00
|
|
|
|
|
|
|
|
{actionButtons}
|
|
|
|
|
<br clear="all"/><br />
|
|
|
|
|
|
|
|
|
|
<div className="profile-photo">
|
|
|
|
|
<div className="avatar-profile">
|
|
|
|
|
<img width="200" height="200" src={avatar}/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2016-01-15 20:51:22 +00:00
|
|
|
{profileNav}
|
2016-01-13 02:37:00 +00:00
|
|
|
<div className="clearall"></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="profile-body">
|
|
|
|
|
<div className="profile-wrapper">
|
|
|
|
|
{profileLeft}
|
|
|
|
|
<div className="main-content">
|
|
|
|
|
{mainContent}
|
|
|
|
|
</div>
|
2016-01-08 23:29:58 +00:00
|
|
|
|
2016-01-13 02:37:00 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2016-01-07 11:12:11 +00:00
|
|
|
</div>`
|
|
|
|
|
})
|