fix(app): free-tier billing management view, loading guard, dead paywall code cleanup
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -112,34 +112,11 @@ const getBillingCopy = (language: Language) => {
|
|||||||
manageSubscription: 'Abo verwalten',
|
manageSubscription: 'Abo verwalten',
|
||||||
subscriptionTitle: 'Abos',
|
subscriptionTitle: 'Abos',
|
||||||
subscriptionHint: 'Wähle ein Abo und schalte stärkere KI-Scans sowie mehr Credits frei.',
|
subscriptionHint: 'Wähle ein Abo und schalte stärkere KI-Scans sowie mehr Credits frei.',
|
||||||
paywallTitle: 'Vollstaendige Diagnose freischalten',
|
|
||||||
paywallHint: 'Starte Pro fuer echte GPT-5.4 Scans, deinen 7-Tage-Rettungsplan und 100 Credits fuer AI-Scans und Follow-ups.',
|
|
||||||
startTrial: '7 Tage kostenlos testen',
|
startTrial: '7 Tage kostenlos testen',
|
||||||
hardPaywallTitle: 'Pflanze scannen. Richtig pflegen.',
|
|
||||||
hardPaywallHint: 'GreenLens erkennt Art, Pflegebedarf und mögliche Probleme in Sekunden.',
|
|
||||||
identifiedChip: 'Monstera erkannt',
|
|
||||||
benefitUnlimitedScans: 'Unbegrenzte Scans',
|
|
||||||
benefitCarePlan: 'Pflegeplan + Erinnerungen',
|
|
||||||
weeklyPlanName: 'Monatlich',
|
|
||||||
yearlyPlanName: 'Jährlich',
|
|
||||||
weeklyPriceFallback: '5,99 € / Monat',
|
|
||||||
yearlyPriceFallback: '39,99 € / Jahr',
|
|
||||||
bestOffer: 'Bestes Angebot',
|
|
||||||
noPaymentToday: 'Keine Zahlung heute · jederzeit kündbar',
|
|
||||||
monthlyFooter: 'Monatlich kündbar · kein Gratis-Test',
|
|
||||||
monthlyCta: 'Monatlich starten',
|
|
||||||
yearlyCta: 'Jaehrlich starten',
|
|
||||||
yearlyTrialBadge: '7 TAGE GRATIS',
|
|
||||||
monthlyBadge: 'FLEXIBEL',
|
|
||||||
yearlySubline: 'Danach 39,99 EUR/Jahr. Jederzeit kuendbar.',
|
|
||||||
monthlySubline: '4,99 EUR/Monat. Ohne Jahresbindung.',
|
|
||||||
saveLabel: 'Bester Wert',
|
|
||||||
expoGoPurchaseTitle: 'Kauf nur im Dev Build',
|
expoGoPurchaseTitle: 'Kauf nur im Dev Build',
|
||||||
expoGoPurchaseMessage: 'Expo Go kann keine Apple- oder RevenueCat-Kaufmaske anzeigen. Im Development Build oder TestFlight erscheint hier der echte 7-Tage-Trial. Fuer lokale Tests kannst du Pro simulieren.',
|
expoGoPurchaseMessage: 'Expo Go kann keine Apple- oder RevenueCat-Kaufmaske anzeigen. Im Development Build oder TestFlight erscheint hier der echte 7-Tage-Trial. Fuer lokale Tests kannst du Pro simulieren.',
|
||||||
expoGoSimulate: 'Pro simulieren',
|
expoGoSimulate: 'Pro simulieren',
|
||||||
continueWithoutPro: 'Ohne Pro fortfahren',
|
continueWithoutPro: 'Ohne Pro fortfahren',
|
||||||
perYear: '/ Jahr',
|
|
||||||
perMonth: '/ Monat',
|
|
||||||
freePlanName: 'Free',
|
freePlanName: 'Free',
|
||||||
freePlanPrice: '0 EUR / Monat',
|
freePlanPrice: '0 EUR / Monat',
|
||||||
proPlanName: 'Pro',
|
proPlanName: 'Pro',
|
||||||
@@ -200,34 +177,11 @@ const getBillingCopy = (language: Language) => {
|
|||||||
manageSubscription: 'Administrar Suscripción',
|
manageSubscription: 'Administrar Suscripción',
|
||||||
subscriptionTitle: 'Suscripciones',
|
subscriptionTitle: 'Suscripciones',
|
||||||
subscriptionHint: 'Elige un plan y desbloquea escaneos con IA más potentes y más créditos.',
|
subscriptionHint: 'Elige un plan y desbloquea escaneos con IA más potentes y más créditos.',
|
||||||
paywallTitle: 'Desbloquear diagnostico completo',
|
|
||||||
paywallHint: 'Inicia Pro para escaneos reales con GPT-5.4, tu plan de rescate de 7 dias y 100 creditos para escaneos IA y seguimientos.',
|
|
||||||
startTrial: 'Probar 7 dias gratis',
|
startTrial: 'Probar 7 dias gratis',
|
||||||
hardPaywallTitle: 'Escanea plantas. Cuídalas bien.',
|
|
||||||
hardPaywallHint: 'GreenLens identifica la especie, los cuidados y posibles problemas en segundos.',
|
|
||||||
identifiedChip: 'Monstera identificada',
|
|
||||||
benefitUnlimitedScans: 'Escaneos ilimitados',
|
|
||||||
benefitCarePlan: 'Plan de cuidado + recordatorios',
|
|
||||||
weeklyPlanName: 'Mensual',
|
|
||||||
yearlyPlanName: 'Anual',
|
|
||||||
weeklyPriceFallback: '5,99 € / mes',
|
|
||||||
yearlyPriceFallback: '39,99 € / año',
|
|
||||||
bestOffer: 'Mejor oferta',
|
|
||||||
noPaymentToday: 'Sin pago hoy · cancela cuando quieras',
|
|
||||||
monthlyFooter: 'Cancela mensualmente · sin prueba gratis',
|
|
||||||
monthlyCta: 'Empezar mensual',
|
|
||||||
yearlyCta: 'Empezar anual',
|
|
||||||
yearlyTrialBadge: '7 DIAS GRATIS',
|
|
||||||
monthlyBadge: 'FLEXIBLE',
|
|
||||||
yearlySubline: 'Despues 39.99 EUR/ano. Cancela cuando quieras.',
|
|
||||||
monthlySubline: '4.99 EUR/mes. Sin compromiso anual.',
|
|
||||||
saveLabel: 'Mejor valor',
|
|
||||||
expoGoPurchaseTitle: 'Compra solo en Dev Build',
|
expoGoPurchaseTitle: 'Compra solo en Dev Build',
|
||||||
expoGoPurchaseMessage: 'Expo Go no puede mostrar la compra nativa de Apple o RevenueCat. En Development Build o TestFlight aparecera el trial real de 7 dias. Para pruebas locales puedes simular Pro.',
|
expoGoPurchaseMessage: 'Expo Go no puede mostrar la compra nativa de Apple o RevenueCat. En Development Build o TestFlight aparecera el trial real de 7 dias. Para pruebas locales puedes simular Pro.',
|
||||||
expoGoSimulate: 'Simular Pro',
|
expoGoSimulate: 'Simular Pro',
|
||||||
continueWithoutPro: 'Continuar sin Pro',
|
continueWithoutPro: 'Continuar sin Pro',
|
||||||
perYear: '/ ano',
|
|
||||||
perMonth: '/ mes',
|
|
||||||
freePlanName: 'Gratis',
|
freePlanName: 'Gratis',
|
||||||
freePlanPrice: '0 EUR / Mes',
|
freePlanPrice: '0 EUR / Mes',
|
||||||
proPlanName: 'Pro',
|
proPlanName: 'Pro',
|
||||||
@@ -288,34 +242,11 @@ const getBillingCopy = (language: Language) => {
|
|||||||
manageSubscription: 'Manage Subscription',
|
manageSubscription: 'Manage Subscription',
|
||||||
subscriptionTitle: 'Subscriptions',
|
subscriptionTitle: 'Subscriptions',
|
||||||
subscriptionHint: 'Choose a plan to unlock stronger AI scans and more credits.',
|
subscriptionHint: 'Choose a plan to unlock stronger AI scans and more credits.',
|
||||||
paywallTitle: 'Unlock the full diagnosis',
|
|
||||||
paywallHint: 'Start Pro for real GPT-5.4 scans, your 7-day rescue plan, and 100 credits for AI scans and follow-ups.',
|
|
||||||
startTrial: 'Start 7-day free trial',
|
startTrial: 'Start 7-day free trial',
|
||||||
hardPaywallTitle: 'Scan plants. Care for them right.',
|
|
||||||
hardPaywallHint: 'GreenLens identifies the species, care needs, and possible problems in seconds.',
|
|
||||||
identifiedChip: 'Monstera identified',
|
|
||||||
benefitUnlimitedScans: 'Unlimited scans',
|
|
||||||
benefitCarePlan: 'Care plan + reminders',
|
|
||||||
weeklyPlanName: 'Monthly',
|
|
||||||
yearlyPlanName: 'Yearly',
|
|
||||||
weeklyPriceFallback: '$4.99 / month',
|
|
||||||
yearlyPriceFallback: '$39.99 / year',
|
|
||||||
bestOffer: 'Best offer',
|
|
||||||
noPaymentToday: 'No payment today · cancel anytime',
|
|
||||||
monthlyFooter: 'Cancel monthly · no free trial',
|
|
||||||
monthlyCta: 'Start monthly',
|
|
||||||
yearlyCta: 'Start yearly',
|
|
||||||
yearlyTrialBadge: '7 DAYS FREE',
|
|
||||||
monthlyBadge: 'FLEXIBLE',
|
|
||||||
yearlySubline: 'Then EUR 39.99/year. Cancel anytime.',
|
|
||||||
monthlySubline: 'EUR 4.99/month. No annual commitment.',
|
|
||||||
saveLabel: 'Best value',
|
|
||||||
expoGoPurchaseTitle: 'Purchase requires a dev build',
|
expoGoPurchaseTitle: 'Purchase requires a dev build',
|
||||||
expoGoPurchaseMessage: 'Expo Go cannot show the native Apple or RevenueCat purchase sheet. In a Development Build or TestFlight this opens the real 7-day trial. For local testing you can simulate Pro.',
|
expoGoPurchaseMessage: 'Expo Go cannot show the native Apple or RevenueCat purchase sheet. In a Development Build or TestFlight this opens the real 7-day trial. For local testing you can simulate Pro.',
|
||||||
expoGoSimulate: 'Simulate Pro',
|
expoGoSimulate: 'Simulate Pro',
|
||||||
continueWithoutPro: 'Continue without Pro',
|
continueWithoutPro: 'Continue without Pro',
|
||||||
perYear: '/ year',
|
|
||||||
perMonth: '/ month',
|
|
||||||
freePlanName: 'Free',
|
freePlanName: 'Free',
|
||||||
freePlanPrice: '0 EUR / Month',
|
freePlanPrice: '0 EUR / Month',
|
||||||
proPlanName: 'Pro',
|
proPlanName: 'Pro',
|
||||||
@@ -394,7 +325,7 @@ export default function BillingScreen() {
|
|||||||
|
|
||||||
const planId = billingSummary?.entitlement?.plan || 'free';
|
const planId = billingSummary?.entitlement?.plan || 'free';
|
||||||
const credits = isLoadingBilling && !billingSummary ? '...' : (billingSummary?.credits?.available ?? 0);
|
const credits = isLoadingBilling && !billingSummary ? '...' : (billingSummary?.credits?.available ?? 0);
|
||||||
const showPaywallPlans = (!session || paywallRequested) && planId !== 'pro';
|
const showPaywallPlans = (!session || paywallRequested) && (!isLoadingBilling || !session) && planId !== 'pro';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
@@ -802,122 +733,39 @@ export default function BillingScreen() {
|
|||||||
<ActivityIndicator size="large" color={colors.primary} style={{ marginTop: 40 }} />
|
<ActivityIndicator size="large" color={colors.primary} style={{ marginTop: 40 }} />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{session && planId === 'pro' && (
|
{session && (
|
||||||
<View style={[styles.card, { backgroundColor: colors.cardBg, borderColor: colors.border }]}>
|
<View style={[styles.card, { backgroundColor: colors.cardBg, borderColor: colors.border }]}>
|
||||||
<Text style={[styles.sectionTitle, { color: colors.text }]}>{copy.planLabel}</Text>
|
<Text style={[styles.sectionTitle, { color: colors.text }]}>{copy.planLabel}</Text>
|
||||||
<View style={[styles.row, { marginBottom: 16 }]}>
|
<View style={[styles.row, { marginBottom: 16 }]}>
|
||||||
<Text style={[styles.value, { color: colors.text }]}>
|
<Text style={[styles.value, { color: colors.text }]}>
|
||||||
{planId === 'pro' ? copy.planPro : copy.planFree}
|
{planId === 'pro' ? copy.planPro : copy.planFree}
|
||||||
</Text>
|
</Text>
|
||||||
|
{planId === 'pro' && (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.manageBtn, { backgroundColor: colors.primary }]}
|
style={[styles.manageBtn, { backgroundColor: colors.primary }]}
|
||||||
onPress={() => setSubModalVisible(true)}
|
onPress={() => setSubModalVisible(true)}
|
||||||
>
|
>
|
||||||
<Text style={styles.manageBtnText}>{copy.manageSubscription}</Text>
|
<Text style={styles.manageBtnText}>{copy.manageSubscription}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Text style={[styles.sectionTitle, { color: colors.text }]}>{copy.creditsAvailableLabel}</Text>
|
<Text style={[styles.sectionTitle, { color: colors.text }]}>{copy.creditsAvailableLabel}</Text>
|
||||||
<Text style={[styles.creditsValue, { color: colors.text }]}>{credits}</Text>
|
<Text style={[styles.creditsValue, { color: colors.text }]}>{credits}</Text>
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
{showPaywallPlans && (
|
|
||||||
<View style={[styles.card, { backgroundColor: colors.cardBg, borderColor: colors.border }]}>
|
|
||||||
<Text style={[styles.paywallTitle, { color: colors.text }]}>{copy.paywallTitle}</Text>
|
|
||||||
<Text style={[styles.modalHint, { color: colors.text + '80', marginBottom: 16 }]}>
|
|
||||||
{copy.paywallHint}
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<View style={styles.paywallValueRows}>
|
|
||||||
{copy.proBenefits.slice(0, 3).map((benefit, index) => (
|
|
||||||
<View key={benefit} style={[styles.paywallValueRow, { backgroundColor: colors.surfaceMuted }]}>
|
|
||||||
<Ionicons
|
|
||||||
name={index === 0 ? 'scan-outline' : index === 1 ? 'medkit-outline' : 'calendar-outline'}
|
|
||||||
size={17}
|
|
||||||
color={colors.primary}
|
|
||||||
/>
|
|
||||||
<Text style={[styles.paywallValueText, { color: colors.text }]}>{benefit}</Text>
|
|
||||||
</View>
|
|
||||||
))}
|
|
||||||
</View>
|
|
||||||
|
|
||||||
|
{planId !== 'pro' && (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.paywallPlanCardPrimary, { borderColor: colors.primary, backgroundColor: colors.primary + '12' }]}
|
style={[styles.upgradeCta, { backgroundColor: colors.primary }]}
|
||||||
onPress={() => handlePurchase('yearly_pro')}
|
onPress={() => router.push('/profile/billing?view=paywall')}
|
||||||
disabled={isUpdating || !storeReady || Boolean(storeError)}
|
activeOpacity={0.86}
|
||||||
activeOpacity={0.9}
|
|
||||||
>
|
>
|
||||||
<View style={styles.planTopRow}>
|
<Ionicons name="sparkles-outline" size={18} color={colors.onPrimary} />
|
||||||
<View>
|
<Text style={[styles.upgradeCtaText, { color: colors.onPrimary }]}>{copy.startTrial}</Text>
|
||||||
<Text style={[styles.guestPlanName, { color: colors.text }]}>GreenLens Pro</Text>
|
|
||||||
<Text style={[styles.planSubline, { color: colors.textMuted }]}>{copy.saveLabel}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[styles.proBadge, { backgroundColor: colors.primary }]}>
|
|
||||||
<Text style={styles.proBadgeText}>{copy.yearlyTrialBadge}</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<View style={styles.priceRow}>
|
|
||||||
<Text style={[styles.guestPlanPrice, { color: colors.text }]}>{yearlyPrice}</Text>
|
|
||||||
<Text style={[styles.planTerm, { color: colors.textMuted }]}>{copy.perYear}</Text>
|
|
||||||
</View>
|
|
||||||
<Text style={[styles.guestPlanRenew, { color: colors.textMuted }]}>{copy.yearlySubline}</Text>
|
|
||||||
<View style={[styles.trialCallout, { backgroundColor: colors.primarySoft }]}>
|
|
||||||
<Ionicons name="sparkles-outline" size={16} color={colors.primary} />
|
|
||||||
<Text style={[styles.trialCalloutText, { color: colors.text }]}>{copy.startTrial}</Text>
|
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[
|
|
||||||
styles.paywallPlanCardSecondary,
|
|
||||||
{ borderColor: colors.border },
|
|
||||||
(!storeReady || isUpdating || Boolean(storeError)) && styles.disabledPlanCard,
|
|
||||||
]}
|
|
||||||
onPress={() => handlePurchase('monthly_pro')}
|
|
||||||
disabled={isUpdating || !storeReady || Boolean(storeError)}
|
|
||||||
activeOpacity={0.9}
|
|
||||||
>
|
|
||||||
<View style={styles.planTopRow}>
|
|
||||||
<View style={{ flex: 1 }}>
|
|
||||||
<Text style={[styles.guestPlanName, { color: colors.text }]}>Monatlich</Text>
|
|
||||||
<Text style={[styles.planSubline, { color: colors.textMuted }]}>{copy.monthlySubline}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[styles.secondaryBadge, { borderColor: colors.borderStrong }]}>
|
|
||||||
<Text style={[styles.secondaryBadgeText, { color: colors.textSecondary }]}>{copy.monthlyBadge}</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<View style={styles.priceRow}>
|
|
||||||
<Text style={[styles.guestPlanPrice, { color: colors.text }]}>{monthlyPrice}</Text>
|
|
||||||
<Text style={[styles.planTerm, { color: colors.textMuted }]}>{copy.perMonth}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[styles.monthlyCtaButton, { backgroundColor: colors.surfaceMuted, borderColor: colors.border }]}>
|
|
||||||
{!storeReady ? (
|
|
||||||
<ActivityIndicator size="small" color={colors.primary} />
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Text style={[styles.monthlyCtaText, { color: colors.primary }]}>{copy.monthlyCta}</Text>
|
|
||||||
<Ionicons name="arrow-forward" size={14} color={colors.primary} />
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
<View style={[styles.legalLinksRow, { marginTop: 16 }]}>
|
|
||||||
<TouchableOpacity onPress={() => Linking.openURL('https://greenlenspro.com/privacy')}>
|
|
||||||
<Text style={[styles.legalLink, { color: colors.primary }]}>Privacy Policy</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<Text style={[styles.legalSep, { color: colors.textMuted }]}> · </Text>
|
|
||||||
<TouchableOpacity onPress={() => Linking.openURL('https://greenlenspro.com/terms')}>
|
|
||||||
<Text style={[styles.legalLink, { color: colors.primary }]}>Terms of Use</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
<TouchableOpacity style={styles.restoreBtn} onPress={handleRestore} disabled={isUpdating}>
|
|
||||||
<Text style={[styles.legalLink, { color: colors.textMuted }]}>{copy.restorePurchases}</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
)}
|
)}
|
||||||
|
{session && !isExpoGo ? (
|
||||||
{session && planId === 'pro' && !isExpoGo ? (
|
|
||||||
<View style={[styles.card, { backgroundColor: colors.cardBg, borderColor: colors.border }]}>
|
<View style={[styles.card, { backgroundColor: colors.cardBg, borderColor: colors.border }]}>
|
||||||
<Text style={[styles.sectionTitle, { color: colors.text }]}>{copy.topupTitle}</Text>
|
<Text style={[styles.sectionTitle, { color: colors.text }]}>{copy.topupTitle}</Text>
|
||||||
<Text style={[styles.modalHint, { color: colors.text + '80', marginBottom: 8 }]}>{copy.topupHint}</Text>
|
<Text style={[styles.modalHint, { color: colors.text + '80', marginBottom: 8 }]}>{copy.topupHint}</Text>
|
||||||
@@ -1264,30 +1112,18 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 32,
|
fontSize: 32,
|
||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
},
|
},
|
||||||
paywallTitle: {
|
upgradeCta: {
|
||||||
fontSize: 24,
|
marginTop: 16,
|
||||||
fontWeight: '800',
|
height: 50,
|
||||||
lineHeight: 30,
|
borderRadius: 14,
|
||||||
marginBottom: 8,
|
|
||||||
},
|
|
||||||
paywallValueRows: {
|
|
||||||
gap: 8,
|
|
||||||
marginBottom: 14,
|
|
||||||
},
|
|
||||||
paywallValueRow: {
|
|
||||||
minHeight: 42,
|
|
||||||
borderRadius: 12,
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
paddingVertical: 10,
|
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 9,
|
justifyContent: 'center',
|
||||||
|
gap: 8,
|
||||||
},
|
},
|
||||||
paywallValueText: {
|
upgradeCtaText: {
|
||||||
flex: 1,
|
fontSize: 16,
|
||||||
fontSize: 13,
|
fontWeight: '800',
|
||||||
fontWeight: '700',
|
|
||||||
lineHeight: 18,
|
|
||||||
},
|
},
|
||||||
topupBtn: {
|
topupBtn: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
@@ -1446,114 +1282,9 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
},
|
},
|
||||||
guestPlanCard: {
|
|
||||||
borderWidth: 2,
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 16,
|
|
||||||
},
|
|
||||||
paywallPlanCardPrimary: {
|
|
||||||
borderWidth: 2,
|
|
||||||
borderRadius: 14,
|
|
||||||
padding: 16,
|
|
||||||
marginTop: 2,
|
|
||||||
},
|
|
||||||
paywallPlanCardSecondary: {
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 14,
|
|
||||||
padding: 14,
|
|
||||||
marginTop: 10,
|
|
||||||
},
|
|
||||||
disabledPlanCard: {
|
disabledPlanCard: {
|
||||||
opacity: 0.72,
|
opacity: 0.72,
|
||||||
},
|
},
|
||||||
guestPlanHeader: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: 8,
|
|
||||||
marginBottom: 4,
|
|
||||||
},
|
|
||||||
planTopRow: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
gap: 10,
|
|
||||||
marginBottom: 10,
|
|
||||||
},
|
|
||||||
guestPlanName: {
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: '700',
|
|
||||||
},
|
|
||||||
planSubline: {
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: '600',
|
|
||||||
marginTop: 2,
|
|
||||||
},
|
|
||||||
priceRow: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'baseline',
|
|
||||||
gap: 6,
|
|
||||||
},
|
|
||||||
guestPlanPrice: {
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: '700',
|
|
||||||
marginBottom: 2,
|
|
||||||
},
|
|
||||||
planTerm: {
|
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: '600',
|
|
||||||
},
|
|
||||||
guestPlanRenew: {
|
|
||||||
fontSize: 12,
|
|
||||||
lineHeight: 17,
|
|
||||||
},
|
|
||||||
trialCallout: {
|
|
||||||
minHeight: 46,
|
|
||||||
borderRadius: 12,
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
paddingVertical: 10,
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
gap: 8,
|
|
||||||
marginTop: 14,
|
|
||||||
},
|
|
||||||
trialCalloutText: {
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: '800',
|
|
||||||
},
|
|
||||||
secondaryBadge: {
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 999,
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
paddingVertical: 3,
|
|
||||||
flexShrink: 0,
|
|
||||||
},
|
|
||||||
secondaryBadgeText: {
|
|
||||||
fontSize: 10,
|
|
||||||
fontWeight: '800',
|
|
||||||
},
|
|
||||||
monthlyCtaText: {
|
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: '800',
|
|
||||||
},
|
|
||||||
monthlyCtaButton: {
|
|
||||||
minHeight: 42,
|
|
||||||
borderRadius: 12,
|
|
||||||
borderWidth: 1,
|
|
||||||
marginTop: 12,
|
|
||||||
paddingHorizontal: 14,
|
|
||||||
paddingVertical: 10,
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
gap: 8,
|
|
||||||
},
|
|
||||||
guestSubscribeBtn: {
|
|
||||||
marginTop: 14,
|
|
||||||
paddingVertical: 12,
|
|
||||||
borderRadius: 10,
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
legalLinksRow: {
|
legalLinksRow: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
|||||||
Reference in New Issue
Block a user