context = window rest = context.JK.Rest() logger = context.JK.logger EVENTS = context.JK.EVENTS; SubjectStore = context.SubjectStore InstrumentStore = context.InstrumentStore LanguageStore = context.LanguageStore GenreStore = context.GenreStore UserStore = context.UserStore AppStore = context.AppStore ProfileActions = context.ProfileActions profileUtils = context.JK.ProfileUtils proficiencyCssMap = { "1": "proficiency-beginner", "2": "proficiency-intermediate", "3": "proficiency-expert" }; proficiencyDescriptionMap = { "1": "BEGINNER", "2": "INTERMEDIATE", "3": "EXPERT" }; @TeacherProfile = React.createClass({ mixins: [ PostProcessorMixin, 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' visible: false profileClipboard: null TILES: ['about', 'experience', 'samples', 'ratings', 'prices'] onAppInit: (@app) -> @app.bindScreen('profile/teacher', {beforeShow: @beforeShow, afterShow: @afterShow, beforeHide: @beforeHide}) onSubjectsChanged: () -> @setState({subjects: true}) onInstrumentsChanged: () -> @setState({instruments: true}) onGenresChanged: () -> @setState({genres: true}) onLanguagesChanged: () -> @setState({languages: true}) componentDidMount: () -> @root = $(@getDOMNode()) @screen = $('#teacher-profile') @starbox() @clipboard() componentDidUpdate:() -> @starbox() context.JK.popExternalLinks(@root) @clipboard() clipboard: () -> $profileLink = @root.find('.copy-profile-link') if $profileLink.length > 0 && !@profileClipboard? # mount it @profileClipboard = new Clipboard($profileLink.get(0), { text: => return context.JK.makeAbsolute('/client#/teacher/profile/' + @state.user.id) }) else if $profileLink.length == 0 && @profileClipboard? @profileClipboard.destroy() @profileClipboard = null 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() ) userDetailDone: (response) -> if response.id == @state.userId console.log("teacher markup", response) @postProcessUser(response) @setState({user: response, isSelf: response.id == context.JK.currentUserId}) else logger.debug("ignoring userDetailDone", response.id, @state.userId) @showSideBubbleWhenReady() showSideBubbleWhenReady: () -> if @user? && @state.user? if @visible setTimeout((() => ( if @visible @showSideBubble() )), 5000) beforeHide: (e) -> @visible = false @hideSideBubble(); logger.debug("TeacherProfile: beforeHide") ProfileActions.viewTeacherProfileDone() beforeShow: (e) -> logger.debug("TeacherProfile: beforeShow") afterShow: (e) -> UserActions.refresh() @visible = true logger.debug("TeacherProfile: afterShow") @setState({userId: e.id, user: null}) @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) -> rest.getUserDetail({ id: id, show_teacher: true, show_profile: true }).done((response) => @userDetailDone(response)).fail(@app.ajaxError) showSideBubble: () -> # :remaining_test_drives, :can_buy_test_drive? if @state.user?['same_school_with_student'] @showBuyNormalLessonBubble() else if @user['jamclass_credits'] > 0 @showUseRemainingJamClassCreditsBubble() else if @state.user?['has_booked_test_drive_with_student'] @showBuyNormalLessonBubble() else if @user['remaining_test_drives'] > 0 @showUseRemainingTestDrivesBubble() else if @user['can_buy_test_drive?'] @showBuyTestDriveBubble() else @showBuyNormalLessonBubble() hideSideBubble: () -> if @screen.btOff @screen.btOff() showUseRemainingTestDrivesBubble: ( ) -> context.JK.HelpBubbleHelper.showUseRemainingTestDrives(@screen, @screen, @user, (() => @useRemainingTestDrives())) showUseRemainingJamClassCreditsBubble: ( ) -> context.JK.HelpBubbleHelper.showUseRemainingJamClassCreditsBubble(@screen, @screen, @user, (() => @useRemainingTestDrives())) showBuyTestDriveBubble: () -> context.JK.HelpBubbleHelper.showBuyTestDrive(@screen, @screen, @user, (() => @buyTestDrive())) showBuyNormalLessonBubble: () -> 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}" buyNormalLesson: () -> window.location.href = "/client#/jamclass/book-lesson/normal_#{@state.user.id}" getInitialState: () -> { userId: null, user: null, selected: 'about' , isSelf: false, subjects: false, instruments: false, genres: false, languages: false } onUserChanged: (userState) -> @user = userState?.user @showSideBubbleWhenReady() 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 `{text}` editMusicProfileLink: (text, selected) -> if @state.isSelf `{text}` editTeacherProfile: (e) -> e.preventDefault() ProfileActions.startTeacherEdit(null, false) teacherBio: (user, teacher) -> if teacher.biography? biography = teacher.biography else biography = 'No bio defined yet' biography = biography.replace(/\n/g, "
") # make button available only if this is the current user viewing if @state.userId == @user?.id copyUrlToClipboard = ` COPY PROFILE URL TO CLIPBOARD ` `
{copyUrlToClipboard}

Teacher Profile {this.editProfileLink('edit profile', 'introduction')}

` getYoutubeId:(url) -> regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/ match = url.match(regExp) if match && match[2].length >= 9 return match[2] else return 'unknown' 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}" video = ` ` return `

Intro Video

{video}
` teachesInfo: (user, teacher) -> teachesInfo = [] instruments = teacher.instruments.map((id) -> InstrumentStore.display(id)) instrumentData = instruments.join(', ') teachesInfo.push(` Instruments {instrumentData} `) subjects = teacher.subjects.map((id) -> SubjectStore.display(id)) subjectsData = subjects.join(', ') teachesInfo.push(` Subjects {subjectsData} `) genres = teacher.genres.map((id) -> GenreStore.display(id)) genresData = genres.join(', ') teachesInfo.push(` Genres {genresData} `) 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(', ') teachesInfo.push(` Levels {levelsData} `) 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" teachesInfo.push(` Ages {ageData} `) languages = teacher.languages.map((id) -> LanguageStore.display(id)) languagesData = languages.join(', ') teachesInfo.push(` Languages {languagesData} `) `

{this.state.user.first_name} Teaches {this.editProfileLink('edit teaching', 'basics')}

{teachesInfo}
` musicianBio: (user, teacher) -> if user.biography? musicianBio = user.biography else musicianBio = 'None specified.' musicianBio = musicianBio.replace(/\n/g, "
") `

Musical Profile {this.editMusicProfileLink('update bio', '')}

` 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" gigTable = `
{gigs}
{studioSessions}
` 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); display_instruments.push(`

{description}
{proficiencyDescriptionMap[proficiency]}
`) `

{this.state.user.first_name} Plays {this.editMusicProfileLink('update instruments', 'experience')}

{display_instruments} {gigTable}

` createPresence: (className, url, img) -> `
` 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 = `
None specified
` `

Online Presence {this.editMusicProfileLink('update presence', 'samples')}

{presences}
` about: () -> user = @state.user teacher = user.teacher `
{this.sampleVideo(user, teacher)} {this.teacherBio(user, teacher)} {this.teachesInfo(user, teacher)} {this.musicianBio(user, teacher)} {this.plays(user, teacher)} {this.onlinePresences(user, teacher)}
` experiences: (title, attr, update, user, teacher) -> teachingExperiences = [] for teachingExperience, i in teacher['experiences_' + attr] years = '' if teachingExperience.start_year > 0 if teachingExperience.end_year && teachingExperience.end_year > 0 years = "#{teachingExperience.start_year} - #{teachingExperience.end_year}" else years = "#{teachingExperience.start_year} - Present" teachingExperiences.push(`
{years}

{teachingExperience.name}

{teachingExperience.organization}
`) if update? updateLink = this.editProfileLink('update ' + update, 'experience') if teachingExperiences.length == 0 teachingExperiences = `
None specified
` `

{title} {updateLink}

{teachingExperiences}
` 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 jamkazamSamples.push(`{sample.claimed_recording.name}`) soundCloudSamples= [] samples = profileUtils.soundCloudSamples(performance_samples); for sample in samples soundCloudSamples.push(`{sample.description}`) youTubeSamples = [] samples = profileUtils.youTubeSamples(performance_samples); for sample in samples youTubeSamples.push(`{sample.description}`) sampleJsx = [] if jamkazamSamples.length > 0 sampleJsx.push(`
{jamkazamSamples}
`) if soundCloudSamples.length > 0 sampleJsx.push(`
{soundCloudSamples}
`) if youTubeSamples.length > 0 sampleJsx.push(`
{youTubeSamples}
`) `

Performance Samples {this.editMusicProfileLink('update samples', 'samples')}

{sampleJsx}
` experience: () -> user = @state.user teacher = user.teacher `
{this.experiences('Teaching Experience', 'teaching', 'experience', user, teacher)} {this.experiences('Music Education', 'education', null, user, teacher)} {this.experiences('Music Awards', 'award', null, user, teacher)}
` samples: () -> user = @state.user teacher = user.teacher `
{this.musicSamples(user, teacher)}
` 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) ) ratings: () -> user = @state.user teacher = user.teacher summary = teacher.review_summary || {avg_rating: 0, review_count: 0} if summary.review_count == 1 reviewCount = '1 review' else reviewCount = summary.review_count + ' reviews' reviews = [] for review in teacher.recent_reviews photo_url = review.user.photo_url if !photo_url? photo_url = '/assets/shared/avatar_generic.png' name = `
{review.user.name}
` reviews.push(`
{name}
{context.JK.formatDateShort(review.created_at)}
`) `

Ratings & Reviews

{user.first_name} Summary Rating:
({reviewCount})
RATE TEACHER

{reviews}
` 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' rows.push(`{minutes + " Minutes"}{lessonPriceFormatted}{monthlyPriceFormatted}`) `

Lesson Prices {this.editProfileLink('update prices', 'pricing')}

{rows}
LESSON LENGTHPRICE PER LESSONPRICE PER MONTH
` 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: () -> if this.state.user.age? age = `
{this.state.user.age} years old
` else age = null backgroundCheck = null backgroundCheckAt = @state.user?.teacher?.background_check_at if backgroundCheckAt backgroundCheck = `
Background Check:
{context.JK.formatDateShort(new Date(backgroundCheckAt))}
` `
{this.state.user.city}
{this.state.user.state}
{this.state.user.country}
{age}
Last Signed In:
{"very recently"}
{backgroundCheck}
` copyProfileLink: (e) -> e.preventDefault() @app.layout.notify({ title: 'Teacher Profile Link Copied', text: "Your clipboard now has a link to this teacher that you can share with anyone." }) 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 `
{tile}
` onCustomBack: (customBack, e) -> e.preventDefault() context.location = customBack render: () -> if @state.user? avatar = context.JK.resolveAvatarUrl(@state.user.photo_url); if @state.user? if @state.user.teacher? mainContent = @mainContent() profileLeft = @profileLeft() else if context.JK.currentUserId? && @state.user?.id == context.JK.currentUserId noTeacherProfile = `
You have no teacher profile defined yet. Start making one now.
` else noTeacherProfile = `
This user has no teacher profile.
` mainContent = `
{noTeacherProfile}
` else noTeacherProfile = `
Loading profile...
` mainContent = `
{noTeacherProfile}
` if ProfileStore.customBack actionButtons = `
{ProfileStore.customBackDisplay}
` profileSelections = [] for tile, i in @TILES profileSelections.push(@createTileLink(i, tile, profileSelections)) profileNav = `
{profileSelections}
` `
{actionButtons}

{profileNav}
{profileLeft}
{mainContent}
` })