import { useCallback, useMemo, useState } from 'react'; import { ScrollView, StyleSheet, Platform, View, Text, useWindowDimensions } from 'react-native'; import { useFocusEffect } from 'expo-router'; import Animated, { FadeInDown } from 'react-native-reanimated'; import { Ionicons } from '@expo/vector-icons'; import { useAuthStore, usePacksStore } from '../../src/store'; import { GradientBackground } from '../../src/components/ui'; import { Paywall } from '../../src/components/paywall'; import { CompactHeader, ContentRow } from '../../src/components/discovery'; import { colors, spacing, typography, radius } from '../../src/theme'; import type { QuestionPack, Category } from '../../src/types'; const MAX_CONTENT_WIDTH = 600; // Group packs by category function groupPacksByCategory( packs: QuestionPack[], categories: Category[] ): { category: Category; packs: QuestionPack[] }[] { const categoryMap = new Map(); const uncategorized: QuestionPack[] = []; // Initialize map with empty arrays for each category categories.forEach((cat) => { categoryMap.set(cat.id, []); }); // Group packs packs.forEach((pack) => { if (pack.category_id && categoryMap.has(pack.category_id)) { categoryMap.get(pack.category_id)!.push(pack); } else { uncategorized.push(pack); } }); // Build result array maintaining category sort order const result: { category: Category; packs: QuestionPack[] }[] = []; categories.forEach((cat) => { const categoryPacks = categoryMap.get(cat.id) || []; if (categoryPacks.length > 0) { result.push({ category: cat, packs: categoryPacks }); } }); // Add uncategorized at the end if any if (uncategorized.length > 0) { result.push({ category: { id: 'uncategorized', name: 'More', description: null, icon: 'ellipsis-horizontal', color: null, sort_order: 999, created_at: '', is_public: true, }, packs: uncategorized, }); } return result; } export default function DiscoveryScreen() { const { user, partner, couple } = useAuthStore(); const { packs, categories, fetchPacks, getPackProgress } = usePacksStore(); const { width } = useWindowDimensions(); const [showPaywall, setShowPaywall] = useState(false); const isPremiumUser = user?.is_premium ?? false; const isWideScreen = width > MAX_CONTENT_WIDTH; // Refresh data when screen gains focus useFocusEffect( useCallback(() => { fetchPacks(); }, []) ); // Group packs by category const packsByCategory = useMemo( () => groupPacksByCategory(packs, categories), [packs, categories] ); // Check if user has no packs enabled (empty state) const hasNoPacks = packs.length === 0; return ( {/* Compact Header */} {/* Content Rows by Category */} {packsByCategory.map((group, index) => ( setShowPaywall(true)} /> ))} {/* Empty state when no packs */} {hasNoPacks && ( No packs available Check back soon for new content )} {/* Paywall Modal */} setShowPaywall(false)} onSuccess={() => { setShowPaywall(false); fetchPacks(); // Refresh packs to update lock status }} /> ); } const styles = StyleSheet.create({ container: { flex: 1, }, contentContainer: { flexGrow: 1, paddingBottom: Platform.OS === 'ios' ? 100 : 80, }, contentContainerWide: { alignItems: 'center', }, innerContainer: { flex: 1, width: '100%', }, innerContainerWide: { maxWidth: MAX_CONTENT_WIDTH, }, emptyState: { flex: 1, justifyContent: 'center', alignItems: 'center', paddingHorizontal: spacing.xl, paddingVertical: spacing.xxl, }, emptyIcon: { width: 80, height: 80, borderRadius: 40, backgroundColor: 'rgba(233, 69, 96, 0.1)', justifyContent: 'center', alignItems: 'center', marginBottom: spacing.lg, }, emptyTitle: { ...typography.title3, color: colors.text, marginBottom: spacing.sm, }, emptySubtitle: { ...typography.body, color: colors.textSecondary, textAlign: 'center', }, bottomSpacer: { height: spacing.lg, }, });