Files
tabatago/app/privacy.tsx
Millian Lamiaux b833198e9d feat: migrate icons to SF Symbols, refactor explore tab, add collections/programs data layer
- Replace all Ionicons with native SF Symbols via expo-symbols SymbolView
- Create reusable Icon wrapper component (src/shared/components/Icon.tsx)
- Remove @expo/vector-icons and lucide-react dependencies
- Refactor explore tab with filters, search, and category browsing
- Add collections and programs data with Supabase integration
- Add explore filter store and filter sheet
- Update i18n strings (en, de, es, fr) for new explore features
- Update test mocks and remove stale snapshots
- Add user fitness level to user store and types
2026-03-25 23:28:51 +01:00

213 lines
6.0 KiB
TypeScript

/**
* TabataFit Privacy Policy Screen
* Required for App Store submission
*/
import React from 'react'
import { View, ScrollView, StyleSheet, Text, Pressable } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { useRouter } from 'expo-router'
import { Icon } from '@/src/shared/components/Icon'
import { useTranslation } from 'react-i18next'
import { useHaptics } from '@/src/shared/hooks'
import { darkColors, BRAND } from '@/src/shared/theme'
import { SPACING } from '@/src/shared/constants/spacing'
export default function PrivacyPolicyScreen() {
const { t } = useTranslation('screens')
const router = useRouter()
const insets = useSafeAreaInsets()
const haptics = useHaptics()
const handleClose = () => {
haptics.selection()
router.back()
}
return (
<View style={[styles.container, { paddingTop: insets.top }]}>
{/* Header */}
<View style={styles.header}>
<Pressable style={styles.backButton} onPress={handleClose}>
<Icon name="chevron.left" size={28} color={darkColors.text.primary} />
</Pressable>
<Text style={styles.headerTitle}>{t('privacy.title')}</Text>
<View style={{ width: 44 }} />
</View>
<ScrollView
style={styles.scrollView}
contentContainerStyle={[
styles.content,
{ paddingBottom: insets.bottom + 40 },
]}
showsVerticalScrollIndicator={false}
>
<Section title={t('privacy.lastUpdated')} />
<Section title={t('privacy.intro.title')}>
<Paragraph>{t('privacy.intro.content')}</Paragraph>
</Section>
<Section title={t('privacy.dataCollection.title')}>
<Paragraph>{t('privacy.dataCollection.content')}</Paragraph>
<BulletList
items={[
t('privacy.dataCollection.items.workouts'),
t('privacy.dataCollection.items.settings'),
t('privacy.dataCollection.items.device'),
]}
/>
</Section>
<Section title={t('privacy.usage.title')}>
<Paragraph>{t('privacy.usage.content')}</Paragraph>
</Section>
<Section title={t('privacy.sharing.title')}>
<Paragraph>{t('privacy.sharing.content')}</Paragraph>
</Section>
<Section title={t('privacy.security.title')}>
<Paragraph>{t('privacy.security.content')}</Paragraph>
</Section>
<Section title={t('privacy.rights.title')}>
<Paragraph>{t('privacy.rights.content')}</Paragraph>
</Section>
<Section title={t('privacy.contact.title')}>
<Paragraph>{t('privacy.contact.content')}</Paragraph>
<Text style={styles.email}>privacy@tabatafit.app</Text>
</Section>
<View style={styles.footer}>
<Text style={styles.footerText}>
TabataFit v1.0.0
</Text>
</View>
</ScrollView>
</View>
)
}
// ═══════════════════════════════════════════════════════════════════════════
// HELPER COMPONENTS
// ═══════════════════════════════════════════════════════════════════════════
function Section({
title,
children,
}: {
title: string
children?: React.ReactNode
}) {
return (
<View style={styles.section}>
<Text style={styles.sectionTitle}>{title}</Text>
{children}
</View>
)
}
function Paragraph({ children }: { children: string }) {
return <Text style={styles.paragraph}>{children}</Text>
}
function BulletList({ items }: { items: string[] }) {
return (
<View style={styles.bulletList}>
{items.map((item, index) => (
<View key={index} style={styles.bulletItem}>
<Text style={styles.bullet}></Text>
<Text style={styles.bulletText}>{item}</Text>
</View>
))}
</View>
)
}
// ═══════════════════════════════════════════════════════════════════════════
// STYLES
// ═══════════════════════════════════════════════════════════════════════════
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: darkColors.bg.base,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: SPACING[4],
paddingVertical: SPACING[3],
borderBottomWidth: 1,
borderBottomColor: darkColors.border.glass,
},
backButton: {
width: 44,
height: 44,
alignItems: 'center',
justifyContent: 'center',
},
headerTitle: {
fontSize: 17,
fontWeight: '600',
color: darkColors.text.primary,
},
scrollView: {
flex: 1,
},
content: {
paddingHorizontal: SPACING[5],
paddingTop: SPACING[4],
},
section: {
marginBottom: SPACING[6],
},
sectionTitle: {
fontSize: 20,
fontWeight: '700',
color: darkColors.text.primary,
marginBottom: SPACING[3],
},
paragraph: {
fontSize: 15,
lineHeight: 22,
color: darkColors.text.secondary,
},
bulletList: {
marginTop: SPACING[3],
},
bulletItem: {
flexDirection: 'row',
marginBottom: SPACING[2],
},
bullet: {
fontSize: 15,
color: BRAND.PRIMARY,
marginRight: SPACING[2],
},
bulletText: {
flex: 1,
fontSize: 15,
lineHeight: 22,
color: darkColors.text.secondary,
},
email: {
fontSize: 15,
color: BRAND.PRIMARY,
marginTop: SPACING[2],
},
footer: {
marginTop: SPACING[8],
alignItems: 'center',
},
footerText: {
fontSize: 13,
color: darkColors.text.tertiary,
},
})