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
This commit is contained in:
Millian Lamiaux
2026-03-25 23:28:51 +01:00
parent f11eb6b9ae
commit b833198e9d
42 changed files with 2006 additions and 1594 deletions

View File

@@ -7,7 +7,7 @@ import { View, StyleSheet, ScrollView, Pressable } from 'react-native'
import { useRouter, useLocalSearchParams } from 'expo-router'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { LinearGradient } from 'expo-linear-gradient'
import Ionicons from '@expo/vector-icons/Ionicons'
import { Icon } from '@/src/shared/components/Icon'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
@@ -76,7 +76,7 @@ export default function ProgramDetailScreen() {
{/* Header */}
<View style={styles.header}>
<Pressable style={styles.backButton} onPress={() => router.back()}>
<Ionicons name="arrow-back" size={24} color={colors.text.primary} />
<Icon name="arrow.left" size={24} color={colors.text.primary} />
</Pressable>
<StyledText size={FONTS.TITLE} weight="bold" color={colors.text.primary}>
{program.title}
@@ -215,7 +215,7 @@ export default function ProgramDetailScreen() {
{week.title}
</StyledText>
{!isUnlocked && (
<Ionicons name="lock-closed" size={16} color={colors.text.tertiary} />
<Icon name="lock.fill" size={16} color={colors.text.tertiary} />
)}
{isCurrentWeek && isUnlocked && (
<View style={styles.currentBadge}>
@@ -257,9 +257,9 @@ export default function ProgramDetailScreen() {
>
<View style={styles.workoutNumber}>
{isCompleted ? (
<Ionicons name="checkmark-circle" size={24} color={BRAND.SUCCESS} />
<Icon name="checkmark.circle.fill" size={24} color={BRAND.SUCCESS} />
) : isLocked ? (
<Ionicons name="lock-closed" size={20} color={colors.text.tertiary} />
<Icon name="lock.fill" size={20} color={colors.text.tertiary} />
) : (
<StyledText size={14} weight="semibold" color={colors.text.primary}>
{index + 1}
@@ -280,7 +280,7 @@ export default function ProgramDetailScreen() {
</StyledText>
</View>
{!isLocked && !isCompleted && (
<Ionicons name="chevron-forward" size={20} color={colors.text.tertiary} />
<Icon name="chevron.right" size={20} color={colors.text.tertiary} />
)}
</Pressable>
)
@@ -308,7 +308,7 @@ export default function ProgramDetailScreen() {
: t('programs.continueTraining')
}
</StyledText>
<Ionicons name="arrow-forward" size={20} color="#FFFFFF" style={styles.ctaIcon} />
<Icon name="arrow.right" size={20} color="#FFFFFF" style={styles.ctaIcon} />
</LinearGradient>
</Pressable>
</View>