mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-19 05:09:38 +02:00
Onboarding redirect tests and trial status bar (#2197)
* Onboarding redirect tests and trial status bar * use helper method * Fix time tolerance failure * Update post-onboarding message to be generic * Disable turbo frames on Trial start button * Update flash notice in test
This commit is contained in:
parent
bc7e32deab
commit
441f436187
9 changed files with 110 additions and 18 deletions
|
@ -18,11 +18,7 @@ module Onboardable
|
|||
return unless Current.user
|
||||
return unless redirectable_path?(request.path)
|
||||
|
||||
# Check if trial was started VERY recently (e.g., within the last few seconds)
|
||||
# If so, assume onboarding was just completed in the previous request, even if onboarded_at appears blank momentarily.
|
||||
trial_just_started = Current.family.trial_started_at.present? && Current.family.trial_started_at > 10.seconds.ago
|
||||
|
||||
if Current.user.onboarded_at.blank? && !trial_just_started
|
||||
if !Current.user.onboarded?
|
||||
redirect_to onboarding_path
|
||||
elsif !Current.family.subscribed? && !Current.family.trialing? && !self_hosted?
|
||||
redirect_to upgrade_subscription_path
|
||||
|
|
|
@ -14,7 +14,6 @@ class OnboardingsController < ApplicationController
|
|||
end
|
||||
|
||||
private
|
||||
|
||||
def set_user
|
||||
@user = Current.user
|
||||
end
|
||||
|
|
|
@ -8,16 +8,14 @@ class SubscriptionsController < ApplicationController
|
|||
end
|
||||
|
||||
def start_trial
|
||||
if Current.family.trial_started_at.present?
|
||||
redirect_to root_path, alert: "You've already started or completed your trial"
|
||||
else
|
||||
Family.transaction do
|
||||
Current.family.update(trial_started_at: Time.current)
|
||||
Current.user.update(onboarded_at: Time.current)
|
||||
unless Current.family.trialing?
|
||||
ActiveRecord::Base.transaction do
|
||||
Current.user.update!(onboarded_at: Time.current)
|
||||
Current.family.update!(trial_started_at: Time.current)
|
||||
end
|
||||
end
|
||||
|
||||
redirect_to root_path, notice: "Your trial has started"
|
||||
end
|
||||
redirect_to root_path, notice: "Welcome to Maybe!"
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
@ -152,6 +152,10 @@ class User < ApplicationRecord
|
|||
totp.provisioning_uri(email)
|
||||
end
|
||||
|
||||
def onboarded?
|
||||
onboarded_at.present?
|
||||
end
|
||||
|
||||
private
|
||||
def ensure_valid_profile_image
|
||||
return unless profile_image.attached?
|
||||
|
|
|
@ -79,9 +79,32 @@
|
|||
<% if content_for?(:sidebar) %>
|
||||
<%= yield :sidebar %>
|
||||
<% else %>
|
||||
<div id="account-sidebar-tabs" data-turbo-permanent>
|
||||
<div class="h-full flex flex-col">
|
||||
<div class="overflow-y-auto grow" id="account-sidebar-tabs" data-turbo-permanent>
|
||||
<%= render "accounts/account_sidebar_tabs", family: Current.family, active_account_group_tab: params[:account_group_tab] || "assets" %>
|
||||
</div>
|
||||
|
||||
<% if Current.family.trialing? && !self_hosted? %>
|
||||
<div class="px-4 py-3 space-y-4 bg-container shadow-border-xs rounded-xl">
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<p class="text-sm font-medium text-primary">Free trial</p>
|
||||
<p class="text-sm text-secondary"><%= Current.family.trial_remaining_days %> days remaining</p>
|
||||
</div>
|
||||
|
||||
<%= render LinkComponent.new(
|
||||
text: "Upgrade",
|
||||
href: upgrade_subscription_path,
|
||||
) %>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-0.5 h-1.5">
|
||||
<div class="h-full bg-warning rounded-full" style="width: <%= 100 - Current.family.trial_remaining_days / 14.0 * 100 %>%"></div>
|
||||
<div class="h-full bg-surface-inset rounded-full" style="width: <%= Current.family.trial_remaining_days / 14.0 * 100 %>%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{ name: "Setup", path: onboarding_path, is_complete: user.first_name.present?, step_number: 1 },
|
||||
{ name: "Preferences", path: preferences_onboarding_path, is_complete: user.set_onboarding_preferences_at.present?, step_number: 2 },
|
||||
{ name: "Goals", path: goals_onboarding_path , is_complete: user.set_onboarding_goals_at.present?, step_number: 3 },
|
||||
{ name: "Start", path: trial_onboarding_path, is_complete: user.onboarded_at.present?, step_number: 4 },
|
||||
{ name: "Start", path: trial_onboarding_path, is_complete: user.onboarded?, step_number: 4 },
|
||||
] %>
|
||||
|
||||
<%# Don't show last step if self hosted %>
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
<%= render ButtonComponent.new(
|
||||
text: "Try Maybe for 14 days",
|
||||
href: start_trial_subscription_path,
|
||||
full_width: true
|
||||
full_width: true,
|
||||
data: { turbo: false }
|
||||
) %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
43
test/controllers/concerns/onboardable_test.rb
Normal file
43
test/controllers/concerns/onboardable_test.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
require "test_helper"
|
||||
|
||||
class OnboardableTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in @user = users(:empty)
|
||||
end
|
||||
|
||||
test "must complete onboarding before any other action" do
|
||||
@user.update!(onboarded_at: nil)
|
||||
|
||||
get root_path
|
||||
assert_redirected_to onboarding_path
|
||||
|
||||
@user.family.update!(trial_started_at: 1.day.ago, stripe_subscription_status: "active")
|
||||
|
||||
get root_path
|
||||
assert_redirected_to onboarding_path
|
||||
end
|
||||
|
||||
test "must subscribe if onboarding complete and no trial or subscription is active" do
|
||||
@user.update!(onboarded_at: 1.day.ago)
|
||||
@user.family.update!(trial_started_at: nil, stripe_subscription_status: "incomplete")
|
||||
|
||||
get root_path
|
||||
assert_redirected_to upgrade_subscription_path
|
||||
end
|
||||
|
||||
test "onboarded trial user can visit dashboard" do
|
||||
@user.update!(onboarded_at: 1.day.ago)
|
||||
@user.family.update!(trial_started_at: 1.day.ago, stripe_subscription_status: "incomplete")
|
||||
|
||||
get root_path
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "onboarded subscribed user can visit dashboard" do
|
||||
@user.update!(onboarded_at: 1.day.ago)
|
||||
@user.family.update!(stripe_subscription_status: "active")
|
||||
|
||||
get root_path
|
||||
assert_response :success
|
||||
end
|
||||
end
|
|
@ -5,6 +5,34 @@ class SubscriptionsControllerTest < ActionDispatch::IntegrationTest
|
|||
sign_in @user = users(:family_admin)
|
||||
end
|
||||
|
||||
test "can start trial" do
|
||||
@user.update!(onboarded_at: nil)
|
||||
@user.family.update!(trial_started_at: nil, stripe_subscription_status: "incomplete")
|
||||
|
||||
assert_nil @user.onboarded_at
|
||||
assert_nil @user.family.trial_started_at
|
||||
|
||||
post start_trial_subscription_path
|
||||
assert_redirected_to root_path
|
||||
assert_equal "Welcome to Maybe!", flash[:notice]
|
||||
|
||||
assert @user.reload.onboarded?
|
||||
assert @user.family.reload.trial_started_at.present?
|
||||
end
|
||||
|
||||
test "if user re-enters onboarding, don't restart trial" do
|
||||
onboard_time = 1.day.ago
|
||||
trial_start_time = 1.day.ago
|
||||
|
||||
@user.update!(onboarded_at: onboard_time)
|
||||
@user.family.update!(trial_started_at: trial_start_time, stripe_subscription_status: "incomplete")
|
||||
|
||||
post start_trial_subscription_path
|
||||
assert_redirected_to root_path
|
||||
|
||||
assert @user.reload.family.trial_started_at < Date.current
|
||||
end
|
||||
|
||||
test "redirects to settings if self hosting" do
|
||||
Rails.application.config.app_mode.stubs(:self_hosted?).returns(true)
|
||||
get subscription_path
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue