diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index cfbc1e2..36210f4 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -1,45 +1,72 @@ import { Tabs } from 'expo-router'; -import React from 'react'; -import { Platform } from 'react-native'; - -import { HapticTab } from '@/components/HapticTab'; -import { IconSymbol } from '@/components/ui/IconSymbol'; -import TabBarBackground from '@/components/ui/TabBarBackground'; -import { Colors } from '@/constants/Colors'; -import { useColorScheme } from '@/hooks/useColorScheme'; +import { Ionicons, MaterialCommunityIcons } from '@expo/vector-icons'; +import { View } from 'react-native'; export default function TabLayout() { - const colorScheme = useColorScheme(); - return ( + }} + > , + tabBarIcon: ({ color }) => ( + + ), }} /> + , + title: 'Recipes', + tabBarIcon: ({ color }) => ( + + ), + }} + /> + + ( + + ), + }} + /> + + ( + + ), }} /> ); -} +} \ No newline at end of file diff --git a/app/(tabs)/explore.tsx b/app/(tabs)/explore.tsx deleted file mode 100644 index d4fbcaa..0000000 --- a/app/(tabs)/explore.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { Image } from 'expo-image'; -import { Platform, StyleSheet } from 'react-native'; - -import { Collapsible } from '@/components/Collapsible'; -import { ExternalLink } from '@/components/ExternalLink'; -import ParallaxScrollView from '@/components/ParallaxScrollView'; -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; -import { IconSymbol } from '@/components/ui/IconSymbol'; - -export default function TabTwoScreen() { - return ( - - }> - - Explore - - This app includes example code to help you get started. - - - This app has two screens:{' '} - app/(tabs)/index.tsx and{' '} - app/(tabs)/explore.tsx - - - The layout file in app/(tabs)/_layout.tsx{' '} - sets up the tab navigator. - - - Learn more - - - - - You can open this project on Android, iOS, and the web. To open the web version, press{' '} - w in the terminal running this project. - - - - - For static images, you can use the @2x and{' '} - @3x suffixes to provide files for - different screen densities - - - - Learn more - - - - - Open app/_layout.tsx to see how to load{' '} - - custom fonts such as this one. - - - - Learn more - - - - - This template has light and dark mode support. The{' '} - useColorScheme() hook lets you inspect - what the user's current color scheme is, and so you can adjust UI colors accordingly. - - - Learn more - - - - - This template includes an example of an animated component. The{' '} - components/HelloWave.tsx component uses - the powerful react-native-reanimated{' '} - library to create a waving hand animation. - - {Platform.select({ - ios: ( - - The components/ParallaxScrollView.tsx{' '} - component provides a parallax effect for the header image. - - ), - })} - - - ); -} - -const styles = StyleSheet.create({ - headerImage: { - color: '#808080', - bottom: -90, - left: -35, - position: 'absolute', - }, - titleContainer: { - flexDirection: 'row', - gap: 8, - }, -}); diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 462e8cd..bfbc1bb 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -1,75 +1,253 @@ -import { Image } from 'expo-image'; -import { Platform, StyleSheet } from 'react-native'; +import React, { useState } from 'react'; +import { View, Text, Image, TextInput, TouchableOpacity, SafeAreaView, StatusBar, ScrollView, Alert } from 'react-native'; +import { Feather, FontAwesome, Ionicons } from '@expo/vector-icons'; +import { router } from 'expo-router'; +import * as ImagePicker from 'expo-image-picker'; -import { HelloWave } from '@/components/HelloWave'; -import ParallaxScrollView from '@/components/ParallaxScrollView'; -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; +// Sample recipe data +const recipeData = [ + { + id: 1, + title: "Pad Kra Pao Moo Sab with Eggs", + image: "/placeholder.svg?height=400&width=400&query=thai basil stir fry with egg and rice", + color: "#ffd60a" + }, + { + id: 2, + title: "Chicken Curry", + image: "/placeholder.svg?height=400&width=400&query=chicken curry with rice", + color: "#ffd60a" + }, + { + id: 3, + title: "Beef Steak", + image: "/placeholder.svg?height=400&width=400&query=beef steak with vegetables", + color: "#bb0718" + }, + { + id: 4, + title: "Vegetable Pasta", + image: "/placeholder.svg?height=400&width=400&query=vegetable pasta", + color: "#ffd60a" + }, + { + id: 5, + title: "Salmon Sushi", + image: "/placeholder.svg?height=400&width=400&query=salmon sushi", + color: "#ffd60a" + } +]; export default function HomeScreen() { - return ( - - }> - - Welcome! - - - - Step 1: Try it - - Edit app/(tabs)/index.tsx to see changes. - Press{' '} - - {Platform.select({ - ios: 'cmd + d', - android: 'cmd + m', - web: 'F12', - })} - {' '} - to open developer tools. - - - - Step 2: Explore - - {`Tap the Explore tab to learn more about what's included in this starter app.`} - - - - Step 3: Get a fresh start - - {`When you're ready, run `} - npm run reset-project to get a fresh{' '} - app directory. This will move the current{' '} - app to{' '} - app-example. - - - - ); -} + const [searchQuery, setSearchQuery] = useState(''); + const [filteredRecipes, setFilteredRecipes] = useState(recipeData); + + // Handle search + const handleSearch = (text: string): void => { + setSearchQuery(text); + if (text) { + const filtered = recipeData.filter((recipe: Recipe) => + recipe.title.toLowerCase().includes(text.toLowerCase()) + ); + setFilteredRecipes(filtered); + } else { + setFilteredRecipes(recipeData); + } + }; + + // Handle camera + const takePhoto = async () => { + const { status } = await ImagePicker.requestCameraPermissionsAsync(); + + if (status !== 'granted') { + Alert.alert('Permission needed', 'Please grant camera permissions to use this feature.'); + return; + } + + const result = await ImagePicker.launchCameraAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + allowsEditing: true, + aspect: [1, 1], + quality: 1, + }); + + if (!result.canceled) { + // Navigate to recipe detail with the captured image + router.push({ + pathname: '/recipe-detail', + params: { + title: 'My New Recipe', + image: result.assets[0].uri + } + }); + } + }; + + // Handle gallery + const pickImage = async () => { + const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); + + if (status !== 'granted') { + Alert.alert('Permission needed', 'Please grant media library permissions to use this feature.'); + return; + } + + const result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + allowsEditing: true, + aspect: [1, 1], + quality: 1, + }); + + if (!result.canceled) { + // Navigate to recipe detail with the selected image + router.push({ + pathname: '/recipe-detail', + params: { + title: 'My New Recipe', + image: result.assets[0].uri + } + }); + } + }; + + // Navigate to recipe detail + interface Recipe { + id: number; + title: string; + image: string; + color: string; + } -const styles = StyleSheet.create({ - titleContainer: { - flexDirection: 'row', - alignItems: 'center', - gap: 8, - }, - stepContainer: { - gap: 8, - marginBottom: 8, - }, - reactLogo: { - height: 178, - width: 290, - bottom: 0, - left: 0, - position: 'absolute', - }, -}); + const goToRecipeDetail = (recipe: Recipe): void => { + router.push({ + pathname: '/recipe-detail', + params: { + title: recipe.title, + image: recipe.image + } + }); + }; + + return ( + + + + {/* Header - Fixed at top */} + + Hi! Mr. Chef + + + + + + {/* Scrollable Content */} + + {/* Center Image */} + + + + + + + + + + + {/* Highlights Section */} + + + Highlights + + + + + + {filteredRecipes.slice(0, 3).map((recipe) => ( + goToRecipeDetail(recipe)} + > + + + ))} + + + + + {filteredRecipes.slice(3, 5).map((recipe) => ( + goToRecipeDetail(recipe)} + > + + + ))} + + + + {/* Show your dishes */} + + + Show your dishes + + + + + + + + + + + + + + + From Camera + Straight from Camera + + + + + + + From Gallery + Straight from Gallery + + + + + + {/* Extra space at bottom */} + + + + ); +} \ No newline at end of file diff --git a/app/_layout.tsx b/app/_layout.tsx index fd827d9..0b15951 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,30 +1,25 @@ -import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'; -import { useFonts } from 'expo-font'; import { Stack } from 'expo-router'; -import { StatusBar } from 'expo-status-bar'; -import 'react-native-reanimated'; -import "../global.css"; - -import { useColorScheme } from '@/hooks/useColorScheme'; +import { GestureHandlerRootView } from 'react-native-gesture-handler'; +import "../global.css" export default function RootLayout() { - const colorScheme = useColorScheme(); - const [loaded] = useFonts({ - SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'), - }); - - if (!loaded) { - // Async font loading only occurs in development. - return null; - } - return ( - - - - + + + + - - + ); -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5d1de14..a73cf83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "expo-font": "~13.3.1", "expo-haptics": "~14.1.4", "expo-image": "~2.1.7", + "expo-image-picker": "~16.1.4", "expo-linking": "~7.1.4", "expo-router": "~5.0.6", "expo-splash-screen": "~0.30.8", @@ -2263,6 +2264,7 @@ "version": "14.1.0", "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-14.1.0.tgz", "integrity": "sha512-7T09UE9h8QDTsUeMGymB4i+iqvtEeaO5VvUjryFB4tugDTG/bkzViWA74hm5pfjjDEhYMXWaX112mcvhccmIwQ==", + "license": "MIT", "peerDependencies": { "expo-font": "*", "react": "*", @@ -6317,6 +6319,27 @@ } } }, + "node_modules/expo-image-loader": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-5.1.0.tgz", + "integrity": "sha512-sEBx3zDQIODWbB5JwzE7ZL5FJD+DK3LVLWBVJy6VzsqIA6nDEnSFnsnWyCfCTSvbGigMATs1lgkC2nz3Jpve1Q==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-picker": { + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-16.1.4.tgz", + "integrity": "sha512-bTmmxtw1AohUT+HxEBn2vYwdeOrj1CLpMXKjvi9FKSoSbpcarT4xxI0z7YyGwDGHbrJqyyic3I9TTdP2J2b4YA==", + "license": "MIT", + "dependencies": { + "expo-image-loader": "~5.1.0" + }, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-keep-awake": { "version": "14.1.4", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.1.4.tgz", diff --git a/package.json b/package.json index f3d99d4..bd73d78 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "expo-font": "~13.3.1", "expo-haptics": "~14.1.4", "expo-image": "~2.1.7", + "expo-image-picker": "~16.1.4", "expo-linking": "~7.1.4", "expo-router": "~5.0.6", "expo-splash-screen": "~0.30.8", diff --git a/tsconfig.json b/tsconfig.json index 909e901..2f35dd4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,7 @@ "**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", - "expo-env.d.ts" + "expo-env.d.ts", + "nativewind-env.d.ts" ] -} +} \ No newline at end of file