import { router } from 'expo-router'; import { useMemo, useState } from 'react'; import { ActivityIndicator, FlatList, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { fetchRecipes } from '@/src/api/recipes.api'; import { EmptyState, RecipeCard } from '@/src/components/RecipeCard'; import { ErrorView } from '@/src/components/ErrorView'; import { Input } from '@/src/components/Input'; import { Screen } from '@/src/components/Screen'; import { useAppearance } from '@/src/context/AppearanceContext'; import { nextSort, sortBy, sortIndicator, type SortDirection } from '@/src/utils/sort'; type RecipeSortColumn = 'name' | 'calories' | 'prepTime'; const RECIPE_SORT_COLUMNS: { id: RecipeSortColumn; labelKey: string }[] = [ { id: 'name', labelKey: 'manage.recipeName' }, { id: 'calories', labelKey: 'recipes.calories' }, { id: 'prepTime', labelKey: 'manage.prepTimeMin' }, ]; export default function MealsScreen() { const { t } = useTranslation(); const { colors } = useAppearance(); const [search, setSearch] = useState(''); const [ingredient, setIngredient] = useState(''); const [recipeSort, setRecipeSort] = useState<{ column: RecipeSortColumn; direction: SortDirection }>({ column: 'name', direction: 'asc', }); const recipesQuery = useQuery({ queryKey: ['recipes', search, ingredient], queryFn: () => fetchRecipes({ search: search.trim() || undefined, ingredient: ingredient.trim() || undefined, }), }); const emptyMessage = useMemo(() => { if (ingredient.trim()) return t('recipes.noMatchingIngredient'); return t('recipes.noMatchingFilter'); }, [ingredient, t]); const sortedRecipes = useMemo(() => { const list = recipesQuery.data ?? []; const { column, direction } = recipeSort; return sortBy(list, direction, (recipe) => { switch (column) { case 'name': return recipe.name; case 'calories': return recipe.calories; case 'prepTime': return recipe.prepTimeMinutes; } }); }, [recipesQuery.data, recipeSort]); return ( {(recipesQuery.data?.length ?? 0) > 0 ? ( {RECIPE_SORT_COLUMNS.map(({ id, labelKey }) => ( setRecipeSort((current) => nextSort(current, id))} /> ))} ) : null} {recipesQuery.isLoading ? ( ) : recipesQuery.isError ? ( recipesQuery.refetch()} /> ) : ( String(item.id)} contentContainerStyle={styles.list} ListEmptyComponent={ } renderItem={({ item }) => ( router.push(`/(main)/recipe/${item.id}`)} /> )} /> )} ); } function SortChip({ label, active, onPress }: { label: string; active: boolean; onPress: () => void }) { const { colors } = useAppearance(); return ( {label} ); } const styles = StyleSheet.create({ filters: { gap: 10, }, sortRow: { gap: 8, paddingBottom: 8, }, sortChip: { borderWidth: 1, borderRadius: 999, paddingHorizontal: 12, paddingVertical: 6, }, list: { gap: 10, paddingBottom: 24, flexGrow: 1, }, loading: { flex: 1, alignItems: 'center', justifyContent: 'center', paddingVertical: 40, }, });