Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implemented search #1

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/components/ListCategories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Category = {
type ListCategoriesProps = {
categories: Category[];
activeCategory: string;
handleChangeCategory: () => void;
handleChangeCategory: (category: string) => void;
}

export function ListCategories({ categories, activeCategory, handleChangeCategory }: ListCategoriesProps) {
Expand Down Expand Up @@ -56,4 +56,4 @@ export function ListCategories({ categories, activeCategory, handleChangeCategor
</ScrollView>
</Animated.View>
);
}
}
19 changes: 9 additions & 10 deletions src/components/RecipleCard.tsx → src/components/RecipeCard.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
import React from 'react';
import { Pressable, Text } from 'react-native';

import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen';
import { heightPercentageToDP as hp } from 'react-native-responsive-screen';
import Animated, { FadeInDown } from 'react-native-reanimated';
import { CachedImage } from '@/helpers/image';
import { useNavigation } from '@react-navigation/native';
import type {NavigationProp} from "@react-navigation/core/src/types";

type ItemProp = {
export type RecipeItemProp = {
strMeal: string;
strMealThumb: string;
idMeal: string;
}

type RecipleCardProps = {
export type RecipeCardProps = {
index: number;
item: ItemProp;
item: RecipeItemProp;
navigation: NavigationProp<any>;
}

export function RecipleCard({ item, index, navigation }: RecipleCardProps) {
export function RecipeCard({ item, index, navigation }: RecipeCardProps) {

let isEven = index % 2 == 0
return (
<Animated.View entering={FadeInDown.delay(index * 100).duration(600).springify().damping(12)}>
<Pressable
style={{ width: '100%', paddingLeft: isEven ? 0 : 8, paddingRight: isEven ? 8 : 0 }}
className='flex justify-center mb-4 space-y-4'
onPress={() => navigation.navigate('RecipleDetail', { ...item })}
onPress={() => navigation.navigate('RecipeDetail', { ...item })}
>

<Animated.Image
Expand Down Expand Up @@ -53,4 +52,4 @@ export function RecipleCard({ item, index, navigation }: RecipleCardProps) {
</Pressable>
</Animated.View>
)
}
}
37 changes: 17 additions & 20 deletions src/components/Recipes.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,38 @@
import React from 'react';
import { Text, View } from 'react-native';

import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen';
import {Text, View} from 'react-native';
import {heightPercentageToDP as hp} from 'react-native-responsive-screen';
import MasonryList from '@react-native-seoul/masonry-list';
import { RecipleCard } from './RecipleCard';

import {
RecipeCard,
RecipeItemProp
} from './RecipeCard';
import Loading from './Loading';
import {useNavigation} from '@react-navigation/native';

import { useNavigation } from '@react-navigation/native';


export function Recipes({ categories, meals }) {

export function Recipes({categories, meals}: { categories: any[], meals: RecipeItemProp[] }) {
const navigation = useNavigation();

return (
<View className='mx-4 space-y-3'>
<Text style={{ fontSize: hp(3) }} className='font-semibold text-neutral-600'>Recipes</Text>
<Text style={{fontSize: hp(3)}} className='font-semibold text-neutral-600'>Recipes</Text>
<View>
{
(categories.length == 0 && meals == 0)
? (<Loading size={"large"} className='mt-20' />)
(categories.length === 0 && meals.length === 0)
? (<Loading size={"large"} className='mt-20'/>)
: (
<MasonryList
<MasonryList<RecipeItemProp>
data={meals}
keyExtractor={(item): string => item.idMeal}
keyExtractor={(item: RecipeItemProp): string => item.idMeal}
numColumns={2}
showsVerticalScrollIndicator={false}
renderItem={({ item, i }) => <RecipleCard item={item} index={i} navigation={navigation} />}
// refreshing={isLoadingNext}
// onRefresh={() => refetch({ first: ITEM_CNT })}
renderItem={({item, i}: { item: RecipeItemProp, i: number }) => <RecipeCard item={item}
index={i}
navigation={navigation}/>}
onEndReachedThreshold={0.1}
// onEndReached={() => loadNext(ITEM_CNT)}
/>)
}

</View>
</View>
);
}
}
6 changes: 3 additions & 3 deletions src/routes/appRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { HomeScreen } from '@/screens/HomeScreen';
import { WelcomeScreen } from '@/screens/WelcomeScreen';
import { RecipleDetailScreen } from '@/screens/RecipleDetailScreen';
import { RecipeDetailScreen } from '@/screens/RecipeDetailScreen';



Expand All @@ -16,8 +16,8 @@ export function AppRoutes() {
<Navigator initialRouteName='Welcome' screenOptions={{ headerShown: false }}>
<Screen name='Home' component={HomeScreen} />
<Screen name='Welcome' component={WelcomeScreen} />
<Screen name='RecipleDetail' component={RecipleDetailScreen} />
<Screen name='RecipeDetail' component={RecipeDetailScreen} />
</Navigator>
</NavigationContainer>
);
}
}
29 changes: 24 additions & 5 deletions src/screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export function HomeScreen() {
const [activeCategory, setActiveCategory] = useState('Beef');
const [categories, setCategories] = useState([]);
const [meals, setMeals] = useState([]);
const [searchTerm, setSearchTerm] = useState(''); // New state variable for the search term


const getCategories = async () => {
Expand All @@ -26,7 +27,7 @@ export function HomeScreen() {
}
}

const getReciples = async (category = "Beef") => {
const getRecipes = async (category = "Beef") => {
try {
const response = await axios.get(`https://www.themealdb.com/api/json/v1/1/filter.php?c=${category}`);
if (response && response.data) {
Expand All @@ -37,24 +38,41 @@ export function HomeScreen() {
}
}

const handleChangeCategory = (category: string) => {
getReciples(category);
const handleChangeCategory = async (category: string) => {
await getRecipes(category);
setActiveCategory(category);
setMeals([]);
}

const getSearchResults = async () => {
try {
const response = await axios.get(`https://www.themealdb.com/api/json/v1/1/search.php?s=${searchTerm}`);
if (response && response.data) {
setMeals(response.data?.meals ?? []);
}
} catch (err) {
console.log("Error: ", err);
}
}

useEffect(() => {
const fetchData = async () => {
try {
await getCategories();
await getReciples();
await getRecipes();
} catch (error) {
console.error("Erro ao carregar dados:", error);
}
};
fetchData();
}, []);

useEffect(() => {
if (searchTerm) {
getSearchResults();
}
}, [searchTerm]);

return (
<View className='flex-1 bg-white'>

Expand Down Expand Up @@ -84,6 +102,7 @@ export function HomeScreen() {
placeholder='Search any recipe'
placeholderTextColor={'gray'}
className='flex-1 text-base mb-1 pl-3 tracking-wide'
onChangeText={text => setSearchTerm(text)}
/>
<View className='bg-white rounded-full p-3'>
<MagnifyingGlassIcon size={hp(2.5)} strokeWidth={3} color={'gray'} />
Expand Down Expand Up @@ -111,4 +130,4 @@ export function HomeScreen() {

</View>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Loading from '@/components/Loading';
import YoutubeIframe from 'react-native-youtube-iframe';
import Animated, { FadeIn, FadeInDown } from 'react-native-reanimated';

export function RecipleDetailScreen(props) {
export function RecipeDetailScreen(props) {

const [isFavourite, setIsFavourite] = useState(false);
const [meal, setMeal] = useState(null);
Expand Down Expand Up @@ -265,7 +265,7 @@ export function RecipleDetailScreen(props) {
<Animated.View
entering={FadeInDown.delay(300).duration(700).springify().damping(12)} className='space-y-4'>
<Text style={{ fontSize: hp(2.5) }} className='font-bold flex-1 text-neutral-600'>
Reciple Video
Recipe Video
</Text>
<View>
<YoutubeIframe
Expand All @@ -282,4 +282,4 @@ export function RecipleDetailScreen(props) {

</ScrollView>
);
}
}