mirror of
https://github.com/Sosokker/chefhai.git
synced 2025-12-19 14:04:08 +01:00
create home page
This commit is contained in:
parent
d33796154d
commit
d074115a71
@ -1,43 +1,70 @@
|
|||||||
import { Tabs } from 'expo-router';
|
import { Tabs } from 'expo-router';
|
||||||
import React from 'react';
|
import { Ionicons, MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { Platform } from 'react-native';
|
import { View } 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';
|
|
||||||
|
|
||||||
export default function TabLayout() {
|
export default function TabLayout() {
|
||||||
const colorScheme = useColorScheme();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
|
tabBarStyle: {
|
||||||
headerShown: false,
|
backgroundColor: '#ffd60a',
|
||||||
tabBarButton: HapticTab,
|
height: 70,
|
||||||
tabBarBackground: TabBarBackground,
|
borderTopLeftRadius: 0,
|
||||||
tabBarStyle: Platform.select({
|
borderTopRightRadius: 0,
|
||||||
ios: {
|
|
||||||
// Use a transparent background on iOS to show the blur effect
|
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
elevation: 0,
|
||||||
|
borderTopWidth: 0,
|
||||||
},
|
},
|
||||||
default: {},
|
tabBarActiveTintColor: '#bb0718',
|
||||||
}),
|
tabBarInactiveTintColor: '#bb0718',
|
||||||
}}>
|
tabBarShowLabel: true,
|
||||||
|
tabBarLabelStyle: {
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: '500',
|
||||||
|
},
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
name="index"
|
name="index"
|
||||||
options={{
|
options={{
|
||||||
title: 'Home',
|
title: 'Home',
|
||||||
tabBarIcon: ({ color }) => <IconSymbol size={28} name="house.fill" color={color} />,
|
tabBarIcon: ({ color }) => (
|
||||||
|
<Ionicons name="home-outline" size={24} color={color} />
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
name="explore"
|
name="recipes"
|
||||||
options={{
|
options={{
|
||||||
title: 'Explore',
|
title: 'Recipes',
|
||||||
tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />,
|
tabBarIcon: ({ color }) => (
|
||||||
|
<MaterialCommunityIcons name="notebook-outline" size={24} color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Tabs.Screen
|
||||||
|
name="forum"
|
||||||
|
options={{
|
||||||
|
title: 'Forum',
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<MaterialCommunityIcons name="forum-outline" size={24} color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Tabs.Screen
|
||||||
|
name="profile"
|
||||||
|
options={{
|
||||||
|
title: 'Profile',
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<Ionicons name="person-outline" size={24} color={color} />
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@ -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 (
|
|
||||||
<ParallaxScrollView
|
|
||||||
headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }}
|
|
||||||
headerImage={
|
|
||||||
<IconSymbol
|
|
||||||
size={310}
|
|
||||||
color="#808080"
|
|
||||||
name="chevron.left.forwardslash.chevron.right"
|
|
||||||
style={styles.headerImage}
|
|
||||||
/>
|
|
||||||
}>
|
|
||||||
<ThemedView style={styles.titleContainer}>
|
|
||||||
<ThemedText type="title">Explore</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedText>This app includes example code to help you get started.</ThemedText>
|
|
||||||
<Collapsible title="File-based routing">
|
|
||||||
<ThemedText>
|
|
||||||
This app has two screens:{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> and{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app/(tabs)/explore.tsx</ThemedText>
|
|
||||||
</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
The layout file in <ThemedText type="defaultSemiBold">app/(tabs)/_layout.tsx</ThemedText>{' '}
|
|
||||||
sets up the tab navigator.
|
|
||||||
</ThemedText>
|
|
||||||
<ExternalLink href="https://docs.expo.dev/router/introduction">
|
|
||||||
<ThemedText type="link">Learn more</ThemedText>
|
|
||||||
</ExternalLink>
|
|
||||||
</Collapsible>
|
|
||||||
<Collapsible title="Android, iOS, and web support">
|
|
||||||
<ThemedText>
|
|
||||||
You can open this project on Android, iOS, and the web. To open the web version, press{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">w</ThemedText> in the terminal running this project.
|
|
||||||
</ThemedText>
|
|
||||||
</Collapsible>
|
|
||||||
<Collapsible title="Images">
|
|
||||||
<ThemedText>
|
|
||||||
For static images, you can use the <ThemedText type="defaultSemiBold">@2x</ThemedText> and{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to provide files for
|
|
||||||
different screen densities
|
|
||||||
</ThemedText>
|
|
||||||
<Image source={require('@/assets/images/react-logo.png')} style={{ alignSelf: 'center' }} />
|
|
||||||
<ExternalLink href="https://reactnative.dev/docs/images">
|
|
||||||
<ThemedText type="link">Learn more</ThemedText>
|
|
||||||
</ExternalLink>
|
|
||||||
</Collapsible>
|
|
||||||
<Collapsible title="Custom fonts">
|
|
||||||
<ThemedText>
|
|
||||||
Open <ThemedText type="defaultSemiBold">app/_layout.tsx</ThemedText> to see how to load{' '}
|
|
||||||
<ThemedText style={{ fontFamily: 'SpaceMono' }}>
|
|
||||||
custom fonts such as this one.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedText>
|
|
||||||
<ExternalLink href="https://docs.expo.dev/versions/latest/sdk/font">
|
|
||||||
<ThemedText type="link">Learn more</ThemedText>
|
|
||||||
</ExternalLink>
|
|
||||||
</Collapsible>
|
|
||||||
<Collapsible title="Light and dark mode components">
|
|
||||||
<ThemedText>
|
|
||||||
This template has light and dark mode support. The{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">useColorScheme()</ThemedText> hook lets you inspect
|
|
||||||
what the user's current color scheme is, and so you can adjust UI colors accordingly.
|
|
||||||
</ThemedText>
|
|
||||||
<ExternalLink href="https://docs.expo.dev/develop/user-interface/color-themes/">
|
|
||||||
<ThemedText type="link">Learn more</ThemedText>
|
|
||||||
</ExternalLink>
|
|
||||||
</Collapsible>
|
|
||||||
<Collapsible title="Animations">
|
|
||||||
<ThemedText>
|
|
||||||
This template includes an example of an animated component. The{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">components/HelloWave.tsx</ThemedText> component uses
|
|
||||||
the powerful <ThemedText type="defaultSemiBold">react-native-reanimated</ThemedText>{' '}
|
|
||||||
library to create a waving hand animation.
|
|
||||||
</ThemedText>
|
|
||||||
{Platform.select({
|
|
||||||
ios: (
|
|
||||||
<ThemedText>
|
|
||||||
The <ThemedText type="defaultSemiBold">components/ParallaxScrollView.tsx</ThemedText>{' '}
|
|
||||||
component provides a parallax effect for the header image.
|
|
||||||
</ThemedText>
|
|
||||||
),
|
|
||||||
})}
|
|
||||||
</Collapsible>
|
|
||||||
</ParallaxScrollView>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
headerImage: {
|
|
||||||
color: '#808080',
|
|
||||||
bottom: -90,
|
|
||||||
left: -35,
|
|
||||||
position: 'absolute',
|
|
||||||
},
|
|
||||||
titleContainer: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
gap: 8,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@ -1,75 +1,253 @@
|
|||||||
import { Image } from 'expo-image';
|
import React, { useState } from 'react';
|
||||||
import { Platform, StyleSheet } from 'react-native';
|
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';
|
// Sample recipe data
|
||||||
import ParallaxScrollView from '@/components/ParallaxScrollView';
|
const recipeData = [
|
||||||
import { ThemedText } from '@/components/ThemedText';
|
{
|
||||||
import { ThemedView } from '@/components/ThemedView';
|
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() {
|
export default function HomeScreen() {
|
||||||
return (
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
<ParallaxScrollView
|
const [filteredRecipes, setFilteredRecipes] = useState(recipeData);
|
||||||
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
|
|
||||||
headerImage={
|
// Handle search
|
||||||
<Image
|
const handleSearch = (text: string): void => {
|
||||||
source={require('@/assets/images/partial-react-logo.png')}
|
setSearchQuery(text);
|
||||||
style={styles.reactLogo}
|
if (text) {
|
||||||
/>
|
const filtered = recipeData.filter((recipe: Recipe) =>
|
||||||
}>
|
recipe.title.toLowerCase().includes(text.toLowerCase())
|
||||||
<ThemedView style={styles.titleContainer}>
|
|
||||||
<ThemedText type="title">Welcome!</ThemedText>
|
|
||||||
<HelloWave />
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
|
||||||
Press{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">
|
|
||||||
{Platform.select({
|
|
||||||
ios: 'cmd + d',
|
|
||||||
android: 'cmd + m',
|
|
||||||
web: 'F12',
|
|
||||||
})}
|
|
||||||
</ThemedText>{' '}
|
|
||||||
to open developer tools.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
{`Tap the Explore tab to learn more about what's included in this starter app.`}
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
{`When you're ready, run `}
|
|
||||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
</ParallaxScrollView>
|
|
||||||
);
|
);
|
||||||
|
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 styles = StyleSheet.create({
|
const result = await ImagePicker.launchCameraAsync({
|
||||||
titleContainer: {
|
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
||||||
flexDirection: 'row',
|
allowsEditing: true,
|
||||||
alignItems: 'center',
|
aspect: [1, 1],
|
||||||
gap: 8,
|
quality: 1,
|
||||||
},
|
|
||||||
stepContainer: {
|
|
||||||
gap: 8,
|
|
||||||
marginBottom: 8,
|
|
||||||
},
|
|
||||||
reactLogo: {
|
|
||||||
height: 178,
|
|
||||||
width: 290,
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
position: 'absolute',
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 goToRecipeDetail = (recipe: Recipe): void => {
|
||||||
|
router.push({
|
||||||
|
pathname: '/recipe-detail',
|
||||||
|
params: {
|
||||||
|
title: recipe.title,
|
||||||
|
image: recipe.image
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView className="flex-1 bg-white">
|
||||||
|
<StatusBar barStyle="dark-content" />
|
||||||
|
|
||||||
|
{/* Header - Fixed at top */}
|
||||||
|
<View className="flex-row justify-between items-center px-6 pt-4 pb-2">
|
||||||
|
<Text className="text-3xl font-bold">Hi! Mr. Chef</Text>
|
||||||
|
<View className="bg-[#ffd60a] p-3 rounded-lg">
|
||||||
|
<Ionicons name="settings-outline" size={24} color="black" />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Scrollable Content */}
|
||||||
|
<ScrollView
|
||||||
|
className="flex-1"
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
contentContainerStyle={{ paddingBottom: 100 }}
|
||||||
|
>
|
||||||
|
{/* Center Image */}
|
||||||
|
<View className="items-center justify-center my-8">
|
||||||
|
<View className="w-32 h-32 items-center justify-center bg-[#fff5e6] rounded-full">
|
||||||
|
<View className="flex-row items-center">
|
||||||
|
<View className="absolute flex-row">
|
||||||
|
<Image
|
||||||
|
source={{ uri: "/placeholder.svg?height=60&width=60&query=orange fruit with green leaf" }}
|
||||||
|
className="w-14 h-14"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Highlights Section */}
|
||||||
|
<View className="px-6 mb-6">
|
||||||
|
<View className="flex-row items-center mb-4">
|
||||||
|
<Text className="text-2xl font-bold mr-2">Highlights</Text>
|
||||||
|
<FontAwesome name="star" size={20} color="#ffd60a" />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScrollView horizontal showsHorizontalScrollIndicator={false} className="mb-4">
|
||||||
|
<View className="flex-row">
|
||||||
|
{filteredRecipes.slice(0, 3).map((recipe) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={recipe.id}
|
||||||
|
className={`w-36 h-40 bg-[${recipe.color}] rounded-xl mr-3 overflow-hidden`}
|
||||||
|
onPress={() => goToRecipeDetail(recipe)}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
source={{ uri: recipe.image }}
|
||||||
|
className="w-full h-full opacity-70"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<View className="flex-row">
|
||||||
|
{filteredRecipes.slice(3, 5).map((recipe) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={recipe.id}
|
||||||
|
className={`w-36 h-40 bg-[${recipe.color}] rounded-xl mr-3 overflow-hidden`}
|
||||||
|
onPress={() => goToRecipeDetail(recipe)}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
source={{ uri: recipe.image }}
|
||||||
|
className="w-full h-full opacity-70"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Show your dishes */}
|
||||||
|
<View className="px-6 mb-6">
|
||||||
|
<View className="flex-row items-center mb-4">
|
||||||
|
<Text className="text-2xl font-bold mr-2">Show your dishes</Text>
|
||||||
|
<Feather name="wifi" size={20} color="black" />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View className="bg-white border border-gray-300 rounded-full mb-6 flex-row items-center px-4 py-3">
|
||||||
|
<TextInput
|
||||||
|
className="flex-1"
|
||||||
|
placeholder="Search..."
|
||||||
|
value={searchQuery}
|
||||||
|
onChangeText={handleSearch}
|
||||||
|
/>
|
||||||
|
<View className="bg-[#ffd60a] p-2 rounded-full">
|
||||||
|
<Feather name="send" size={20} color="black" />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View className="flex-row justify-between">
|
||||||
|
<TouchableOpacity
|
||||||
|
className="bg-[#ffd60a] p-4 rounded-xl w-[48%]"
|
||||||
|
onPress={takePhoto}
|
||||||
|
>
|
||||||
|
<View className="items-center">
|
||||||
|
<FontAwesome name="camera" size={24} color="black" />
|
||||||
|
<Text className="text-lg font-bold mt-2">From Camera</Text>
|
||||||
|
<Text className="text-sm text-gray-700">Straight from Camera</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
className="bg-[#f9be25] p-4 rounded-xl w-[48%]"
|
||||||
|
onPress={pickImage}
|
||||||
|
>
|
||||||
|
<View className="items-center">
|
||||||
|
<Feather name="image" size={24} color="black" />
|
||||||
|
<Text className="text-lg font-bold mt-2">From Gallery</Text>
|
||||||
|
<Text className="text-sm text-gray-700">Straight from Gallery</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Extra space at bottom */}
|
||||||
|
<View className="h-20"></View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,30 +1,25 @@
|
|||||||
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
|
|
||||||
import { useFonts } from 'expo-font';
|
|
||||||
import { Stack } from 'expo-router';
|
import { Stack } from 'expo-router';
|
||||||
import { StatusBar } from 'expo-status-bar';
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||||
import 'react-native-reanimated';
|
import "../global.css"
|
||||||
import "../global.css";
|
|
||||||
|
|
||||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
|
||||||
|
|
||||||
export default function RootLayout() {
|
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 (
|
return (
|
||||||
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
||||||
<Stack>
|
<Stack screenOptions={{ headerShown: false }}>
|
||||||
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
<Stack.Screen
|
||||||
<Stack.Screen name="+not-found" />
|
name="(tabs)"
|
||||||
|
options={{
|
||||||
|
headerShown: false
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="recipe-detail"
|
||||||
|
options={{
|
||||||
|
headerShown: false,
|
||||||
|
presentation: 'card'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<StatusBar style="auto" />
|
</GestureHandlerRootView>
|
||||||
</ThemeProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
23
package-lock.json
generated
23
package-lock.json
generated
@ -19,6 +19,7 @@
|
|||||||
"expo-font": "~13.3.1",
|
"expo-font": "~13.3.1",
|
||||||
"expo-haptics": "~14.1.4",
|
"expo-haptics": "~14.1.4",
|
||||||
"expo-image": "~2.1.7",
|
"expo-image": "~2.1.7",
|
||||||
|
"expo-image-picker": "~16.1.4",
|
||||||
"expo-linking": "~7.1.4",
|
"expo-linking": "~7.1.4",
|
||||||
"expo-router": "~5.0.6",
|
"expo-router": "~5.0.6",
|
||||||
"expo-splash-screen": "~0.30.8",
|
"expo-splash-screen": "~0.30.8",
|
||||||
@ -2263,6 +2264,7 @@
|
|||||||
"version": "14.1.0",
|
"version": "14.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-14.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-14.1.0.tgz",
|
||||||
"integrity": "sha512-7T09UE9h8QDTsUeMGymB4i+iqvtEeaO5VvUjryFB4tugDTG/bkzViWA74hm5pfjjDEhYMXWaX112mcvhccmIwQ==",
|
"integrity": "sha512-7T09UE9h8QDTsUeMGymB4i+iqvtEeaO5VvUjryFB4tugDTG/bkzViWA74hm5pfjjDEhYMXWaX112mcvhccmIwQ==",
|
||||||
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"expo-font": "*",
|
"expo-font": "*",
|
||||||
"react": "*",
|
"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": {
|
"node_modules/expo-keep-awake": {
|
||||||
"version": "14.1.4",
|
"version": "14.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.1.4.tgz",
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
"expo-font": "~13.3.1",
|
"expo-font": "~13.3.1",
|
||||||
"expo-haptics": "~14.1.4",
|
"expo-haptics": "~14.1.4",
|
||||||
"expo-image": "~2.1.7",
|
"expo-image": "~2.1.7",
|
||||||
|
"expo-image-picker": "~16.1.4",
|
||||||
"expo-linking": "~7.1.4",
|
"expo-linking": "~7.1.4",
|
||||||
"expo-router": "~5.0.6",
|
"expo-router": "~5.0.6",
|
||||||
"expo-splash-screen": "~0.30.8",
|
"expo-splash-screen": "~0.30.8",
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
"**/*.ts",
|
"**/*.ts",
|
||||||
"**/*.tsx",
|
"**/*.tsx",
|
||||||
".expo/types/**/*.ts",
|
".expo/types/**/*.ts",
|
||||||
"expo-env.d.ts"
|
"expo-env.d.ts",
|
||||||
|
"nativewind-env.d.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user