refactor: code quality cleanup — remove any types, add logger, rename Kine to Tabata
- Phase 0: Rename all Kine references to Tabata (types, files, imports, i18n, analytics events) - Phase 1: Add test coverage for tabataProgramStore, workoutProgramStore, and color utils (47 tests) - Phase 2: Remove all `any` types from production code with proper typed replacements - Phase 3: Replace ~60 raw console.* calls with __DEV__-gated logger utility - Phase 4: Verify .DS_Store housekeeping (already clean) 0 TypeScript errors, 583/583 tests passing.
This commit is contained in:
@@ -12,16 +12,17 @@ import {
|
||||
} from 'react-native'
|
||||
import { useRouter } from 'expo-router'
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import { LinearGradient } from 'expo-linear-gradient'
|
||||
import { Icon, type IconName } from '@/src/shared/components/Icon'
|
||||
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useHaptics, usePurchases } from '@/src/shared/hooks'
|
||||
import { StyledText } from '@/src/shared/components/StyledText'
|
||||
import { useThemeColors, BRAND, GRADIENTS } from '@/src/shared/theme'
|
||||
import { useThemeColors } from '@/src/shared/theme'
|
||||
import { NativeButton } from '@/src/shared/components/native'
|
||||
import type { ThemeColors } from '@/src/shared/theme/types'
|
||||
import { SPACING } from '@/src/shared/constants/spacing'
|
||||
import { RADIUS } from '@/src/shared/constants/borderRadius'
|
||||
import { GREEN, NAVY, BORDER_COLORS } from '@/src/shared/constants/colors'
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// FEATURES LIST
|
||||
@@ -83,17 +84,17 @@ function PlanCard({
|
||||
onPress={handlePress}
|
||||
style={({ pressed }) => [
|
||||
styles.planCard,
|
||||
isSelected && { borderColor: BRAND.PRIMARY },
|
||||
isSelected && { borderColor: GREEN.BORDER },
|
||||
pressed && styles.planCardPressed,
|
||||
{
|
||||
backgroundColor: colors.bg.surface,
|
||||
borderColor: isSelected ? BRAND.PRIMARY : colors.border.glass,
|
||||
borderColor: isSelected ? GREEN.BORDER : BORDER_COLORS.DIM,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{savings && (
|
||||
<View style={styles.savingsBadge}>
|
||||
<StyledText size={10} weight="bold" color={colors.text.primary}>{savings}</StyledText>
|
||||
<StyledText size={10} weight="bold" color={NAVY[900]}>{savings}</StyledText>
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.planInfo}>
|
||||
@@ -104,12 +105,12 @@ function PlanCard({
|
||||
{period}
|
||||
</StyledText>
|
||||
</View>
|
||||
<StyledText size={20} weight="bold" color={BRAND.PRIMARY}>
|
||||
<StyledText size={20} weight="bold" color={GREEN[500]}>
|
||||
{price}
|
||||
</StyledText>
|
||||
{isSelected && (
|
||||
<View style={styles.checkmark}>
|
||||
<Icon name="checkmark.circle.fill" size={24} color={BRAND.PRIMARY} />
|
||||
<Icon name="checkmark.circle.fill" size={24} color={GREEN[500]} />
|
||||
</View>
|
||||
)}
|
||||
</Pressable>
|
||||
@@ -195,9 +196,13 @@ export default function PaywallScreen() {
|
||||
return (
|
||||
<View style={[styles.container, { paddingTop: insets.top }]}>
|
||||
{/* Close Button */}
|
||||
<Pressable style={[styles.closeButton, { top: insets.top + SPACING[2] }]} onPress={handleClose}>
|
||||
<Icon name="xmark" size={28} color={colors.text.secondary} />
|
||||
</Pressable>
|
||||
<View style={[styles.closeButton, { top: insets.top + SPACING[2] }]}>
|
||||
<NativeButton
|
||||
variant="icon"
|
||||
systemImage="xmark"
|
||||
onPress={handleClose}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
@@ -221,8 +226,8 @@ export default function PaywallScreen() {
|
||||
<View style={styles.featuresGrid}>
|
||||
{PREMIUM_FEATURES.map((feature) => (
|
||||
<View key={feature.key} style={styles.featureItem}>
|
||||
<View style={[styles.featureIcon, { backgroundColor: colors.glass.tinted.backgroundColor }]}>
|
||||
<Icon name={feature.icon} size={22} color={BRAND.PRIMARY} />
|
||||
<View style={[styles.featureIcon, { backgroundColor: GREEN.DIM }]}>
|
||||
<Icon name={feature.icon} size={22} color={GREEN[500]} />
|
||||
</View>
|
||||
<StyledText size={13} color={colors.text.secondary} style={{ textAlign: 'center' }}>
|
||||
{t(`paywall.features.${feature.key}`)}
|
||||
@@ -262,30 +267,22 @@ export default function PaywallScreen() {
|
||||
)}
|
||||
|
||||
{/* CTA Button */}
|
||||
<Pressable
|
||||
style={[styles.ctaButton, isLoading && styles.ctaButtonDisabled]}
|
||||
<NativeButton
|
||||
variant="primary"
|
||||
title={isLoading ? t('paywall.processing') : t('paywall.trialCta')}
|
||||
onPress={handlePurchase}
|
||||
disabled={isLoading}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={GRADIENTS.CTA}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
style={styles.ctaGradient}
|
||||
>
|
||||
<StyledText size={17} weight="semibold" color="#FFFFFF">
|
||||
{isLoading ? t('paywall.processing') : t('paywall.trialCta')}
|
||||
</StyledText>
|
||||
</LinearGradient>
|
||||
</Pressable>
|
||||
fullWidth
|
||||
controlSize="large"
|
||||
/>
|
||||
|
||||
{/* Restore & Terms */}
|
||||
<View style={styles.footer}>
|
||||
<Pressable onPress={handleRestore}>
|
||||
<StyledText size={14} color={colors.text.tertiary}>
|
||||
{t('paywall.restore')}
|
||||
</StyledText>
|
||||
</Pressable>
|
||||
<NativeButton
|
||||
variant="ghost"
|
||||
title={t('paywall.restore')}
|
||||
onPress={handleRestore}
|
||||
/>
|
||||
|
||||
<StyledText size={11} color={colors.text.tertiary} style={{ textAlign: 'center', lineHeight: 18, paddingHorizontal: SPACING[4] }}>
|
||||
{t('paywall.terms')}
|
||||
@@ -379,7 +376,7 @@ function createStyles(colors: ThemeColors) {
|
||||
position: 'absolute',
|
||||
top: -8,
|
||||
right: SPACING[3],
|
||||
backgroundColor: BRAND.PRIMARY,
|
||||
backgroundColor: GREEN[500],
|
||||
paddingHorizontal: SPACING[2],
|
||||
paddingVertical: 2,
|
||||
borderRadius: RADIUS.SM,
|
||||
@@ -414,16 +411,14 @@ function createStyles(colors: ThemeColors) {
|
||||
},
|
||||
ctaButton: {
|
||||
borderRadius: RADIUS.LG,
|
||||
overflow: 'hidden',
|
||||
marginTop: SPACING[6],
|
||||
paddingVertical: SPACING[4],
|
||||
alignItems: 'center',
|
||||
backgroundColor: GREEN[500],
|
||||
},
|
||||
ctaButtonDisabled: {
|
||||
opacity: 0.6,
|
||||
},
|
||||
ctaGradient: {
|
||||
paddingVertical: SPACING[4],
|
||||
alignItems: 'center',
|
||||
},
|
||||
ctaText: {
|
||||
fontSize: 17,
|
||||
fontWeight: '600',
|
||||
|
||||
Reference in New Issue
Block a user