Chore/v2/onboarding flow cleanup (#5065)

This commit is contained in:
EthanHealy01
2025-12-02 12:40:20 +00:00
committed by GitHub
parent 341adaa07d
commit 179b569769
44 changed files with 1698 additions and 2275 deletions
@@ -1,12 +1,10 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { useOnboarding } from '@app/contexts/OnboardingContext';
import { useNavigate, useLocation } from 'react-router-dom';
import { isAuthRoute } from '@core/constants/routes';
import { useCheckout } from '@app/contexts/CheckoutContext';
import { InfoBanner } from '@app/components/shared/InfoBanner';
import {
ONBOARDING_SESSION_BLOCK_KEY,
ONBOARDING_SESSION_EVENT,
SERVER_LICENSE_REQUEST_EVENT,
type ServerLicenseRequestPayload,
UPGRADE_BANNER_TEST_EVENT,
@@ -15,13 +13,17 @@ import {
UPGRADE_BANNER_ALERT_EVENT,
} from '@core/constants/events';
import { useServerExperience } from '@app/hooks/useServerExperience';
import { hasSeenStep } from '@core/components/onboarding/orchestrator/onboardingStorage';
const FRIENDLY_LAST_SEEN_KEY = 'upgradeBannerFriendlyLastShownAt';
const WEEK_IN_MS = 7 * 24 * 60 * 60 * 1000;
const UpgradeBanner: React.FC = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const { isOpen: tourOpen } = useOnboarding();
const location = useLocation();
// Check if we're on an auth route (evaluated after hooks, used in render)
const onAuthRoute = isAuthRoute(location.pathname);
const { openCheckout } = useCheckout();
const {
totalUsers,
@@ -34,40 +36,18 @@ const UpgradeBanner: React.FC = () => {
overFreeTierLimit,
scenarioKey,
} = useServerExperience();
const [sessionBlocked, setSessionBlocked] = useState(true);
const [friendlyVisible, setFriendlyVisible] = useState(false);
const onboardingComplete = hasSeenStep('welcome');
const [friendlyVisible, setFriendlyVisible] = useState(() => {
if (typeof window === 'undefined') return false;
const lastShownRaw = window.localStorage.getItem(FRIENDLY_LAST_SEEN_KEY);
if (!lastShownRaw) return false;
const lastShown = parseInt(lastShownRaw, 10);
if (!Number.isFinite(lastShown)) return false;
return Date.now() - lastShown >= WEEK_IN_MS;
});
const isDev = import.meta.env.DEV;
const [testScenario, setTestScenario] = useState<UpgradeBannerTestScenario>(null);
// Track onboarding session flag so we don't show banner if onboarding ran this load
useEffect(() => {
if (typeof window === 'undefined') {
return;
}
const evaluateBlock = () => {
const blocked = window.sessionStorage.getItem(ONBOARDING_SESSION_BLOCK_KEY) === 'true';
setSessionBlocked(blocked);
};
evaluateBlock();
const timer = window.setTimeout(() => {
evaluateBlock();
}, 1000);
const handleOnboardingEvent = () => {
evaluateBlock();
};
window.addEventListener(ONBOARDING_SESSION_EVENT, handleOnboardingEvent as EventListener);
return () => {
clearTimeout(timer);
window.removeEventListener(ONBOARDING_SESSION_EVENT, handleOnboardingEvent as EventListener);
};
}, []);
useEffect(() => {
if (!isDev || typeof window === 'undefined') {
return;
@@ -157,28 +137,16 @@ const UpgradeBanner: React.FC = () => {
shouldShowFriendlyBase &&
!licenseLoading &&
effectiveTotalUsersLoaded &&
!tourOpen &&
!sessionBlocked,
onboardingComplete,
);
// Urgent banner should always show when over-limit
const shouldEvaluateUrgent = scenario
? Boolean(scenario && !scenarioIsFriendly)
: Boolean(
shouldShowUrgentBase &&
!licenseLoading &&
!tourOpen &&
!sessionBlocked,
!licenseLoading,
);
useEffect(() => {
if (typeof window === 'undefined') {
return;
}
if (!shouldShowFriendlyBase && effectiveTotalUsersLoaded) {
window.localStorage.removeItem(FRIENDLY_LAST_SEEN_KEY);
}
}, [shouldShowFriendlyBase, effectiveTotalUsersLoaded]);
useEffect(() => {
if (scenario === 'friendly') {
return;
@@ -214,16 +182,6 @@ const UpgradeBanner: React.FC = () => {
}
: { active: false };
console.debug('[UpgradeBanner] Dispatching alert event', {
shouldEvaluateUrgent,
detail,
totalUsers: effectiveTotalUsers,
freeTierLimit,
effectiveIsAdmin,
effectiveHasPaidLicense,
userCountLoaded: effectiveTotalUsersLoaded,
});
window.dispatchEvent(
new CustomEvent(UPGRADE_BANNER_ALERT_EVENT, { detail }),
);
@@ -246,12 +204,6 @@ const UpgradeBanner: React.FC = () => {
window.localStorage.setItem(FRIENDLY_LAST_SEEN_KEY, Date.now().toString());
}, []);
useEffect(() => {
if (friendlyVisible) {
recordFriendlyLastShown();
}
}, [friendlyVisible, recordFriendlyLastShown]);
const handleUpgrade = () => {
recordFriendlyLastShown();
@@ -308,15 +260,8 @@ const UpgradeBanner: React.FC = () => {
const renderUrgentBanner = () => {
if (!shouldEvaluateUrgent) {
console.debug('[UpgradeBanner] renderUrgentBanner → hidden (shouldEvaluateUrgent=false)');
return null;
}
console.debug('[UpgradeBanner] renderUrgentBanner → visible', {
totalUsers: effectiveTotalUsers,
freeTierLimit,
effectiveIsAdmin,
effectiveHasPaidLicense,
});
const buttonText = effectiveIsAdmin ? t('upgradeBanner.seeInfo', 'See info') : undefined;
@@ -351,7 +296,8 @@ const UpgradeBanner: React.FC = () => {
);
};
if (!friendlyVisible && !shouldEvaluateUrgent) {
// Don't show on auth routes or if neither banner type should show
if (onAuthRoute || (!friendlyVisible && !shouldEvaluateUrgent)) {
return null;
}