VRFS-4142 - test drive packaging feature
This commit is contained in:
parent
ece81a2c9b
commit
88ebada41c
|
|
@ -3,6 +3,6 @@
|
|||
ol.nested-fields
|
||||
//= f.input :test_drive_package, :required=>true, value: @test_drive_package, include_blank: true
|
||||
= f.input :user, :required=>true, collection: User.where(is_a_teacher: true, phantom: false), include_blank: true
|
||||
= f.input :short_bio
|
||||
= f.input :short_bio_temp
|
||||
|
||||
= link_to_remove_association "Delete Teacher", f, class: 'button', style: 'margin-left:10px'
|
||||
|
|
|
|||
|
|
@ -356,4 +356,5 @@ remove_stripe_acct_id.sql
|
|||
track_user_on_lesson.sql
|
||||
audio_in_music_notations.sql
|
||||
lesson_time_tracking.sql
|
||||
packaged_test_drive.sql
|
||||
packaged_test_drive.sql
|
||||
packaged_test_drive2.sql
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE lesson_booking_slots ADD COLUMN from_package BOOL DEFAULT FALSE;
|
||||
ALTER TABLE lesson_bookings ADD COLUMN test_drive_package_choice_id VARCHAR(64) REFERENCES test_drive_package_choices(id);
|
||||
|
|
@ -45,6 +45,7 @@ module JamRuby
|
|||
belongs_to :default_slot, class_name: "JamRuby::LessonBookingSlot", foreign_key: :default_slot_id, inverse_of: :defaulted_booking, :dependent => :destroy
|
||||
belongs_to :counter_slot, class_name: "JamRuby::LessonBookingSlot", foreign_key: :counter_slot_id, inverse_of: :countered_booking, :dependent => :destroy
|
||||
belongs_to :school, class_name: "JamRuby::School"
|
||||
belongs_to :test_drive_package_choice, class_name: "JamRuby::TestDrivePackageChoice"
|
||||
has_many :lesson_booking_slots, class_name: "JamRuby::LessonBookingSlot", :dependent => :destroy
|
||||
has_many :lesson_sessions, class_name: "JamRuby::LessonSession", :dependent => :destroy
|
||||
has_many :lesson_package_purchases, class_name: "JamRuby::LessonPackagePurchase", :dependent => :destroy
|
||||
|
|
@ -139,6 +140,9 @@ module JamRuby
|
|||
booked_price
|
||||
end
|
||||
|
||||
def no_slots
|
||||
default_slot.from_package
|
||||
end
|
||||
|
||||
def alt_slot
|
||||
found = nil
|
||||
|
|
@ -193,12 +197,16 @@ module JamRuby
|
|||
self.counterer = proposer
|
||||
self.countered_at = Time.now
|
||||
self.sent_counter_reminder = false
|
||||
|
||||
if self.default_slot.from_package
|
||||
self.default_slot = slot
|
||||
end
|
||||
#self.status = STATUS_COUNTERED
|
||||
self.save
|
||||
end
|
||||
|
||||
def automatically_default_slot
|
||||
if is_requested?
|
||||
if is_requested? && default_slot.nil?
|
||||
if lesson_booking_slots.length > 0
|
||||
self.default_slot = lesson_booking_slots[0]
|
||||
end
|
||||
|
|
@ -680,8 +688,10 @@ module JamRuby
|
|||
end
|
||||
|
||||
def validate_lesson_booking_slots
|
||||
if lesson_booking_slots.length == 0 || lesson_booking_slots.length == 1
|
||||
errors.add(:lesson_booking_slots, "must have two times specified")
|
||||
if test_drive_package_choice.nil?
|
||||
if lesson_booking_slots.length == 0 || lesson_booking_slots.length == 1
|
||||
errors.add(:lesson_booking_slots, "must have two times specified")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -711,19 +721,22 @@ module JamRuby
|
|||
!!school
|
||||
end
|
||||
|
||||
def self.book_packaged_test_drive(user, teacher, description, test_drive_package_choice)
|
||||
book_test_drive(user, teacher, LessonBookingSlot.packaged_slots, description, test_drive_package_choice)
|
||||
end
|
||||
def self.book_free(user, teacher, lesson_booking_slots, description)
|
||||
self.book(user, teacher, LessonBooking::LESSON_TYPE_FREE, lesson_booking_slots, false, 30, PAYMENT_STYLE_ELSEWHERE, description)
|
||||
end
|
||||
|
||||
def self.book_test_drive(user, teacher, lesson_booking_slots, description)
|
||||
self.book(user, teacher, LessonBooking::LESSON_TYPE_TEST_DRIVE, lesson_booking_slots, false, 30, PAYMENT_STYLE_ELSEWHERE, description)
|
||||
def self.book_test_drive(user, teacher, lesson_booking_slots, description, test_drive_package_choice = nil)
|
||||
self.book(user, teacher, LessonBooking::LESSON_TYPE_TEST_DRIVE, lesson_booking_slots, false, 30, PAYMENT_STYLE_ELSEWHERE, description, test_drive_package_choice)
|
||||
end
|
||||
|
||||
def self.book_normal(user, teacher, lesson_booking_slots, description, recurring, payment_style, lesson_length)
|
||||
self.book(user, teacher, LessonBooking::LESSON_TYPE_PAID, lesson_booking_slots, recurring, lesson_length, payment_style, description)
|
||||
end
|
||||
|
||||
def self.book(user, teacher, lesson_type, lesson_booking_slots, recurring, lesson_length, payment_style, description)
|
||||
def self.book(user, teacher, lesson_type, lesson_booking_slots, recurring, lesson_length, payment_style, description, test_drive_package_choice = nil)
|
||||
|
||||
lesson_booking = nil
|
||||
LessonBooking.transaction do
|
||||
|
|
@ -739,6 +752,7 @@ module JamRuby
|
|||
lesson_booking.payment_style = payment_style
|
||||
lesson_booking.description = description
|
||||
lesson_booking.status = STATUS_REQUESTED
|
||||
lesson_booking.test_drive_package_choice = test_drive_package_choice
|
||||
if lesson_booking.teacher && lesson_booking.teacher.teacher.school
|
||||
lesson_booking.school = lesson_booking.teacher.teacher.school
|
||||
end
|
||||
|
|
|
|||
|
|
@ -74,6 +74,18 @@ module JamRuby
|
|||
(Time.now + APP_CONFIG.minimum_lesson_booking_hrs * 60 * 60)
|
||||
end
|
||||
|
||||
# create a canned slot for a TestDrivePackage. The most important thing here is that it expires in 30 days
|
||||
def self.packaged_slots
|
||||
slot = LessonBookingSlot.new
|
||||
slot.from_package = true
|
||||
slot.preferred_day = Date.today + 30
|
||||
slot.slot_type = LessonBookingSlot::SLOT_TYPE_SINGLE
|
||||
slot.hour = 1
|
||||
slot.minute = 0
|
||||
slot.timezone = 'America/Chicago'
|
||||
[slot]
|
||||
end
|
||||
|
||||
def scheduled_times(needed_sessions, minimum_start_time)
|
||||
|
||||
#puts "NEEDED SESSIONS #{needed_sessions} #{minimum_start_time}"
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ module JamRuby
|
|||
|
||||
|
||||
def to_s
|
||||
"#{name} (#{amount_charged})"
|
||||
"#{name}"
|
||||
end
|
||||
|
||||
def name
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ module JamRuby
|
|||
validate :validate_canceled, :if => :canceling
|
||||
validate :validate_autocancel, :if => :autocanceling
|
||||
|
||||
after_save :after_counter, :if => :countering
|
||||
after_save :manage_slot_changes
|
||||
after_create :create_charge
|
||||
|
||||
|
|
@ -444,10 +443,6 @@ module JamRuby
|
|||
self.lesson_booking.save(:validate => false)
|
||||
end
|
||||
|
||||
def after_counter
|
||||
send_counter(@countered_lesson, @countered_slot)
|
||||
end
|
||||
|
||||
def scheduled_start
|
||||
if music_session
|
||||
music_session.scheduled_start
|
||||
|
|
@ -458,10 +453,12 @@ module JamRuby
|
|||
end
|
||||
|
||||
def send_counter(countered_lesson, countered_slot)
|
||||
if countered_slot.is_teacher_created?
|
||||
UserMailer.student_lesson_counter(countered_lesson, countered_slot).deliver
|
||||
else
|
||||
UserMailer.teacher_lesson_counter(countered_lesson, countered_slot).deliver
|
||||
if !lesson_booking.errors.any?
|
||||
if countered_slot.is_teacher_created?
|
||||
UserMailer.student_lesson_counter(countered_lesson, countered_slot).deliver
|
||||
else
|
||||
UserMailer.teacher_lesson_counter(countered_lesson, countered_slot).deliver
|
||||
end
|
||||
end
|
||||
self.countering = false
|
||||
end
|
||||
|
|
@ -522,6 +519,7 @@ module JamRuby
|
|||
|
||||
self.countering_flag = false
|
||||
end
|
||||
|
||||
def validate_accepted
|
||||
if self.status_was != STATUS_REQUESTED && self.status_was != STATUS_COUNTERED
|
||||
self.errors.add(:status, "This session is already #{self.status_was}.")
|
||||
|
|
@ -632,7 +630,7 @@ module JamRuby
|
|||
# if the school owner is a teacher, show his bookings too
|
||||
extra_teacher = " OR lesson_sessions.teacher_id = '#{user.teacher.id}'"
|
||||
end
|
||||
query = query.where('lesson_sessions.teacher_id in (?)' + extra_teacher, user.owned_school.teachers.map {|t| t.user.id})
|
||||
query = query.where('lesson_sessions.teacher_id in (?)' + extra_teacher, user.owned_school.teachers.map { |t| t.user.id })
|
||||
query = query.where('lesson_sessions.status = ? OR lesson_sessions.status = ?', LessonSession::STATUS_REQUESTED, LessonSession::STATUS_COUNTERED)
|
||||
else
|
||||
# this is a normal teacher (not a school owner)
|
||||
|
|
@ -819,7 +817,7 @@ module JamRuby
|
|||
self.countered_lesson = self
|
||||
self.status = STATUS_COUNTERED
|
||||
#if !update_all
|
||||
self.counter_slot = slot
|
||||
self.counter_slot = slot
|
||||
#end
|
||||
if self.save
|
||||
#if update_all && !lesson_booking.counter(self, proposer, slot)
|
||||
|
|
@ -832,6 +830,7 @@ module JamRuby
|
|||
raise ActiveRecord::Rollback
|
||||
end
|
||||
|
||||
send_counter(@countered_lesson, @countered_slot)
|
||||
message = '' if message.nil?
|
||||
msg = ChatMessage.create(slot.proposer, music_session, message, ChatMessage::CHANNEL_LESSON, nil, slot.recipient, self, "New Time Proposed")
|
||||
Notification.send_lesson_message('counter', self, slot.is_teacher_created?)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ module JamRuby
|
|||
|
||||
#validate :teacher_count
|
||||
|
||||
def lesson_package_type
|
||||
LessonPackageType.package_for_test_drive_count(package_type.to_i)
|
||||
end
|
||||
def teacher_count
|
||||
if package_type != test_drive_package_teachers.length
|
||||
self.errors.add(:test_drive_package_teachers, "wrong number of teachers specified for the given package type #{package_type}")
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ module JamRuby
|
|||
@@log = Logging.logger[TestDrivePackageChoice]
|
||||
|
||||
belongs_to :test_drive_package, class_name: "JamRuby::TestDrivePackage"
|
||||
belongs_to :user, class_name: "JamRuby::User"
|
||||
has_many :test_drive_package_choice_teachers, class_name: "JamRuby::TestDrivePackageChoiceTeacher", foreign_key: :teacher_id
|
||||
|
||||
belongs_to :user, class_name: "JamRuby::User", foreign_key: :user_id, inverse_of: :test_drive_package_choices
|
||||
has_many :test_drive_package_choice_teachers, class_name: "JamRuby::TestDrivePackageChoiceTeacher", inverse_of: :test_drive_package_choice
|
||||
has_many :lesson_bookings, class_name: "JamRuby::LessonBooking"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module JamRuby
|
|||
|
||||
@@log = Logging.logger[TestDrivePackageChoiceTeacher]
|
||||
|
||||
belongs_to :test_drive_package_choice, class_name: "JamRuby::TestDrivePackageChoice"
|
||||
belongs_to :test_drive_package_choice, class_name: "JamRuby::TestDrivePackageChoice", inverse_of: :test_drive_package_choice_teachers
|
||||
belongs_to :teacher, class_name: "JamRuby::User", foreign_key: :teacher_id
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ module JamRuby
|
|||
|
||||
@@log = Logging.logger[TestDrivePackageTeacher]
|
||||
|
||||
attr_accessor :short_bio_temp
|
||||
attr_accessible :user_id, :test_drive_package_id, :short_bio, as: :admin
|
||||
attr_writer :short_bio_temp
|
||||
attr_accessible :user_id, :test_drive_package_id, :short_bio, :short_bio_temp, as: :admin
|
||||
|
||||
belongs_to :test_drive_package, class_name: "JamRuby::TestDrivePackage"
|
||||
belongs_to :user, class_name: "JamRuby::User"
|
||||
|
|
@ -18,12 +18,19 @@ module JamRuby
|
|||
# silly pass through for activeadmin. We pass short_bio set here on to teacher
|
||||
def after_save
|
||||
if user && user.teacher
|
||||
user.teacher.short_bio = short_bio
|
||||
user.teacher.save!
|
||||
if @another_bio.present?
|
||||
user.teacher.short_bio = @another_bio
|
||||
user.teacher.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def short_bio
|
||||
def short_bio_temp=(short_bio)
|
||||
self.updated_at = Time.now
|
||||
self.short_bio = short_bio
|
||||
@another_bio = short_bio
|
||||
end
|
||||
def short_bio_temp
|
||||
if user && user.teacher
|
||||
user.teacher.short_bio
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ module JamRuby
|
|||
attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection
|
||||
|
||||
# updating_password corresponds to a lost_password
|
||||
attr_accessor :validate_instruments, :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json, :expecting_gift_card
|
||||
attr_accessor :test_drive_packaging, :validate_instruments, :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json, :expecting_gift_card
|
||||
|
||||
belongs_to :icecast_server_group, class_name: "JamRuby::IcecastServerGroup", inverse_of: :users, foreign_key: 'icecast_server_group_id'
|
||||
|
||||
|
|
@ -176,6 +176,8 @@ module JamRuby
|
|||
has_many :teacher_lesson_bookings, :class_name => "JamRuby::LessonBooking", :foreign_key => "teacher_id", inverse_of: :teacher
|
||||
has_many :teacher_distributions, :class_name => "JamRuby::TeacherDistribution", :foreign_key => "teacher_id", inverse_of: :teacher
|
||||
has_many :teacher_payments, :class_name => "JamRuby::TeacherPayment", :foreign_key => "teacher_id", inverse_of: :teacher
|
||||
has_many :test_drive_package_choice_teachers, :class_name => "JamRuby::TestDrivePackageChoiceTeacher", :foreign_key => "teacher_id"
|
||||
has_many :test_drive_package_choices, :class_name => "JamRuby::TestDrivePackageChoice", :foreign_key => "user_id", inverse_of: :user
|
||||
belongs_to :desired_package, :class_name => "JamRuby::LessonPackageType", :foreign_key => "lesson_package_type_id", inverse_of: :user_desired_packages # used to hold whether user last wanted test drive 4/2/1
|
||||
|
||||
# Shopping carts
|
||||
|
|
@ -203,7 +205,7 @@ module JamRuby
|
|||
has_many :taught_lessons, :class_name => "JamRuby::LessonSession", inverse_of: :teacher, foreign_key: :teacher_id
|
||||
belongs_to :school, :class_name => "JamRuby::School", inverse_of: :students
|
||||
has_one :owned_school, :class_name => "JamRuby::School", inverse_of: :user
|
||||
|
||||
has_many :test_drive_package_choices, :class_name =>"JamRuby::TestDrivePackageChoice"
|
||||
has_many :jamblasters_users, class_name: "JamRuby::JamblasterUser"
|
||||
has_many :jamblasters, class_name: 'JamRuby::Jamblaster', through: :jamblasters_users
|
||||
|
||||
|
|
@ -1076,6 +1078,27 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def handle_test_drive_package(package, details)
|
||||
self.test_drive_packaging = true
|
||||
choice = TestDrivePackageChoice.new
|
||||
choice.user = self
|
||||
choice.test_drive_package = package
|
||||
details[:teachers].each do |teacher|
|
||||
teacher_choice = TestDrivePackageChoiceTeacher.new
|
||||
teacher_choice.teacher = User.find(teacher[:id])
|
||||
choice.test_drive_package_choice_teachers << teacher_choice
|
||||
end
|
||||
|
||||
choice.save!
|
||||
|
||||
choice.test_drive_package_choice_teachers.each do |teacher_choice|
|
||||
booking = LessonBooking.book_packaged_test_drive(self, teacher_choice.teacher, "Please suggest a time that works for you.", choice)
|
||||
if booking.errors.any?
|
||||
raise "unable to create booking in package user:#{self.email}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# throws ActiveRecord::RecordNotFound if instrument is invalid
|
||||
# throws an email delivery error if unable to connect out to SMTP
|
||||
def self.signup(options)
|
||||
|
|
@ -1107,6 +1130,9 @@ module JamRuby
|
|||
school_id = options[:school_id]
|
||||
school_interest = options[:school_interest]
|
||||
origin = options[:origin]
|
||||
test_drive_package_details = options[:test_drive_package]
|
||||
|
||||
test_drive_package = TestDrivePackage.find_by_name(test_drive_package_details[:name])
|
||||
|
||||
school = School.find(school_id) if school_id
|
||||
user = User.new
|
||||
|
|
@ -1351,6 +1377,7 @@ module JamRuby
|
|||
user.save
|
||||
end if affiliate_referral_id.present?
|
||||
|
||||
user.handle_test_drive_package(test_drive_package, test_drive_package_details) if test_drive_package
|
||||
|
||||
if user.is_a_student
|
||||
UserMailer.student_welcome_message(user).deliver
|
||||
|
|
@ -1981,9 +2008,10 @@ module JamRuby
|
|||
customer
|
||||
end
|
||||
|
||||
def card_approved(token, zip, booking_id)
|
||||
def card_approved(token, zip, booking_id, test_drive_package_choice_id = nil)
|
||||
|
||||
approved_booking = nil
|
||||
choice = nil
|
||||
found_uncollectables = nil
|
||||
User.transaction do
|
||||
self.stripe_token = token if token
|
||||
|
|
@ -1999,6 +2027,13 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
if test_drive_package_choice_id
|
||||
choice = TestDrivePackageChoice.find(test_drive_package_choice_id)
|
||||
choice.lesson_bookings.each do|booking|
|
||||
booking.card_approved
|
||||
end
|
||||
end
|
||||
|
||||
if uncollectables.count > 0
|
||||
found_uncollectables = uncollectables
|
||||
uncollectables.update_all(billing_should_retry: true)
|
||||
|
|
@ -2007,7 +2042,7 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
end
|
||||
[approved_booking, found_uncollectables]
|
||||
[approved_booking, found_uncollectables, choice]
|
||||
end
|
||||
|
||||
def update_name(name)
|
||||
|
|
@ -2038,6 +2073,7 @@ module JamRuby
|
|||
purchase = nil
|
||||
lesson_package_type = nil
|
||||
uncollectables = nil
|
||||
choice = nil
|
||||
User.transaction do
|
||||
|
||||
if params[:name].present?
|
||||
|
|
@ -2046,12 +2082,15 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
booking, uncollectables = card_approved(params[:token], params[:zip], params[:booking_id])
|
||||
booking, uncollectables, choice = card_approved(params[:token], params[:zip], params[:booking_id], params[:test_drive_package_choice_id])
|
||||
if params[:test_drive]
|
||||
self.reload
|
||||
if booking
|
||||
lesson_package_type = booking.resolved_test_drive_package
|
||||
elsif choice
|
||||
choice.test_drive_package.lesson_package_type
|
||||
end
|
||||
|
||||
if lesson_package_type.nil?
|
||||
lesson_package_type = LessonPackageType.test_drive_4
|
||||
end
|
||||
|
|
@ -2071,7 +2110,7 @@ module JamRuby
|
|||
|
||||
end
|
||||
|
||||
{lesson: booking, test_drive: test_drive, purchase: purchase, lesson_package_type: lesson_package_type, uncollectables: uncollectables}
|
||||
{lesson: booking, test_drive: test_drive, purchase: purchase, lesson_package_type: lesson_package_type, uncollectables: uncollectables, package: choice}
|
||||
end
|
||||
|
||||
def requested_test_drive(teacher = nil)
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ FactoryGirl.define do
|
|||
association :user, factory: :user
|
||||
price_per_lesson_60_cents 3000
|
||||
price_per_month_60_cents 3000
|
||||
short_bio 'abc def uueue doc neck'
|
||||
end
|
||||
|
||||
factory :musician_instrument, :class => JamRuby::MusicianInstrument do
|
||||
|
|
|
|||
|
|
@ -905,6 +905,30 @@ describe User do
|
|||
uncollectable.is_card_declined?.should be_false
|
||||
end
|
||||
end
|
||||
describe "handle_test_drive_package" do
|
||||
let(:user) {FactoryGirl.create(:user)}
|
||||
|
||||
it "4-count" do
|
||||
package_size = 4
|
||||
package = FactoryGirl.create(:test_drive_package, :four_pack)
|
||||
detail = {}
|
||||
teachers = []
|
||||
detail[:teachers] = teachers
|
||||
package.test_drive_package_teachers.each do |package_teacher|
|
||||
teachers << {id: package_teacher.user.id}
|
||||
end
|
||||
user.handle_test_drive_package(package, detail)
|
||||
|
||||
user.errors.any?.should be_false
|
||||
|
||||
LessonSession.where(user_id: user.id).count.should eql package_size
|
||||
user.student_lesson_bookings.count.should eql package_size
|
||||
user.student_lesson_bookings.each do |booking|
|
||||
booking.status.should eql LessonBooking::STATUS_REQUESTED
|
||||
booking.card_presumed_ok.should be_false
|
||||
end
|
||||
end
|
||||
end
|
||||
=begin
|
||||
describe "update avatar" do
|
||||
|
||||
|
|
|
|||
|
|
@ -271,7 +271,6 @@
|
|||
|
||||
var show = false;
|
||||
|
||||
console.log("data.newScreen", data.newScreen)
|
||||
if (data.newScreen && activate.indexOf(data.newScreen) > -1) {
|
||||
show = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -237,6 +237,8 @@
|
|||
}
|
||||
|
||||
helpBubble.testDrivePackageGo = function($element, $offsetParent, package_type) {
|
||||
return context.JK.prodBubble($element, 'test-drive-package-go', {plural: package_type != '1'}, bigHelpDarkOptions({offsetParent:$offsetParent, width:260, positions:['bottom']}))
|
||||
return context.JK.prodBubble($element, 'test-drive-package-go', {plural: package_type != '1'}, bigHelpDarkOptions({offsetParent:$offsetParent, width:300, duration:13000, positions:['bottom'], postShow: function(container) {
|
||||
subtlePulse(container)
|
||||
}}))
|
||||
}
|
||||
})(window, jQuery);
|
||||
|
|
@ -2133,6 +2133,15 @@
|
|||
})
|
||||
}
|
||||
|
||||
function getTestDrivePackageChoice(options) {
|
||||
options = options || {}
|
||||
return $.ajax({
|
||||
type: "GET",
|
||||
url: '/api/test_drive_package_choice/' + options.id,
|
||||
dataType: "json",
|
||||
contentType: 'application/json'
|
||||
})
|
||||
}
|
||||
|
||||
function getLessonBooking(options) {
|
||||
options = options || {}
|
||||
|
|
@ -2717,6 +2726,7 @@
|
|||
this.portOverCarts = portOverCarts;
|
||||
this.bookLesson = bookLesson;
|
||||
this.attachRecordingToLesson = attachRecordingToLesson;
|
||||
this.getTestDrivePackageChoice = getTestDrivePackageChoice;
|
||||
this.getLessonBooking = getLessonBooking;
|
||||
this.getUnprocessedLesson = getUnprocessedLesson;
|
||||
this.getUnprocessedLessonOrIntent = getUnprocessedLessonOrIntent;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@
|
|||
//= require jquery.ba-bbq
|
||||
//= require jquery.icheck
|
||||
//= require jquery.exists
|
||||
//= require jquery.manageVsts
|
||||
//= require jquery.lessonSessionActions
|
||||
//= require ResizeSensor
|
||||
//= require AAA_Log
|
||||
//= require AAC_underscore
|
||||
//= require alert
|
||||
|
|
@ -35,6 +38,7 @@
|
|||
//= require ui_helper
|
||||
//= require jam_rest
|
||||
//= require ga
|
||||
//= require recordingModel
|
||||
//= require web/signup_helper
|
||||
//= require web/signin_helper
|
||||
//= require web/signin
|
||||
|
|
|
|||
|
|
@ -114,7 +114,10 @@ LessonTimerActions = context.LessonTimerActions
|
|||
text: "Start time for session set to 65 mins ago"
|
||||
})))
|
||||
else if data.lessonAction == 'enter-payment'
|
||||
window.location.href = "/client#/jamclass/lesson-payment/lesson-booking_#{lessonId}"
|
||||
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}"
|
||||
else
|
||||
context.JK.showAlert('unknown lesson action', 'The option in the menu is unknown')
|
||||
|
||||
|
|
@ -527,7 +530,10 @@ LessonTimerActions = context.LessonTimerActions
|
|||
else
|
||||
unreadMessages = null
|
||||
|
||||
if lessonData.status == 'countered'
|
||||
if lessonData.lesson_booking.no_slots
|
||||
timeStmt = 'No time has been scheduled yet'
|
||||
|
||||
else if lessonData.status == 'countered'
|
||||
timeStmt = lessonData.counter_slot.pretty_scheduled_start_with_timezone
|
||||
else
|
||||
timeStmt = lessonData.music_session.pretty_scheduled_start_with_timezone
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ UserStore = context.UserStore
|
|||
slot.creatorRoleRelative = "your"
|
||||
slot.mySlot = @mySlot(slot)
|
||||
|
||||
# for a test drive packaged delai, while we do create a slot to satisfy certain aspects of the backend, it's not 'real'. So we say 'noSlots' until someone has proposed something
|
||||
noSlots: () ->
|
||||
@state.booking?.no_slots
|
||||
|
||||
processBooking:(booking) ->
|
||||
booking.neverAccepted = booking.accepter_id?
|
||||
booking.isCounter = booking.counter_slot? && booking.status != 'canceled' && booking.status != 'suspended'
|
||||
|
|
@ -58,6 +62,7 @@ UserStore = context.UserStore
|
|||
booking.isRequested = booking.status == 'requested' && !booking.isCounter
|
||||
booking.isCanceled = booking.status == 'canceled'
|
||||
booking.isSuspended = booking.status == 'suspended'
|
||||
|
||||
if booking.isCounter
|
||||
if booking.counter_slot['is_teacher_created?']
|
||||
booking.countererId = booking.teacher_id
|
||||
|
|
@ -472,7 +477,10 @@ UserStore = context.UserStore
|
|||
|
||||
selfLastToAct: () ->
|
||||
if @isRequested()
|
||||
@studentViewing()
|
||||
if @isCounter()
|
||||
@counterer().id == @myself().id
|
||||
else
|
||||
@studentViewing()
|
||||
else if @isCounter()
|
||||
@counterer().id == @myself().id
|
||||
else if @isCanceled()
|
||||
|
|
@ -647,7 +655,8 @@ UserStore = context.UserStore
|
|||
selfLastToAct: this.selfLastToAct(),
|
||||
counterErrors: this.state.counterErrors,
|
||||
cancelErrors: this.state.cancelErrors,
|
||||
focusedLesson: this.focusedLesson()
|
||||
focusedLesson: this.focusedLesson(),
|
||||
noSlots: this.noSlots()
|
||||
}
|
||||
|
||||
render: () ->
|
||||
|
|
@ -813,9 +822,15 @@ UserStore = context.UserStore
|
|||
createDetail: () ->
|
||||
if @hasFocusedLesson() || !@isRecurring()
|
||||
if @onlyOption() && @rescheduling()
|
||||
detail = `<p className="proposing-new-time">You are proposing to change the date/time of the lesson currently scheduled for {this.slotTime(this.state.booking.default_slot)}</p>`
|
||||
if @noSlots()
|
||||
detail = `<p className="proposing-new-time no-slot">You are proposing a date/time for this lesson.</p>`
|
||||
else
|
||||
detail = `<p className="proposing-new-time">You are proposing to change the date/time of the lesson currently scheduled for {this.slotTime(this.state.booking.default_slot)}</p>`
|
||||
else
|
||||
detail = `<p className="generic-time-stmt">Your {this.lessonDesc()} will take place this {this.slotTime(this.state.booking.default_slot)}</p>`
|
||||
if @noSlots()
|
||||
detail = `<p className="generic-time-stmt no-slot">Your lesson has no scheduled time yet.</p>`
|
||||
else
|
||||
detail = `<p className="generic-time-stmt">Your {this.lessonDesc()} will take place this {this.slotTime(this.state.booking.default_slot)}</p>`
|
||||
else
|
||||
if @onlyOption() && @rescheduling()
|
||||
detail = `<p className="proposing-new-time">You are proposing to change the date/time of the lesson currently scheduled for {this.slotTime(this.state.booking.default_slot)}</p>`
|
||||
|
|
@ -916,13 +931,20 @@ UserStore = context.UserStore
|
|||
else
|
||||
action = `<p className="action">Has requested a {this.lessonDesc()} lesson, for which you will be paid {this.lessonPaymentAmt()}.</p>`
|
||||
|
||||
|
||||
if @noSlots()
|
||||
slots = []
|
||||
else
|
||||
slots = [this.state.booking.default_slot]
|
||||
if this.state.booking.alt_slot?
|
||||
slots.push(this.state.booking.alt_slot)
|
||||
`<div className="contents">
|
||||
<div className="row">
|
||||
{this.userHeader(this.other())}
|
||||
{action}
|
||||
{this.slotMessage(this.state.booking.default_slot)}
|
||||
</div>
|
||||
<LessonBookingDecision {...this.decisionProps([this.state.booking.default_slot, this.state.booking.alt_slot])} />
|
||||
<LessonBookingDecision {...this.decisionProps(slots)} />
|
||||
</div>`
|
||||
|
||||
renderTeacherApproved: () ->
|
||||
|
|
|
|||
|
|
@ -145,7 +145,10 @@
|
|||
|
||||
multipleOptions: () ->
|
||||
if this.props.initial
|
||||
!(!this.props.counter && this.props.selfLastToAct)
|
||||
if this.props.noSlots
|
||||
false
|
||||
else
|
||||
!(!this.props.counter && this.props.selfLastToAct)
|
||||
else if this.props.counter
|
||||
!this.props.selfLastToAct
|
||||
else
|
||||
|
|
@ -156,16 +159,19 @@
|
|||
#showUpdateAll = !this.props.initial
|
||||
|
||||
if (!this.props.initial && !this.props.counter) || this.props.selfLastToAct
|
||||
userPromptHeader = `<h3>Would you like to change this lesson?</h3>`
|
||||
userPromptHeader = `<h3>Would you like to update this lesson?</h3>`
|
||||
messagePromptHeader = `<h3>Send message to {this.props.otherRole} with your update.</h3>`
|
||||
else
|
||||
userPromptHeader = `<h3>How do you want to handle this request?</h3>`
|
||||
messagePromptHeader = `<h3>Send message to {this.props.otherRole} with your response.</h3>`
|
||||
if this.props.slot_decision == 'counter'
|
||||
if this.props.update_all
|
||||
actionBtnText = "PROPOSE ALTERNATE TIME FOR ALL LESSONS"
|
||||
if this.props.is_recurring && this.props.update_all
|
||||
actionBtnText = "PROPOSE TIME FOR ALL LESSONS"
|
||||
else
|
||||
actionBtnText = "PROPOSE ALTERNATE TIME"
|
||||
if @props.noSlots
|
||||
actionBtnText = 'PROPOSE TIME'
|
||||
else
|
||||
actionBtnText = "PROPOSE ALTERNATE TIME"
|
||||
|
||||
else if this.props.slot_decision == 'decline'
|
||||
|
||||
|
|
@ -199,7 +205,7 @@
|
|||
<span className="alt-time-block">
|
||||
<span className="alt-time">Time:</span>
|
||||
<select className="hour">{this.hours}</select> : <select disabled={this.props.disabled} className="minute">{this.minutes}</select>
|
||||
<select className="am_pm">{this.am_pm}</select>
|
||||
<select disabled={this.props.disabled} className="am_pm">{this.am_pm}</select>
|
||||
<br/>
|
||||
<span>* Time will be local to {window.JK.currentTimezone()}</span>
|
||||
{errorText}
|
||||
|
|
@ -239,7 +245,10 @@
|
|||
slots = []
|
||||
|
||||
if !(this.props.counter && this.props.selfLastToAct)
|
||||
proposeAltLabelText = "Propose alternate day/time"
|
||||
if this.props.noSlots
|
||||
proposeAltLabelText = 'Propose a day/time'
|
||||
else
|
||||
proposeAltLabelText = "Propose alternate day/time"
|
||||
for slot, i in @props.slots
|
||||
|
||||
if this.props.is_recurring
|
||||
|
|
@ -255,7 +264,11 @@
|
|||
{slotDetail}
|
||||
</div>`)
|
||||
else
|
||||
proposeAltLabelText = "Propose new alternate day/time"
|
||||
if this.props.noSlots
|
||||
proposeAltLabelText = 'Propose a day/time'
|
||||
else
|
||||
proposeAltLabelText = "Propose new alternate day/time"
|
||||
|
||||
# if you have issued a counter, you should be able to withdraw it
|
||||
# TODO
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ UserStore = context.UserStore
|
|||
billingInUS: true,
|
||||
userWantsUpdateCC: false,
|
||||
"test-drive": false,
|
||||
teacher: null
|
||||
teacher: null,
|
||||
package: null
|
||||
}
|
||||
|
||||
beforeHide: (e) ->
|
||||
|
|
@ -75,6 +76,9 @@ UserStore = context.UserStore
|
|||
rest.getUserDetail({id: parsed.teacher_id}).done((response) => @teacherLoaded(response)).fail((jqXHR) => @failedTeacher(jqXHR))
|
||||
else if parsed['test-drive']
|
||||
logger.debug("test-drive lesson payment; no teacher/booking in context")
|
||||
else if parsed['package-choice']
|
||||
logger.debug("TestDrive package selected " + parsed.package_id)
|
||||
rest.getTestDrivePackageChoice({id: parsed.package_id}).done((response) => @packageLoaded(response)).fail((jqXHR) => @failedPackage(jqXHR))
|
||||
else
|
||||
logger.error("unknown state for lesson-payment")
|
||||
window.location.href = '/client#/jamclass'
|
||||
|
|
@ -92,6 +96,7 @@ UserStore = context.UserStore
|
|||
result['test-drive'] = false
|
||||
result['lesson-booking'] = false
|
||||
result['teacher-intent'] = false
|
||||
result['package-choice'] = false
|
||||
|
||||
bits = id.split('_')
|
||||
if bits.length == 1
|
||||
|
|
@ -105,6 +110,9 @@ UserStore = context.UserStore
|
|||
else if type == 'teacher'
|
||||
result['teacher-intent'] = true
|
||||
result.teacher_id = bits[1]
|
||||
else if type == 'package'
|
||||
result['package-choice'] = true
|
||||
result.package_id = bits[1]
|
||||
|
||||
logger.debug("LessonPayment: parseId " + JSON.stringify(result))
|
||||
|
||||
|
|
@ -119,7 +127,7 @@ UserStore = context.UserStore
|
|||
@setState({billingInUS: checked})
|
||||
|
||||
resetState: () ->
|
||||
@setState({updating: false, lesson: null, teacher: null, "test-drive": false, "lesson-booking" : false, "teacher-intent": false})
|
||||
@setState({updating: false, lesson: null, teacher: null, "test-drive": false, "lesson-booking" : false, "teacher-intent": false, package: null, "package-choice": null})
|
||||
|
||||
lessonBookingLoaded: (response) ->
|
||||
@setState({updating: false})
|
||||
|
|
@ -149,6 +157,18 @@ UserStore = context.UserStore
|
|||
text: 'Something has gone wrong. Please try refreshing the page.'
|
||||
})
|
||||
|
||||
packageLoaded: (response) ->
|
||||
@setState({updating: false})
|
||||
logger.debug("package loaded", response)
|
||||
@setState({package: response})
|
||||
|
||||
failedPackage: (jqXHR) ->
|
||||
@setState({updating: false})
|
||||
@app.layout.notify({
|
||||
title: 'unable to load package info',
|
||||
text: 'Something has gone wrong. Please try refreshing the page.'
|
||||
})
|
||||
|
||||
onBack: (e) ->
|
||||
e.preventDefault()
|
||||
window.location.href = '/client#/teachers/search'
|
||||
|
|
@ -253,7 +273,7 @@ UserStore = context.UserStore
|
|||
@state.lesson?.lesson_type == 'paid'
|
||||
|
||||
isTestDrive: () ->
|
||||
@state['test-drive'] == true || @state.lesson?.lesson_type == 'test-drive' || @state['teacher-intent']
|
||||
@state['test-drive'] == true || @state.lesson?.lesson_type == 'test-drive' || @state['teacher-intent'] || @state['package-choice'] == true
|
||||
|
||||
attemptPurchase: (token) ->
|
||||
if this.state.billingInUS
|
||||
|
|
@ -264,6 +284,7 @@ UserStore = context.UserStore
|
|||
zip: zip,
|
||||
test_drive: @isTestDrive(),
|
||||
booking_id: @state.lesson?.id,
|
||||
test_drive_package_choice_id: @state.package?.id
|
||||
normal: @isNormal()
|
||||
}
|
||||
|
||||
|
|
@ -304,6 +325,8 @@ UserStore = context.UserStore
|
|||
teacher_id = response.test_drive.teacher_id
|
||||
if testDriveCount == '1'
|
||||
text = "You have purchased 1 TestDrive credit and have used it to request a JamClass with #{@state.teacher.name}. The teacher has received your request and should respond shortly."
|
||||
else if response.package?
|
||||
text = "Each teacher has received your request and should respond shortly."
|
||||
else
|
||||
text = "You have purchased #{testDriveCount} TestDrive credits and have used 1 credit to request a JamClass with #{@state.teacher.name}. The teacher has received your request and should respond shortly."
|
||||
location = "/client#/jamclass"
|
||||
|
|
@ -326,7 +349,7 @@ UserStore = context.UserStore
|
|||
text = "You now have #{testDriveCount} TestDrive credits that you can take with #{testDriveCount} different teachers.<br/><br/>We've taken you to the Teacher Search screen, so you can search for teachers right for you."
|
||||
location = "/client#/teachers/search"
|
||||
|
||||
context.JK.Banner.showNotice("Test Drive Purchased",text)
|
||||
context.JK.Banner.showNotice("TestDrive Purchased",text)
|
||||
window.location = location
|
||||
else
|
||||
context.JK.Banner.showNotice("Something Went Wrong", "Please email support@jamkazam.com and indicate that your attempt to buy a TestDrive failed")
|
||||
|
|
@ -392,7 +415,7 @@ UserStore = context.UserStore
|
|||
{name}
|
||||
</div>`
|
||||
else
|
||||
if @state.lesson? || @state['test-drive'] || @state.teacher?
|
||||
if @state.lesson? || @state['test-drive'] || @state.teacher? || @state['package-choice'] == true
|
||||
if @state.teacher?
|
||||
photo_url = @state.teacher.photo_url
|
||||
name = @state.teacher.name
|
||||
|
|
@ -406,6 +429,42 @@ UserStore = context.UserStore
|
|||
</div>
|
||||
{name}
|
||||
</div>`
|
||||
else if @state.package?
|
||||
teachers = []
|
||||
teachersHolder = []
|
||||
count = 0
|
||||
for teacher_choice in @state.package.teachers
|
||||
|
||||
if count == 2
|
||||
teachersHolder.push(
|
||||
`<div className="teacher-holder">
|
||||
{teachers}
|
||||
</div>`)
|
||||
teachers = []
|
||||
teacher = teacher_choice.user
|
||||
photo_url = teacher.photo_url
|
||||
name = teacher.name
|
||||
|
||||
if !photo_url?
|
||||
photo_url = '/assets/shared/avatar_generic.png'
|
||||
|
||||
teachers.push(
|
||||
`<div key={teacher.id} className="teacher-subheader">
|
||||
<div className="avatar">
|
||||
<img src={photo_url}/>
|
||||
</div>
|
||||
<div className="teacher-name-packaged">{teacher.first_name}<br/>{teacher.last_name}</div>
|
||||
</div>`)
|
||||
count++
|
||||
|
||||
teachersHolder.push(
|
||||
`<div className="teacher-holder">
|
||||
{teachers}
|
||||
</div>`)
|
||||
teacherDetails = `<div className="teacher-header packaged">
|
||||
{teachersHolder}
|
||||
<br className="clearall" />
|
||||
</div>`
|
||||
|
||||
if @state.lesson?
|
||||
lesson_length = @state.lesson.lesson_length
|
||||
|
|
@ -415,6 +474,7 @@ UserStore = context.UserStore
|
|||
lesson_type = 'test-drive'
|
||||
|
||||
|
||||
|
||||
if @isTestDrive()
|
||||
|
||||
if @reuseStoredCard()
|
||||
|
|
@ -423,14 +483,26 @@ UserStore = context.UserStore
|
|||
header = `<div><h2>enter payment info for test drive</h2></div>`
|
||||
|
||||
bookingInfo = `<p></p>`
|
||||
if this.state.user.lesson_package_type_id == 'test-drive'
|
||||
explanation = `<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 4 private online music lessons - 1 each from 4 different instructors in the JamClass instructor community. The price of this TestDrive package is $49.99.</span>`
|
||||
else if this.state.user.lesson_package_type_id == 'test-drive-1'
|
||||
explanation =`<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 1 private online music lesson from an instructor in the JamClass instructor community. The price of this TestDrive package is $14.99.</span>`
|
||||
else if this.state.user.lesson_package_type_id == 'test-drive-2'
|
||||
explanation =`<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 2 private online music lessons - 1 each from 2 different instructors in the JamClass instructor community. The price of this TestDrive package is $29.99.</span>`
|
||||
if this.state['package-choice']
|
||||
if this.state.package?
|
||||
|
||||
if @state.package.teachers.length == 1
|
||||
explanation = `<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entities you to take a private online music lesson from this instructor. The price of this TestDrive is $14.99. If you have scheduling conflicts with this instructors, we will help you choose another teacher as a replacement.</span>`
|
||||
else if @state.package.teachers.length == 2
|
||||
explanation = `<span className="explanation">You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entities you to take 2 private online music lessons - 1 each from these 2 instructors. The price of this TestDrive is $29.99. If you have scheduling conflicts with any of these instructors, we will help you choose another teacher as a replacement.</span>`
|
||||
else if @state.package.teachers.length == 4
|
||||
explanation = `<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entities you to take 4 private online music lessons - 1 each from these 4 instructors. The price of this TestDrive is $49.99. If you have scheduling conflicts with any of these instructors, we will help you choose another teacher as a replacement.</span>`
|
||||
else
|
||||
alert("unknown package type")
|
||||
else
|
||||
alert("You do not have a test drive package selected")
|
||||
if this.state.user.lesson_package_type_id == 'test-drive'
|
||||
explanation = `<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 4 private online music lessons - 1 each from 4 different instructors in the JamClass instructor community. The price of this TestDrive package is $49.99.</span>`
|
||||
else if this.state.user.lesson_package_type_id == 'test-drive-1'
|
||||
explanation =`<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 1 private online music lesson from an instructor in the JamClass instructor community. The price of this TestDrive package is $14.99.</span>`
|
||||
else if this.state.user.lesson_package_type_id == 'test-drive-2'
|
||||
explanation =`<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 2 private online music lessons - 1 each from 2 different instructors in the JamClass instructor community. The price of this TestDrive package is $29.99.</span>`
|
||||
else
|
||||
alert("You do not have a test drive package selected")
|
||||
|
||||
|
||||
bookingDetail = `<p>{explanation}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,33 @@ context = window
|
|||
|
||||
getInitialState: () ->
|
||||
{
|
||||
target: null,
|
||||
page_data: null
|
||||
target: null,
|
||||
page_data: null
|
||||
}
|
||||
|
||||
|
||||
componentDidMount: () ->
|
||||
@root = $(@getDOMNode())
|
||||
@dialog = @root.closest('.dialog')
|
||||
|
||||
renderTeacher: (teacher) ->
|
||||
photo_url = '/assets/shared/avatar_generic.png'
|
||||
if teacher.photo_url?
|
||||
photo_url = teacher.photo_url
|
||||
|
||||
`<div className="teacher-select">
|
||||
<div className="avatar">
|
||||
<img src={photo_url}/>
|
||||
</div>
|
||||
<div className="username">
|
||||
{teacher.first_name}
|
||||
<br/>
|
||||
{teacher.last_name}
|
||||
</div>
|
||||
<div className="checkbox-wrapper">
|
||||
<input type="checkbox" name="teacher-select" data-teacher-id={teacher.id}/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
doCancel: (e) ->
|
||||
e.preventDefault()
|
||||
|
|
@ -43,55 +63,66 @@ context = window
|
|||
checked = @root.find('input[type="checkbox"]:checked')
|
||||
|
||||
if checked.length != 2
|
||||
context.JK.Banner.showNotice('hold on there', 'Please select 2 teachers.')
|
||||
window.JK.Banner.showAlert('hold on there', 'Please select 2 teachers.')
|
||||
return
|
||||
|
||||
if @state.target == '1'
|
||||
checked = @root.find('input[type="checkbox"]:checked')
|
||||
|
||||
if checked.length != 1
|
||||
context.JK.Banner.showNotice('hold on there', 'Please select a teacher.')
|
||||
window.JK.Banner.showAlert('hold on there', 'Please select 1 teacher.')
|
||||
return
|
||||
|
||||
teachers = []
|
||||
|
||||
console.log("STATE TIME", @state)
|
||||
if @state.page_data?.package?.teachers?
|
||||
for teacher in @state.page_data.package.teachers
|
||||
teachers.push(@teacher(teacher.name, teacher.photo_url, teacher.id))
|
||||
|
||||
$.each(checked, (i, node) => (
|
||||
$node = $(node)
|
||||
teachers.push($node.data('teacher'))
|
||||
teacherId = $node.attr('data-teacher-id')
|
||||
for teacher in @state.page_data.package.teachers
|
||||
if teacher.id == teacherId
|
||||
teachers.push(teacher)
|
||||
break
|
||||
))
|
||||
@root.data('result', { package_type: @state.target, teachers: teachers })
|
||||
@dialog.data('result', {package_type: @state.target, teachers: teachers})
|
||||
@app.layout.closeDialog('test-drive-package-dialog')
|
||||
render: () ->
|
||||
|
||||
if @state.target == '2'
|
||||
help =
|
||||
`<p>
|
||||
Check the boxes under the 2 instructors you want to select for your TestDrive package. Then click the Select button below.
|
||||
Check the boxes under the 2 instructors you want to select for your TestDrive package. Then click the Select
|
||||
button below.
|
||||
</p>`
|
||||
else
|
||||
help =
|
||||
help =
|
||||
`<p>
|
||||
Check the box under the instructor you want to select for your TestDrive package. Then click the Select button below.
|
||||
Check the box under the instructor you want to select for your TestDrive package. Then click the Select button
|
||||
below.
|
||||
</p>`
|
||||
|
||||
teachers = []
|
||||
|
||||
if @state.page_data?.package?.teachers?
|
||||
for teacher in @state.page_data.package.teachers
|
||||
teachers.push(@renderTeacher(teacher))
|
||||
|
||||
teacherHolderClasses = {"teacher-holder" : true, "two": teachers.length == 2, "four": teachers.length == 4}
|
||||
dialogInnerClasses = {"dialog-inner": true, "two": teachers.length == 2, "four": teachers.length == 4}
|
||||
`<div>
|
||||
<div className="content-head">
|
||||
<img className="content-icon" src="/assets/content/icon_add.png" height={19} width={19}/>
|
||||
|
||||
<h1>select instructors</h1>
|
||||
</div>
|
||||
<div className="dialog-inner">
|
||||
<div className={classNames(dialogInnerClasses)}>
|
||||
|
||||
{help}
|
||||
|
||||
{teachers}
|
||||
<div className={classNames(teacherHolderClasses)}>
|
||||
{teachers}
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="actions">
|
||||
<a onClick={this.doCancel} className="button-grey">CANCEL</a>
|
||||
|
|
|
|||
|
|
@ -20,15 +20,23 @@
|
|||
selector: (count, e) ->
|
||||
e.preventDefault()
|
||||
|
||||
context.JK.app.layout.showDialog('test-drive-package-dialog').one(contexnt.JK.EVENTS.DIALOG_CLOSED, (e, data) =>
|
||||
# cheesy way to pass the page data to the dialog
|
||||
window.page_data = @props
|
||||
|
||||
window.JK.app.layout.showDialog('test-drive-package-dialog', {d1: count.toString()}).one(window.JK.EVENTS.DIALOG_CLOSED, (e, data) =>
|
||||
#... code
|
||||
if !data.canceled
|
||||
console.log("dialog closed. result", data.result)
|
||||
console.log("dialog closed. result", data)
|
||||
# dialog wasn't cancelled, so let's check the value of our result:
|
||||
@setState(data.result)
|
||||
@setState({modified: true})
|
||||
|
||||
window.teacherModifications = data.result.teachers
|
||||
|
||||
setTimeout((() => context.JK.prodBubble($('.preview-area.jam-class'), 'body', data.result.package_type)), 1500)
|
||||
$ctaBox = $('.preview-area.jam-class')
|
||||
$.scrollTo($ctaBox, {duration: 500, offset: 0})
|
||||
|
||||
setTimeout((() => window.JK.HelpBubbleHelper.testDrivePackageGo($ctaBox, 'body', data.result.package_type)), 2500)
|
||||
)
|
||||
|
||||
componentDidMount: () ->
|
||||
|
|
@ -59,7 +67,7 @@
|
|||
`<div className="other-options">
|
||||
<p>Like the TestDrive concept, but 4 teachers is too many for you?</p>
|
||||
<ul>
|
||||
<li>Get a special offer of <a onClick={this.selector.bind(this, 2)}>2 of these teachers for a total of $29.99</a>.</li>
|
||||
<li>Get a special offer of <a className="pick-two" onClick={this.selector.bind(this, 2)}>2 of these teachers for a total of $29.99</a>.</li>
|
||||
<li>Or <a onClick={this.selector.bind(this, 1)}>1 teacher for $14.99</a>.</li>
|
||||
<li>Or you can <a href="/client#/jamclass/searchOptions">search all of our teachers</a> and then book a TestDrive package.</li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,34 @@ rest = context.JK.Rest()
|
|||
onClick={this.ctaClick}>{ctaButtonText}</button>
|
||||
</form>
|
||||
</div>`
|
||||
if @props.package?
|
||||
ctaBoxContents = `<div className={classNames({'preview-area': true, 'jam-class': true})}>
|
||||
<p>Sign up for this amazing TestDrive offer now!</p>
|
||||
|
||||
<p>When you sign up below, we will ask you to pay for your TestDrive package, and then we'll forward
|
||||
your lesson requests to these teachers for scheduling.</p>
|
||||
|
||||
<p>We will not share your email. See our <a href="/corp/privacy" onClick={this.privacyPolicy}>privacy
|
||||
policy</a></p>
|
||||
{register}
|
||||
<p>We'll give you 1:1 help to get set up and ready to go with our free app.</p>
|
||||
</div>`
|
||||
else
|
||||
|
||||
ctaBoxContents = `<div className={classNames({'preview-area': true, 'jam-class': true})}>
|
||||
<p>Sign up now. You have no obligation to buy anything. Signing up makes you eligible for our TestDrive
|
||||
offers.</p>
|
||||
|
||||
<p>After signing up, you can search our community of world-class instructors. If you book a TestDrive lesson
|
||||
you can choose to TestDrive 4, 2, or 1 teachers at that time.</p>
|
||||
|
||||
<p>We will not share your email. See our <a href="/corp/privacy" onClick={this.privacyPolicy}>privacy
|
||||
policy</a></p>
|
||||
{register}
|
||||
<p>And pick your teachers now!</p>
|
||||
|
||||
<p>We'll give you 1:1 help to get set up and ready to go with our free app.</p>
|
||||
</div>`
|
||||
|
||||
`<div className="top-container">
|
||||
<div className="full-row name-and-artist">
|
||||
|
|
@ -71,20 +98,7 @@ rest = context.JK.Rest()
|
|||
<div className="preview-jamtrack-header">
|
||||
Sign Up for TestDrive
|
||||
</div>
|
||||
<div className={classNames({'preview-area': true, 'jam-class': true})}>
|
||||
<p>Sign up now. You have no obligation to buy anything. Signing up makes you eligible for our TestDrive
|
||||
offers.</p>
|
||||
|
||||
<p>After signing up, you can search our community of world-class instructors. If you book a TestDrive lesson
|
||||
you can choose to TestDrive 4, 2, or 1 teachers at that time.</p>
|
||||
|
||||
<p>We will not share your email. See our <a href="/corp/privacy" onClick={this.privacyPolicy}>privacy
|
||||
policy</a></p>
|
||||
{register}
|
||||
<p>And pick your teachers now!</p>
|
||||
|
||||
<p>We'll give you 1:1 help to get set up and ready to go with our free app.</p>
|
||||
</div>
|
||||
{ctaBoxContents}
|
||||
</div>
|
||||
</div>
|
||||
<div className="row summary-text">
|
||||
|
|
@ -156,10 +170,28 @@ rest = context.JK.Rest()
|
|||
password = $form.find('input[name="password"]').val()
|
||||
terms = $form.find('input[name="terms"]').is(':checked')
|
||||
|
||||
rest.signup({email: email, password: password, first_name: null, last_name: null, terms: terms, student: true})
|
||||
test_drive_package = null
|
||||
|
||||
if @props.package
|
||||
test_drive_package ={}
|
||||
if window.teacherModifications?
|
||||
teachers = window.window.teacherModifications
|
||||
else
|
||||
teachers = @props.package.teachers
|
||||
test_drive_package.name = @props.package.name
|
||||
test_drive_package.teachers = teachers
|
||||
|
||||
rest.signup({email: email, password: password, first_name: null, last_name: null, terms: terms, student: true, test_drive_package: test_drive_package})
|
||||
.done((response) =>
|
||||
@setState({done: true})
|
||||
context.location = '/client#/jamclass/searchOptions'
|
||||
if test_drive_package?
|
||||
choice = response.test_drive_package_choices?[0]
|
||||
if choice?
|
||||
context.location = '/client#/jamclass/lesson-payment/package_' + choice.id
|
||||
else
|
||||
context.location = '/client#/jamclass/searchOptions'
|
||||
else
|
||||
context.location = '/client#/jamclass/searchOptions'
|
||||
).fail((jqXHR) =>
|
||||
@setState({processing: false})
|
||||
if jqXHR.status == 422
|
||||
|
|
|
|||
|
|
@ -23,7 +23,11 @@
|
|||
//= require jquery.exists
|
||||
//= require jquery.visible
|
||||
//= require jquery.lessonSessionActions
|
||||
//= require jquery.manageVsts
|
||||
//= require jquery.scrollTo
|
||||
//= require jquery.pulse
|
||||
//= require howler.core.js
|
||||
//= require ResizeSensor
|
||||
//= require AAA_Log
|
||||
//= require AAC_underscore
|
||||
//= require alert
|
||||
|
|
@ -59,6 +63,7 @@
|
|||
//= require jam_track_preview
|
||||
//= require landing/init
|
||||
//= require landing/signup
|
||||
//= require recordingModel
|
||||
//= require web/downloads
|
||||
//= require web/congratulations
|
||||
//= require web/sessions
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@import "client/common";
|
||||
|
||||
//body.jam, body.web, .dialog{
|
||||
html {
|
||||
html body {
|
||||
.bt-wrapper {
|
||||
font-size: 14px;
|
||||
font-family: 'Raleway', Arial, Helvetica, sans-serif;
|
||||
|
|
@ -15,6 +15,8 @@ html {
|
|||
margin:1em;
|
||||
line-height:150%;
|
||||
font-size:14px;
|
||||
width:auto;
|
||||
@include border_box_sizing;
|
||||
}
|
||||
ul {
|
||||
font-size:14px;
|
||||
|
|
@ -153,6 +155,9 @@ html {
|
|||
width:180px;
|
||||
}
|
||||
|
||||
.test-drive-package-go {
|
||||
width:300px;
|
||||
}
|
||||
|
||||
.help-hover-recorded-tracks, .help-hover-stream-mix, .help-hover-recorded-backing-tracks {
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,27 @@
|
|||
-moz-border-radius:24px;
|
||||
border-radius:24px;
|
||||
}
|
||||
.teacher-subheader {
|
||||
.avatar {
|
||||
margin:10px 0 0 0;
|
||||
}
|
||||
float:left;
|
||||
width:100px;
|
||||
text-align:center;
|
||||
}
|
||||
.teacher-holder {
|
||||
display:inline-block;
|
||||
}
|
||||
.teacher-header {
|
||||
&.packaged {
|
||||
margin:40px 0 20px 0;
|
||||
text-align:center;
|
||||
}
|
||||
}
|
||||
.teacher-name-packaged {
|
||||
color:$ColorTextTypical;
|
||||
overflow: hidden;
|
||||
}
|
||||
.teacher-name {
|
||||
font-size:16px;
|
||||
display:inline-block;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
@import "client/common";
|
||||
|
||||
#test-drive-package-dialog {
|
||||
//width: 700px;
|
||||
min-width:400px;
|
||||
width:auto;
|
||||
|
||||
h3 {
|
||||
color:white;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
.dialog-inner {
|
||||
width: auto;
|
||||
&.two {
|
||||
width:400px;
|
||||
}
|
||||
&.four {
|
||||
width:600px;
|
||||
}
|
||||
height:100%;
|
||||
@include border_box_sizing;
|
||||
margin-top: -29px;
|
||||
padding: 50px 25px 25px;
|
||||
}
|
||||
|
||||
div[data-react-class="TestDrivePackageDialog"] {
|
||||
|
||||
}
|
||||
.TestDrivePackageDialog {
|
||||
height:100%;
|
||||
}
|
||||
.teacher-select {
|
||||
float:left;
|
||||
}
|
||||
.actions {
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.teacher-select {
|
||||
width: 120px;
|
||||
text-align:center;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
display: inline-block;
|
||||
text-align:center;
|
||||
padding: 1px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
background-color: #ed4818;
|
||||
margin: 4px 0px 7px 0;
|
||||
-webkit-border-radius: 24px;
|
||||
-moz-border-radius: 24px;
|
||||
border-radius: 24px;
|
||||
float: none;
|
||||
|
||||
}
|
||||
.avatar img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
-webkit-border-radius: 24px;
|
||||
-moz-border-radius: 24px;
|
||||
border-radius: 24px;
|
||||
|
||||
}
|
||||
|
||||
.username {
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.teacher-holder {
|
||||
text-align:center;
|
||||
margin:auto;
|
||||
margin-top:20px;
|
||||
|
||||
&.two {
|
||||
width:242px;
|
||||
}
|
||||
|
||||
&.four {
|
||||
width:482px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -512,7 +512,7 @@ body.web.individual_jamtrack {
|
|||
|
||||
p {
|
||||
line-height: 150%;
|
||||
width: 100% !important;
|
||||
width: 100% ;
|
||||
}
|
||||
|
||||
.bottom-banner {
|
||||
|
|
@ -1056,6 +1056,14 @@ body.web.individual_jamtrack {
|
|||
}
|
||||
|
||||
}
|
||||
.other-options {
|
||||
margin-top:20px;
|
||||
border:1px solid $copy-color-on-dark;
|
||||
padding:20px;
|
||||
ul {
|
||||
margin-bottom:0;
|
||||
}
|
||||
}
|
||||
.teacher-option {
|
||||
margin-bottom:20px;
|
||||
height: 98px;
|
||||
|
|
@ -1078,6 +1086,7 @@ body.web.individual_jamtrack {
|
|||
display: inline-block;
|
||||
width: 140px;
|
||||
margin-right: 20px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
|
|
@ -1087,7 +1096,7 @@ body.web.individual_jamtrack {
|
|||
width: 64px;
|
||||
height: 64px;
|
||||
background-color: #ed4818;
|
||||
margin: 4px 8px 7px 0;
|
||||
margin: 4px 0px 7px 0;
|
||||
-webkit-border-radius: 32px;
|
||||
-moz-border-radius: 32px;
|
||||
border-radius: 32px;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ p, div {
|
|||
white-space: normal;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
position:fixed !important;
|
||||
}
|
||||
|
||||
body.web {
|
||||
background-repeat: repeat-x;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
*= require web/downloads
|
||||
*= require users/signinCommon
|
||||
*= require dialogs/dialog
|
||||
*= require client/help
|
||||
*= require landings/partner_agreement_v1
|
||||
*= require web/affiliate_links
|
||||
*= require_directory ../landings
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@ class ApiLessonBookingsController < ApiController
|
|||
|
||||
end
|
||||
|
||||
def show_choice
|
||||
@choice = TestDrivePackageChoice.find(params[:id])
|
||||
|
||||
raise JamPermissionError, "You do not have permission to this data" if @choice.user != current_user
|
||||
end
|
||||
|
||||
def create
|
||||
|
||||
if params[:lesson_type] == LessonBooking::LESSON_TYPE_FREE
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class ApiStripeController < ApiController
|
|||
@normal = data[:normal]
|
||||
@lesson_package_type = data[:lesson_package_type]
|
||||
@uncollectables = data[:uncollectables]
|
||||
@package = data[:package]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -93,7 +93,8 @@ class ApiUsersController < ApiController
|
|||
school_id: params[:school_id],
|
||||
school_interest: params[:school_interest],
|
||||
affiliate_referral_id: cookies[:affiliate_visitor],
|
||||
origin: origin_cookie
|
||||
origin: origin_cookie,
|
||||
test_drive_package: params[:test_drive_package]
|
||||
}
|
||||
|
||||
options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options)
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class LandingsController < ApplicationController
|
|||
teachers = []
|
||||
package.test_drive_package_teachers.each do |package_teacher|
|
||||
teacher = package_teacher.user
|
||||
teachers.push({id: teacher.id, name: teacher.name, biography: teacher.teacher.biography, photo_url: teacher.photo_url})
|
||||
teachers.push({id: teacher.id, name: teacher.name, first_name: teacher.first_name,last_name: teacher.last_name, biography: teacher.teacher.short_bio, photo_url: teacher.photo_url})
|
||||
end
|
||||
package_data[:teachers] = teachers
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
object @lesson_booking
|
||||
|
||||
attributes :id, :status, :lesson_type, :payment_style, :recurring, :teacher_id, :description, :lesson_length, :created_at, :user_id, :active, :accepter_id, :canceler_id, :cancel_message, :booked_price, :card_presumed_ok
|
||||
attributes :id, :status, :lesson_type, :payment_style, :recurring, :teacher_id, :description, :lesson_length, :created_at, :user_id, :active, :accepter_id, :canceler_id, :cancel_message, :booked_price, :card_presumed_ok, :no_slots
|
||||
|
||||
child(:lesson_booking_slots => :slots) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
}
|
||||
|
||||
child(:default_slot => :default_slot) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
}
|
||||
|
||||
child(:alt_slot => :alt_slot) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
}
|
||||
|
||||
child(:counter_slot => :counter_slot) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
object @choice
|
||||
|
||||
attributes :id
|
||||
|
||||
child(:test_drive_package => :package) {
|
||||
attributes :package_type
|
||||
}
|
||||
|
||||
child(:test_drive_package_choice_teachers => :teachers) {
|
||||
child(:teacher) {
|
||||
attributes :id, :first_name, :last_name, :name, :photo_url
|
||||
}
|
||||
}
|
||||
|
|
@ -14,13 +14,13 @@ end
|
|||
|
||||
child(:lesson_booking => :lesson_booking) {
|
||||
|
||||
attributes :card_presumed_ok
|
||||
attributes :card_presumed_ok, :test_drive_package_choice_id, :no_slots
|
||||
|
||||
}
|
||||
|
||||
|
||||
child(:counter_slot => :counter_slot) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
node :pretty_scheduled_start_with_timezone do |slot|
|
||||
pretty_scheduled_start_slot(slot, true)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,6 +14,13 @@ if @test_drive
|
|||
end
|
||||
|
||||
|
||||
if @package
|
||||
node :package do |lesson|
|
||||
{id: @package.id}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if @normal
|
||||
node :normal do |lesson|
|
||||
{teacher_id: @normal.teacher_id}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ if current_user && @user == current_user
|
|||
attributes :uid, :provider, :token_expiration
|
||||
end
|
||||
|
||||
child :test_drive_package_choices do |choice|
|
||||
attributes :id
|
||||
end
|
||||
|
||||
node :geoiplocation do |user|
|
||||
geoiplocation = current_user.geoiplocation
|
||||
geoiplocation.info if geoiplocation
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
<%= render "clients/footer" %>
|
||||
</div>
|
||||
|
||||
<%= render "clients/lessonSessionActions" %>
|
||||
<%= render "clients/manageVsts" %>
|
||||
<%= render 'dialogs/dialogs' %>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
<%= render "clients/jam_track_preview" %>
|
||||
<%= render "clients/help" %>
|
||||
<%= render "clients/lessonSessionActions" %>
|
||||
<%= render "clients/manageVsts" %>
|
||||
<%= render 'dialogs/dialogs' %>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
|
@ -147,6 +148,8 @@
|
|||
JK.genres = genres;
|
||||
});
|
||||
|
||||
AppActions.appInit.trigger(JK.app)
|
||||
|
||||
JK.JamServer.connect() // singleton here defined in JamServer.js
|
||||
.done(function() {
|
||||
console.log("websocket connected")
|
||||
|
|
|
|||
|
|
@ -707,6 +707,7 @@ SampleApp::Application.routes.draw do
|
|||
match '/lesson_bookings/:id/counter' => 'api_lesson_bookings#counter', :via => :post
|
||||
match '/lesson_bookings/:id/cancel' => 'api_lesson_bookings#cancel', :via => :post
|
||||
match '/lesson_bookings/:id' => 'api_lesson_bookings#show', :via => :get
|
||||
match '/test_drive_package_choice/:id' => 'api_lesson_bookings#show_choice', :via => :get
|
||||
|
||||
|
||||
match '/schools/:id' => 'api_schools#show', :via => :get
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class UserManager < BaseManager
|
|||
school_id = options[:school_id]
|
||||
school_interest = options[:school_interest]
|
||||
origin = options[:origin]
|
||||
test_drive_package = options[:test_drive_package]
|
||||
|
||||
recaptcha_failed = false
|
||||
unless options[:skip_recaptcha] # allow callers to opt-of recaptcha
|
||||
|
|
@ -86,7 +87,8 @@ class UserManager < BaseManager
|
|||
school_invitation_code: school_invitation_code,
|
||||
school_id: school_id,
|
||||
school_interest: school_interest,
|
||||
origin: origin)
|
||||
origin: origin,
|
||||
test_drive_package: test_drive_package)
|
||||
user
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ FactoryGirl.define do
|
|||
association :user, factory: :user
|
||||
price_per_lesson_60_cents 3000
|
||||
price_per_month_60_cents 3000
|
||||
short_bio "It's gonna be a blast!"
|
||||
end
|
||||
|
||||
factory :musician_instrument, :class=> JamRuby::MusicianInstrument do
|
||||
|
|
@ -1004,4 +1005,53 @@ FactoryGirl.define do
|
|||
ready false
|
||||
amount_in_cents 1000
|
||||
end
|
||||
|
||||
|
||||
factory :test_drive_package, class: "JamRuby::TestDrivePackage" do
|
||||
|
||||
sequence(:name) { |n| "package-#{n}" }
|
||||
|
||||
trait :one_pack do
|
||||
package_type 1
|
||||
after(:create) do |package, evaluator|
|
||||
1.times.each do
|
||||
FactoryGirl.create(:test_drive_package_teachers, test_drive_package: package)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
trait :two_pack do
|
||||
package_type 2
|
||||
after(:create) do |package, evaluator|
|
||||
2.times.each do
|
||||
FactoryGirl.create(:test_drive_package_teachers, test_drive_package: package)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
trait :four_pack do
|
||||
package_type 4
|
||||
after(:create) do |package, evaluator|
|
||||
4.times.each do
|
||||
FactoryGirl.create(:test_drive_package_teachers, test_drive_package: package)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
factory :test_drive_package_teachers, class: "JamRuby::TestDrivePackageTeacher" do
|
||||
association :user, factory: :teacher_user
|
||||
association :test_drive_package, factory: [:test_drive_package, :four_pack]
|
||||
end
|
||||
|
||||
factory :test_drive_package_choice, class: "JamRuby::TestDrivePackageChoice" do
|
||||
association :user, factory: :user
|
||||
association :test_drive_package, factory: [:test_drive_package, :four_pack]
|
||||
end
|
||||
|
||||
factory :test_drive_package_choice_teacher, class: "JamRuby::TestDrivePackageChoiceTeacher" do
|
||||
association :teacher, factory: :teacher_user
|
||||
association :test_drive_package_choice, factory: :test_drive_package_choice
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ describe "Student Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
# should fail because we haven't filled out email/password/terms
|
||||
find('.register-area .errors', text: "Email can't be blank")
|
||||
|
||||
fill_in "email", with: 'student_123@jamkazam.com'
|
||||
fill_in "password", with: 'jam123'
|
||||
fill_in "email", with: 'student_123@jamkazam.com'
|
||||
fill_in "password", with: 'jam123'
|
||||
find('.register-area ins', visible: false).trigger(:click)
|
||||
find('button.cta-button', text: 'SIGN UP').trigger(:click)
|
||||
|
||||
|
|
@ -55,9 +55,9 @@ describe "Student Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
# should fail because we haven't filled out email/password/terms
|
||||
find('.register-area .errors', text: "Email can't be blank")
|
||||
|
||||
fill_in "email", with: 'student_125@jamkazam.com'
|
||||
fill_in "password", with: 'jam123'
|
||||
find('.register-area ins', visible: false) .trigger(:click)
|
||||
fill_in "email", with: 'student_125@jamkazam.com'
|
||||
fill_in "password", with: 'jam123'
|
||||
find('.register-area ins', visible: false).trigger(:click)
|
||||
find('button.cta-button', text: 'SIGN UP').trigger(:click)
|
||||
|
||||
find('h3', text: 'Student Levels Taught:')
|
||||
|
|
@ -74,7 +74,7 @@ describe "Student Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
|
||||
|
||||
it "logged in" do
|
||||
fast_signin(user,"/landing/jamclass/students")
|
||||
fast_signin(user, "/landing/jamclass/students")
|
||||
|
||||
find('h1.jamclass-h1', 'Let Us Find You The Perfect Music Teacher')
|
||||
find('h2.jamclass-h2', 'And Connect You Online With Our Patented, Unique Technology')
|
||||
|
|
@ -89,4 +89,109 @@ describe "Student Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
user.musician.should be true
|
||||
end
|
||||
|
||||
it "package 4 count but picks 2" do
|
||||
|
||||
package = FactoryGirl.create(:test_drive_package, :four_pack)
|
||||
visit "/landing/jamclass/students?utm-teachers=#{package.name}"
|
||||
|
||||
find('h1.jamclass-h1', 'Let Us Find You The Perfect Music Teacher')
|
||||
find('h2.jamclass-h2', 'And Connect You Online With Our Patented, Unique Technology')
|
||||
|
||||
teacher1 = package.test_drive_package_teachers[0].user
|
||||
teacher2 = package.test_drive_package_teachers[1].user
|
||||
teacher3 = package.test_drive_package_teachers[2].user
|
||||
teacher4 = package.test_drive_package_teachers[3].user
|
||||
find('p', text: 'Like the TestDrive concept, but 4 teachers is too many for you?')
|
||||
find('a.pick-two').trigger(:click)
|
||||
find('input[data-teacher-id="' + teacher1.id + '"]').trigger(:click)
|
||||
find('input[data-teacher-id="' + teacher2.id + '"]').trigger(:click)
|
||||
find('a.select-teachers').trigger(:click)
|
||||
|
||||
fill_in "email", with: 'student_package2@jamkazam.com'
|
||||
fill_in "password", with: 'jam123'
|
||||
find('.register-area ins', visible: false).trigger(:click)
|
||||
find('button.cta-button', text: 'SIGN UP').trigger(:click)
|
||||
|
||||
find('.teacher-name-packaged', text: teacher1.last_name)
|
||||
find('.teacher-name-packaged', text: teacher2.last_name)
|
||||
|
||||
page.should_not have_selector('.teacher-name-packaged', text: teacher3.last_name)
|
||||
page.should_not have_selector('.teacher-name-packaged', text: teacher4.last_name)
|
||||
|
||||
find('.explanation', text: '2 private online music lessons - 1 each from these 2 instructors')
|
||||
end
|
||||
|
||||
it "package 4 count" do
|
||||
package = FactoryGirl.create(:test_drive_package, :four_pack)
|
||||
visit "/landing/jamclass/students?utm-teachers=#{package.name}"
|
||||
|
||||
find('h1.jamclass-h1', 'Let Us Find You The Perfect Music Teacher')
|
||||
find('h2.jamclass-h2', 'And Connect You Online With Our Patented, Unique Technology')
|
||||
|
||||
find('p', text: 'Like the TestDrive concept, but 4 teachers is too many for you?')
|
||||
|
||||
fill_in "email", with: 'student_package1@jamkazam.com'
|
||||
fill_in "password", with: 'jam123'
|
||||
find('.register-area ins', visible: false).trigger(:click)
|
||||
find('button.cta-button', text: 'SIGN UP').trigger(:click)
|
||||
|
||||
package.test_drive_package_teachers.each do |package_teacher|
|
||||
teacher = package_teacher.user
|
||||
find('.teacher-name-packaged', text: teacher.last_name)
|
||||
end
|
||||
|
||||
|
||||
user = User.find_by_email('student_package1@jamkazam.com')
|
||||
user.is_a_student.should be true
|
||||
user.is_a_teacher.should be false
|
||||
user.musician.should be true
|
||||
user.origin_utm_source.should eql "organic"
|
||||
user.origin_utm_campaign.should eql "127.0.0.1"
|
||||
user.origin_utm_medium.should eql "organic"
|
||||
user.origin_referrer.should_not be_nil
|
||||
|
||||
user.test_drive_package_choices.count.should eql 1
|
||||
choice = user.test_drive_package_choices[0]
|
||||
choice.test_drive_package_choice_teachers.count.should eql 4
|
||||
|
||||
fill_out_payment(nil, "Super HahaGuy")
|
||||
|
||||
find('#banner h1', text: 'TestDrive Purchased')
|
||||
find('#banner .dialog-inner', text: 'Each teacher has received your request and should respond shortly')
|
||||
find('#banner .close-btn').trigger(:click)
|
||||
|
||||
user.reload
|
||||
user.first_name.should eql 'Super'
|
||||
# find each of teh 4 lessons requested
|
||||
user.student_lesson_bookings.each do |booking|
|
||||
lesson = booking.lesson_sessions[0]
|
||||
lesson.status.should eql LessonSession::STATUS_REQUESTED
|
||||
booking.card_presumed_ok.should be_true
|
||||
find('tr[data-lesson-session-id="' + lesson.id + '"] td.startTimeColumn', text: 'No time has been scheduled yet')
|
||||
end
|
||||
|
||||
booking = user.student_lesson_bookings[0]
|
||||
lesson = booking.lesson_sessions[0]
|
||||
teacher = lesson.teacher
|
||||
|
||||
jamclass_hover_option(lesson, 'status', 'View Status')
|
||||
|
||||
find('h2', text: 'your lesson has been requested')
|
||||
|
||||
# verify that the lesson stats screen looks right
|
||||
find('a.button-orange.schedule', text: 'PROPOSE TIME')
|
||||
find('label', text: 'Propose a day/time')
|
||||
find('.generic-time-stmt.no-slot', text: 'Your lesson has no scheduled time yet.')
|
||||
|
||||
switch_user(teacher, '/client#/jamclass')
|
||||
jamclass_hover_option(lesson, 'status', 'View Status')
|
||||
find('.description', text: 'Message from ' + user.first_name)
|
||||
counter_day(lesson)
|
||||
|
||||
switch_user(user, '/client#/jamclass')
|
||||
jamclass_hover_option(lesson, 'status', 'View Status')
|
||||
find('.generic-time-stmt', text: 'will take place this')
|
||||
approve_lesson(lesson)
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ def jamclass_hover_option(lesson, option, text)
|
|||
find('li[data-lesson-option="' + option + '"] a', visible: false, text: text).trigger(:click)
|
||||
end
|
||||
|
||||
def counter_day
|
||||
def counter_day(lesson)
|
||||
fill_in "alt-date-input", with: date_picker_format(Date.new(Date.today.year, Date.today.month + 1, 17))
|
||||
find('td a', text: '17').trigger(:click)
|
||||
sleep 3
|
||||
|
|
@ -87,8 +87,11 @@ def approve_lesson(lesson, slot = lesson.lesson_booking.default_slot)
|
|||
find('tr[data-lesson-session-id="' + lesson.id + '"] td.displayStatusColumn', text: 'Scheduled')
|
||||
end
|
||||
|
||||
def fill_out_payment(expected = nil)
|
||||
def fill_out_payment(expected = nil, name = nil )
|
||||
|
||||
if name
|
||||
fill_in 'name', with: name
|
||||
end
|
||||
fill_in 'card-number', with: '4111111111111111'
|
||||
fill_in 'expiration', with: '11/2016'
|
||||
fill_in 'cvv', with: '111'
|
||||
|
|
|
|||
|
|
@ -212,7 +212,8 @@ def sign_out_poltergeist(options = {})
|
|||
end
|
||||
|
||||
def open_user_dropdown
|
||||
find('.userinfo').hover()
|
||||
#find('.userinfo').hover()
|
||||
find('.userinfo').mousemove()
|
||||
end
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue