TTikotok
This commit is contained in:
@@ -24,7 +24,7 @@ type SubscriptionProductId = 'monthly_pro' | 'yearly_pro';
|
||||
type TopupProductId = Extract<PurchaseProductId, 'topup_small' | 'topup_medium' | 'topup_large'>;
|
||||
type SubscriptionPackages = Partial<Record<SubscriptionProductId, PurchasesPackage>>;
|
||||
type TopupProducts = Partial<Record<TopupProductId, PurchasesStoreProduct>>;
|
||||
type PaywallPlanId = 'weekly' | 'yearly';
|
||||
type PaywallPlanId = 'monthly' | 'yearly';
|
||||
|
||||
const PAYWALL_BACKGROUND = require('../../assets/paywall_scan_background.png');
|
||||
|
||||
@@ -159,7 +159,7 @@ const getBillingCopy = (language: Language) => {
|
||||
planCardBody: 'Unbegrenzte KI-Scans, Gesundheitsdiagnose, 7-Tage-Rettungspläne, 100 Credits/Monat',
|
||||
planCardPriceTrial: (price: string) => `7 Tage gratis, dann ${price}/Jahr`,
|
||||
planCardPriceMonthly: (price: string) => `${price}/Monat`,
|
||||
trialToggleLabel: 'Gratis-Test aktiviert',
|
||||
trialToggleLabel: '7 Tage gratis testen',
|
||||
dueTodayTrial: 'Fällig heute — 7 Tage gratis',
|
||||
dueTodayAmount: '0,00 €',
|
||||
dueLater: (date: string) => `Fällig am ${date}`,
|
||||
@@ -224,7 +224,7 @@ const getBillingCopy = (language: Language) => {
|
||||
planCardBody: 'Escaneos IA ilimitados, diagnóstico de salud, planes de rescate de 7 días, 100 créditos/mes',
|
||||
planCardPriceTrial: (price: string) => `7 días gratis, luego ${price}/año`,
|
||||
planCardPriceMonthly: (price: string) => `${price}/mes`,
|
||||
trialToggleLabel: 'Prueba gratis activada',
|
||||
trialToggleLabel: 'Probar 7 días gratis',
|
||||
dueTodayTrial: 'Hoy — 7 días gratis',
|
||||
dueTodayAmount: '0,00 €',
|
||||
dueLater: (date: string) => `El ${date}`,
|
||||
@@ -289,7 +289,7 @@ const getBillingCopy = (language: Language) => {
|
||||
planCardBody: 'Unlimited AI scans, health diagnosis, 7-day rescue plans, 100 credits/month',
|
||||
planCardPriceTrial: (price: string) => `Free for 7 days, then ${price}/year`,
|
||||
planCardPriceMonthly: (price: string) => `${price}/month`,
|
||||
trialToggleLabel: 'Free Trial Enabled',
|
||||
trialToggleLabel: 'Try 7 days free',
|
||||
dueTodayTrial: 'Due today — 7 days free',
|
||||
dueTodayAmount: '€0.00',
|
||||
dueLater: (date: string) => `Due ${date}`,
|
||||
@@ -308,7 +308,7 @@ export default function BillingScreen() {
|
||||
const params = useLocalSearchParams<{ view?: string; context?: string }>();
|
||||
const paywallRequested = params.view === 'paywall';
|
||||
const onboardingContext = params.context === 'onboarding';
|
||||
const { isDarkMode, language, billingSummary, isLoadingBilling, simulatePurchase, simulateWebhookEvent, syncRevenueCatState, colorPalette, session } = useApp();
|
||||
const { isDarkMode, language, billingSummary, isLoadingBilling, simulatePurchase, simulateWebhookEvent, syncRevenueCatState, colorPalette, session, hasCompletedOnboarding, markOnboardingCompleted } = useApp();
|
||||
const colors = useColors(isDarkMode, colorPalette);
|
||||
const posthog = useSafeAnalytics();
|
||||
const copy = getBillingCopy(language);
|
||||
@@ -320,7 +320,8 @@ export default function BillingScreen() {
|
||||
const [storeError, setStoreError] = useState<string | null>(null);
|
||||
const [subscriptionPackages, setSubscriptionPackages] = useState<SubscriptionPackages>({});
|
||||
const [topupProducts, setTopupProducts] = useState<TopupProducts>({});
|
||||
const [selectedPaywallPlan, setSelectedPaywallPlan] = useState<PaywallPlanId>('yearly');
|
||||
// Monthly is the default; the 7-day trial (yearly plan) must be opted into via the toggle.
|
||||
const [selectedPaywallPlan, setSelectedPaywallPlan] = useState<PaywallPlanId>('monthly');
|
||||
|
||||
// Cancel Flow State
|
||||
const [cancelStep, setCancelStep] = useState<'none' | 'survey' | 'offer'>('none');
|
||||
@@ -426,7 +427,9 @@ export default function BillingScreen() {
|
||||
if (showPaywallPlans) {
|
||||
posthog.capture('paywall_dismissed', { context: onboardingContext ? 'onboarding' : 'in_app' });
|
||||
if (onboardingContext) {
|
||||
router.replace('/auth/signup');
|
||||
// Guests continue into the app; paid actions are gated at the point of use.
|
||||
markOnboardingCompleted();
|
||||
router.replace('/(tabs)');
|
||||
return;
|
||||
}
|
||||
if (session) {
|
||||
@@ -434,7 +437,7 @@ export default function BillingScreen() {
|
||||
else router.replace('/(tabs)');
|
||||
return;
|
||||
}
|
||||
router.replace('/onboarding');
|
||||
router.replace(hasCompletedOnboarding ? '/(tabs)' : '/onboarding');
|
||||
return;
|
||||
}
|
||||
if (router.canGoBack()) {
|
||||
@@ -442,7 +445,7 @@ export default function BillingScreen() {
|
||||
return;
|
||||
}
|
||||
router.replace('/(tabs)');
|
||||
}, [router, showPaywallPlans, onboardingContext, session, posthog]);
|
||||
}, [router, showPaywallPlans, onboardingContext, session, posthog, hasCompletedOnboarding, markOnboardingCompleted]);
|
||||
|
||||
const postPurchaseRoute = onboardingContext ? '/auth/signup' : '/(tabs)';
|
||||
|
||||
@@ -653,7 +656,7 @@ export default function BillingScreen() {
|
||||
<Text style={[styles.trialToggleLabel, { color: colors.text }]}>{copy.trialToggleLabel}</Text>
|
||||
<Switch
|
||||
value={trialEnabled}
|
||||
onValueChange={(next) => setSelectedPaywallPlan(next ? 'yearly' : 'weekly')}
|
||||
onValueChange={(next) => setSelectedPaywallPlan(next ? 'yearly' : 'monthly')}
|
||||
trackColor={{ true: colors.primary, false: colors.border }}
|
||||
thumbColor="#FFFFFF"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user