add ui placeholder
@ -1,43 +1,57 @@
|
|||||||
import { Tabs } from 'expo-router';
|
import { Tabs } from "expo-router";
|
||||||
import React from 'react';
|
|
||||||
import { Platform } from 'react-native';
|
|
||||||
|
|
||||||
import { HapticTab } from '@/components/HapticTab';
|
import { HapticTab } from "@/components/HapticTab";
|
||||||
import { IconSymbol } from '@/components/ui/IconSymbol';
|
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,
|
tabBarActiveTintColor: "#FF0000", // Red active color
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
tabBarButton: HapticTab,
|
tabBarButton: HapticTab,
|
||||||
tabBarBackground: TabBarBackground,
|
tabBarStyle: {
|
||||||
tabBarStyle: Platform.select({
|
backgroundColor: "#FFCC00", // Yellow background
|
||||||
ios: {
|
height: 60,
|
||||||
// Use a transparent background on iOS to show the blur effect
|
paddingBottom: 5,
|
||||||
position: 'absolute',
|
borderTopWidth: 0,
|
||||||
},
|
},
|
||||||
default: {},
|
}}
|
||||||
}),
|
>
|
||||||
}}>
|
|
||||||
<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 }) => (
|
||||||
|
<IconSymbol size={28} name="house.fill" 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 }) => (
|
||||||
|
<IconSymbol size={28} name="doc.text.fill" color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="forum"
|
||||||
|
options={{
|
||||||
|
title: "Forum",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<IconSymbol size={28} name="hand.thumbsup.fill" color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="profile"
|
||||||
|
options={{
|
||||||
|
title: "Profile",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<IconSymbol size={28} name="person.fill" 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,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
260
app/(tabs)/forum.tsx
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
import { IconSymbol } from "@/components/ui/IconSymbol";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import {
|
||||||
|
ScrollView,
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
export default function ForumScreen() {
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container} edges={["top"]}>
|
||||||
|
<ScrollView style={styles.scrollView}>
|
||||||
|
{/* Search Bar */}
|
||||||
|
<View style={styles.searchContainer}>
|
||||||
|
<IconSymbol name="magnifyingglass" size={20} color="#FF0000" />
|
||||||
|
<TextInput
|
||||||
|
style={styles.searchInput}
|
||||||
|
placeholder="Search"
|
||||||
|
placeholderTextColor="#FF0000"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Category Filters */}
|
||||||
|
<View style={styles.categoryContainer}>
|
||||||
|
<TouchableOpacity style={styles.categoryButton}>
|
||||||
|
<Text style={styles.categoryText}>Main dish</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.categoryButton}>
|
||||||
|
<Text style={styles.categoryText}>Dessert</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.categoryButton}>
|
||||||
|
<Text style={styles.categoryText}>Appetite</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Filter Options */}
|
||||||
|
<View style={styles.filterContainer}>
|
||||||
|
<TouchableOpacity style={styles.filterButton}>
|
||||||
|
<Text style={styles.filterText}>Rating</Text>
|
||||||
|
<IconSymbol name="star.fill" size={16} color="#FFCC00" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.filterButton}>
|
||||||
|
<Text style={styles.filterText}>Newest</Text>
|
||||||
|
<IconSymbol name="calendar" size={16} color="#FFFFFF" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.filterButton}>
|
||||||
|
<Text style={styles.filterText}>Best</Text>
|
||||||
|
<IconSymbol name="flame.fill" size={16} color="#FFCC00" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Post */}
|
||||||
|
<View style={styles.postContainer}>
|
||||||
|
{/* User Info */}
|
||||||
|
<View style={styles.userInfoContainer}>
|
||||||
|
<View style={styles.userInfo}>
|
||||||
|
<View style={styles.userAvatar}>
|
||||||
|
<IconSymbol
|
||||||
|
name="person.circle.fill"
|
||||||
|
size={24}
|
||||||
|
color="#888888"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.userName}>Mr. Chef</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.ratingContainer}>
|
||||||
|
<Text style={styles.ratingText}>4.2</Text>
|
||||||
|
<IconSymbol name="star.fill" size={16} color="#FFCC00" />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Post Image */}
|
||||||
|
<Image
|
||||||
|
source={require("@/assets/images/placeholder-food.jpg")}
|
||||||
|
style={styles.postImage}
|
||||||
|
contentFit="cover"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Post Content */}
|
||||||
|
<View style={styles.postContent}>
|
||||||
|
<Text style={styles.postTitle}>Kajjecaw</Text>
|
||||||
|
<Text style={styles.postDescription}>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut at
|
||||||
|
hendrerit enim. Etiam lacinia mi nec nunc ornare, vitae tempus leo
|
||||||
|
aliquet...
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Post Actions */}
|
||||||
|
<View style={styles.postActions}>
|
||||||
|
<TouchableOpacity style={styles.actionButton}>
|
||||||
|
<IconSymbol
|
||||||
|
name="arrowshape.turn.up.left.fill"
|
||||||
|
size={16}
|
||||||
|
color="#888888"
|
||||||
|
/>
|
||||||
|
<Text style={styles.actionText}>3</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.actionButton}>
|
||||||
|
<IconSymbol name="text.bubble.fill" size={16} color="#888888" />
|
||||||
|
<Text style={styles.actionText}>2</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.actionButton}>
|
||||||
|
<IconSymbol name="heart.fill" size={16} color="#888888" />
|
||||||
|
<Text style={styles.actionText}>2</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.actionButton}>
|
||||||
|
<IconSymbol name="bookmark.fill" size={16} color="#888888" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
},
|
||||||
|
scrollView: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
searchContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 16,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
height: 40,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
borderRadius: 20,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#DDDDDD",
|
||||||
|
},
|
||||||
|
searchInput: {
|
||||||
|
flex: 1,
|
||||||
|
marginLeft: 8,
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
categoryContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
categoryButton: {
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
paddingVertical: 12,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
borderRadius: 12,
|
||||||
|
flex: 1,
|
||||||
|
marginHorizontal: 4,
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
categoryText: {
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
filterContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
filterButton: {
|
||||||
|
backgroundColor: "#FF0000",
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
borderRadius: 20,
|
||||||
|
marginRight: 8,
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
filterText: {
|
||||||
|
color: "#FFFFFF",
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginRight: 4,
|
||||||
|
},
|
||||||
|
postContainer: {
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginBottom: 16,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
borderRadius: 12,
|
||||||
|
overflow: "hidden",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#EEEEEE",
|
||||||
|
},
|
||||||
|
userInfoContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
paddingVertical: 8,
|
||||||
|
},
|
||||||
|
userInfo: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
userAvatar: {
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
borderRadius: 16,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
backgroundColor: "#F5F5F5",
|
||||||
|
},
|
||||||
|
userName: {
|
||||||
|
marginLeft: 8,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
ratingContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
ratingText: {
|
||||||
|
marginRight: 4,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
postImage: {
|
||||||
|
width: "100%",
|
||||||
|
height: 200,
|
||||||
|
},
|
||||||
|
postContent: {
|
||||||
|
padding: 12,
|
||||||
|
},
|
||||||
|
postTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: 4,
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
postDescription: {
|
||||||
|
color: "#666666",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
postActions: {
|
||||||
|
flexDirection: "row",
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderTopColor: "#EEEEEE",
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
},
|
||||||
|
actionButton: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginRight: 16,
|
||||||
|
},
|
||||||
|
actionText: {
|
||||||
|
marginLeft: 4,
|
||||||
|
color: "#666666",
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -1,75 +1,321 @@
|
|||||||
import { Image } from 'expo-image';
|
import { Image } from "expo-image";
|
||||||
import { Platform, StyleSheet } from 'react-native';
|
import { router } from "expo-router";
|
||||||
|
import {
|
||||||
|
ScrollView,
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
import { HelloWave } from '@/components/HelloWave';
|
import { IconSymbol } from "@/components/ui/IconSymbol";
|
||||||
import ParallaxScrollView from '@/components/ParallaxScrollView';
|
|
||||||
import { ThemedText } from '@/components/ThemedText';
|
|
||||||
import { ThemedView } from '@/components/ThemedView';
|
|
||||||
|
|
||||||
export default function HomeScreen() {
|
export default function HomeScreen() {
|
||||||
|
const foodHighlights = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Pad Kra Pao Moo Sab with Eggs",
|
||||||
|
image: require("@/assets/images/food/padkrapao.jpg"),
|
||||||
|
description: "Thai stir-fry with ground pork and holy basil",
|
||||||
|
time: "30 Mins",
|
||||||
|
calories: "520 kcal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Jjajangmyeon",
|
||||||
|
image: require("@/assets/images/food/jjajangmyeon.jpg"),
|
||||||
|
description: "Korean black bean noodles",
|
||||||
|
time: "45 Mins",
|
||||||
|
calories: "650 kcal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Ramen",
|
||||||
|
image: require("@/assets/images/food/ramen.jpg"),
|
||||||
|
description: "Japanese noodle soup",
|
||||||
|
time: "60 Mins",
|
||||||
|
calories: "480 kcal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Beef Wellington",
|
||||||
|
image: require("@/assets/images/food/beef.jpg"),
|
||||||
|
description: "Tender beef wrapped in puff pastry",
|
||||||
|
time: "90 Mins",
|
||||||
|
calories: "750 kcal",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const navigateToFoodDetail = (foodId: string) => {
|
||||||
|
router.push({ pathname: "/food/[id]", params: { id: foodId } });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ParallaxScrollView
|
<SafeAreaView style={styles.container} edges={["top"]}>
|
||||||
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
|
<ScrollView style={styles.scrollView}>
|
||||||
headerImage={
|
{/* Header */}
|
||||||
|
<View style={styles.header}>
|
||||||
|
<Text style={styles.greeting}>Hi! Mr. Chef</Text>
|
||||||
|
<TouchableOpacity style={styles.scanButton}>
|
||||||
|
<IconSymbol name="qrcode.viewfinder" size={24} color="#333333" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Hero Section */}
|
||||||
|
<View style={styles.heroContainer}>
|
||||||
|
<View style={styles.heroContent}>
|
||||||
<Image
|
<Image
|
||||||
source={require('@/assets/images/partial-react-logo.png')}
|
source={require("@/assets/images/notebook-orange.png")}
|
||||||
style={styles.reactLogo}
|
style={styles.heroImage}
|
||||||
|
contentFit="contain"
|
||||||
/>
|
/>
|
||||||
}>
|
</View>
|
||||||
<ThemedView style={styles.titleContainer}>
|
</View>
|
||||||
<ThemedText type="title">Welcome!</ThemedText>
|
|
||||||
<HelloWave />
|
{/* Food Highlights Section */}
|
||||||
</ThemedView>
|
<View style={styles.sectionContainer}>
|
||||||
<ThemedView style={styles.stepContainer}>
|
<View style={styles.sectionHeader}>
|
||||||
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
<Text style={styles.sectionTitle}>Food Highlights</Text>
|
||||||
<ThemedText>
|
<IconSymbol name="star.fill" size={16} color="#FFCC00" />
|
||||||
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
</View>
|
||||||
Press{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">
|
<View style={styles.foodHighlightsContainer}>
|
||||||
{Platform.select({
|
{foodHighlights.map((food) => (
|
||||||
ios: 'cmd + d',
|
<TouchableOpacity
|
||||||
android: 'cmd + m',
|
key={food.id}
|
||||||
web: 'F12',
|
style={styles.foodCard}
|
||||||
})}
|
onPress={() => navigateToFoodDetail(String(food.id))}
|
||||||
</ThemedText>{' '}
|
>
|
||||||
to open developer tools.
|
<Image
|
||||||
</ThemedText>
|
source={food.image}
|
||||||
</ThemedView>
|
style={styles.foodImage}
|
||||||
<ThemedView style={styles.stepContainer}>
|
contentFit="cover"
|
||||||
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
|
/>
|
||||||
<ThemedText>
|
<View style={styles.foodCardContent}>
|
||||||
{`Tap the Explore tab to learn more about what's included in this starter app.`}
|
<Text style={styles.foodCardTitle} numberOfLines={1}>
|
||||||
</ThemedText>
|
{food.name}
|
||||||
</ThemedView>
|
</Text>
|
||||||
<ThemedView style={styles.stepContainer}>
|
<Text style={styles.foodCardDescription} numberOfLines={1}>
|
||||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
{food.description}
|
||||||
<ThemedText>
|
</Text>
|
||||||
{`When you're ready, run `}
|
<View style={styles.foodCardMeta}>
|
||||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
<View style={styles.foodCardMetaItem}>
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
<IconSymbol name="clock" size={12} color="#666666" />
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
<Text style={styles.foodCardMetaText}>{food.time}</Text>
|
||||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
</View>
|
||||||
</ThemedText>
|
<View style={styles.foodCardMetaItem}>
|
||||||
</ThemedView>
|
<IconSymbol name="flame" size={12} color="#666666" />
|
||||||
</ParallaxScrollView>
|
<Text style={styles.foodCardMetaText}>
|
||||||
|
{food.calories}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Show your dishes Section */}
|
||||||
|
<View style={styles.sectionContainer}>
|
||||||
|
<View style={styles.sectionHeader}>
|
||||||
|
<Text style={styles.sectionTitle}>Show your dishes</Text>
|
||||||
|
<IconSymbol name="chevron.down" size={16} color="#333333" />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.searchContainer}>
|
||||||
|
<TextInput style={styles.searchInput} placeholder="Search..." />
|
||||||
|
<TouchableOpacity style={styles.searchButton}>
|
||||||
|
<IconSymbol name="arrow.right" size={16} color="#333333" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.uploadOptions}>
|
||||||
|
<TouchableOpacity style={styles.uploadOption}>
|
||||||
|
<IconSymbol name="camera.fill" size={24} color="#333333" />
|
||||||
|
<Text style={styles.uploadOptionTitle}>From Camera</Text>
|
||||||
|
<Text style={styles.uploadOptionSubtitle}>
|
||||||
|
Snap it from Camera
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.uploadOption, styles.orangeOption]}
|
||||||
|
>
|
||||||
|
<IconSymbol name="photo.fill" size={24} color="#333333" />
|
||||||
|
<Text style={styles.uploadOptionTitle}>From Gallery</Text>
|
||||||
|
<Text style={styles.uploadOptionSubtitle}>
|
||||||
|
Select from Gallery
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
titleContainer: {
|
container: {
|
||||||
flexDirection: 'row',
|
flex: 1,
|
||||||
alignItems: 'center',
|
backgroundColor: "#FFFFFF",
|
||||||
gap: 8,
|
|
||||||
},
|
},
|
||||||
stepContainer: {
|
scrollView: {
|
||||||
gap: 8,
|
flex: 1,
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 12,
|
||||||
|
},
|
||||||
|
greeting: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
scanButton: {
|
||||||
|
width: 36,
|
||||||
|
height: 36,
|
||||||
|
borderRadius: 18,
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
heroContainer: {
|
||||||
|
height: 180,
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginVertical: 16,
|
||||||
|
borderRadius: 16,
|
||||||
|
backgroundColor: "#FFF3D9", // Light yellow/orange gradient
|
||||||
|
overflow: "hidden",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
heroContent: {
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
position: "relative",
|
||||||
|
},
|
||||||
|
heroImage: {
|
||||||
|
width: 120,
|
||||||
|
height: 120,
|
||||||
|
},
|
||||||
|
sectionContainer: {
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
sectionHeader: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
foodHighlightsContainer: {
|
||||||
|
width: "100%",
|
||||||
|
},
|
||||||
|
foodCard: {
|
||||||
|
flexDirection: "row",
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
borderRadius: 12,
|
||||||
|
marginBottom: 12,
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOffset: { width: 0, height: 2 },
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 4,
|
||||||
|
elevation: 2,
|
||||||
|
overflow: "hidden",
|
||||||
|
},
|
||||||
|
foodImage: {
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
},
|
||||||
|
foodCardContent: {
|
||||||
|
flex: 1,
|
||||||
|
padding: 12,
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
foodCardTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
marginBottom: 4,
|
||||||
|
},
|
||||||
|
foodCardDescription: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#666666",
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
},
|
},
|
||||||
reactLogo: {
|
foodCardMeta: {
|
||||||
height: 178,
|
flexDirection: "row",
|
||||||
width: 290,
|
justifyContent: "space-between",
|
||||||
bottom: 0,
|
},
|
||||||
left: 0,
|
foodCardMetaItem: {
|
||||||
position: 'absolute',
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
foodCardMetaText: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#666666",
|
||||||
|
marginLeft: 4,
|
||||||
|
},
|
||||||
|
searchContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 16,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#DDDDDD",
|
||||||
|
borderRadius: 24,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
height: 48,
|
||||||
|
},
|
||||||
|
searchInput: {
|
||||||
|
flex: 1,
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
searchButton: {
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
borderRadius: 16,
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
uploadOptions: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
uploadOption: {
|
||||||
|
flex: 1,
|
||||||
|
height: 100,
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
borderRadius: 12,
|
||||||
|
marginRight: 8,
|
||||||
|
padding: 12,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
orangeOption: {
|
||||||
|
backgroundColor: "#FFA500", // Darker orange
|
||||||
|
marginRight: 0,
|
||||||
|
},
|
||||||
|
uploadOptionTitle: {
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
uploadOptionSubtitle: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#333333",
|
||||||
|
opacity: 0.8,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
216
app/(tabs)/profile.tsx
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { useState } from "react";
|
||||||
|
import {
|
||||||
|
ScrollView,
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
export default function ProfileScreen() {
|
||||||
|
const [activeTab, setActiveTab] = useState("Repost");
|
||||||
|
|
||||||
|
const foodItems = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Padthaipro",
|
||||||
|
image: require("@/assets/images/food/padthai.jpg"),
|
||||||
|
color: "#FFCC00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Jjajangmyeon",
|
||||||
|
image: require("@/assets/images/food/jjajangmyeon.jpg"),
|
||||||
|
color: "#FFA500",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Wingztab",
|
||||||
|
image: require("@/assets/images/food/wings.jpg"),
|
||||||
|
color: "#FFCC00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Ramen",
|
||||||
|
image: require("@/assets/images/food/ramen.jpg"),
|
||||||
|
color: "#FFA500",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Tiramisu",
|
||||||
|
image: require("@/assets/images/food/tiramisu.jpg"),
|
||||||
|
color: "#FFCC00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "Beef wellington",
|
||||||
|
image: require("@/assets/images/food/beef.jpg"),
|
||||||
|
color: "#FFA500",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "Tiramisu",
|
||||||
|
image: require("@/assets/images/food/tiramisu.jpg"),
|
||||||
|
color: "#FFCC00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: "Beef wellington",
|
||||||
|
image: require("@/assets/images/food/beef.jpg"),
|
||||||
|
color: "#FFA500",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container} edges={["top"]}>
|
||||||
|
<ScrollView style={styles.scrollView}>
|
||||||
|
{/* Profile Header */}
|
||||||
|
<View style={styles.profileHeader}>
|
||||||
|
<View style={styles.avatarContainer}>
|
||||||
|
<View style={styles.avatar}>
|
||||||
|
<Text style={styles.avatarPlaceholder}>👨🍳</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.username}>Mr. Chef</Text>
|
||||||
|
<TouchableOpacity style={styles.editButton}>
|
||||||
|
<Text style={styles.editButtonText}>Edit</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Tab Navigation */}
|
||||||
|
<View style={styles.tabContainer}>
|
||||||
|
{["Repost", "Likes", "Bookmark"].map((tab) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={tab}
|
||||||
|
style={[styles.tab, activeTab === tab && styles.activeTab]}
|
||||||
|
onPress={() => setActiveTab(tab)}
|
||||||
|
>
|
||||||
|
<Text style={styles.tabText}>{tab}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.divider} />
|
||||||
|
|
||||||
|
{/* Food Grid */}
|
||||||
|
<View style={styles.foodGrid}>
|
||||||
|
{foodItems.map((item, index) => (
|
||||||
|
<View key={`${item.id}-${index}`} style={styles.foodItem}>
|
||||||
|
<Image
|
||||||
|
source={item.image}
|
||||||
|
style={styles.foodImage}
|
||||||
|
contentFit="cover"
|
||||||
|
/>
|
||||||
|
<View style={[styles.foodLabel, { backgroundColor: item.color }]}>
|
||||||
|
<Text style={styles.foodLabelText}>{item.name}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
},
|
||||||
|
scrollView: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
profileHeader: {
|
||||||
|
alignItems: "center",
|
||||||
|
paddingVertical: 24,
|
||||||
|
},
|
||||||
|
avatarContainer: {
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
borderRadius: 50,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#DDDDDD",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
width: 96,
|
||||||
|
height: 96,
|
||||||
|
borderRadius: 48,
|
||||||
|
backgroundColor: "#F5F5F5",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
avatarPlaceholder: {
|
||||||
|
fontSize: 40,
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
editButton: {
|
||||||
|
backgroundColor: "#FF0000",
|
||||||
|
paddingVertical: 10,
|
||||||
|
paddingHorizontal: 40,
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
editButtonText: {
|
||||||
|
color: "#FFFFFF",
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
tabContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-around",
|
||||||
|
paddingVertical: 12,
|
||||||
|
},
|
||||||
|
tab: {
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
},
|
||||||
|
activeTab: {
|
||||||
|
borderBottomWidth: 2,
|
||||||
|
borderBottomColor: "#333333",
|
||||||
|
},
|
||||||
|
tabText: {
|
||||||
|
fontWeight: "500",
|
||||||
|
},
|
||||||
|
divider: {
|
||||||
|
height: 1,
|
||||||
|
backgroundColor: "#EEEEEE",
|
||||||
|
marginHorizontal: 16,
|
||||||
|
},
|
||||||
|
foodGrid: {
|
||||||
|
flexDirection: "row",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
padding: 8,
|
||||||
|
},
|
||||||
|
foodItem: {
|
||||||
|
width: "50%",
|
||||||
|
padding: 8,
|
||||||
|
position: "relative",
|
||||||
|
},
|
||||||
|
foodImage: {
|
||||||
|
width: "100%",
|
||||||
|
height: 120,
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
foodLabel: {
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 16,
|
||||||
|
left: 16,
|
||||||
|
paddingVertical: 4,
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
foodLabelText: {
|
||||||
|
color: "#333333",
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
});
|
||||||
187
app/(tabs)/recipes.tsx
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
import { IconSymbol } from "@/components/ui/IconSymbol";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import {
|
||||||
|
ScrollView,
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
export default function RecipesScreen() {
|
||||||
|
const foodItems = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Padthaipro",
|
||||||
|
image: require("@/assets/images/food/padthai.jpg"),
|
||||||
|
color: "#FFCC00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Jjajangmyeon",
|
||||||
|
image: require("@/assets/images/food/jjajangmyeon.jpg"),
|
||||||
|
color: "#FFA500",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Wingztab",
|
||||||
|
image: require("@/assets/images/food/wings.jpg"),
|
||||||
|
color: "#FFCC00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Ramen",
|
||||||
|
image: require("@/assets/images/food/ramen.jpg"),
|
||||||
|
color: "#FFA500",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Tiramisu",
|
||||||
|
image: require("@/assets/images/food/tiramisu.jpg"),
|
||||||
|
color: "#FFCC00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "Beef wellington",
|
||||||
|
image: require("@/assets/images/food/beef.jpg"),
|
||||||
|
color: "#FFA500",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container} edges={["top"]}>
|
||||||
|
<ScrollView style={styles.scrollView}>
|
||||||
|
{/* Search Bar */}
|
||||||
|
<View style={styles.searchContainer}>
|
||||||
|
<IconSymbol name="magnifyingglass" size={20} color="#FF0000" />
|
||||||
|
<TextInput
|
||||||
|
style={styles.searchInput}
|
||||||
|
placeholder="Search"
|
||||||
|
placeholderTextColor="#FF0000"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Filter Buttons */}
|
||||||
|
<View style={styles.filterContainer}>
|
||||||
|
<TouchableOpacity style={styles.yellowButton}>
|
||||||
|
<Text style={styles.buttonText}>All Recipes</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.redButton}>
|
||||||
|
<Text style={styles.redButtonText}>My Recipes</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Divider */}
|
||||||
|
<View style={styles.divider} />
|
||||||
|
|
||||||
|
{/* Food Grid */}
|
||||||
|
<View style={styles.foodGrid}>
|
||||||
|
{foodItems.map((item) => (
|
||||||
|
<View key={item.id} style={styles.foodItem}>
|
||||||
|
<Image
|
||||||
|
source={item.image}
|
||||||
|
style={styles.foodImage}
|
||||||
|
contentFit="cover"
|
||||||
|
/>
|
||||||
|
<View style={[styles.foodLabel, { backgroundColor: item.color }]}>
|
||||||
|
<Text style={styles.foodLabelText}>{item.name}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
},
|
||||||
|
scrollView: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
searchContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 16,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
height: 40,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
borderRadius: 20,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#DDDDDD",
|
||||||
|
},
|
||||||
|
searchInput: {
|
||||||
|
flex: 1,
|
||||||
|
marginLeft: 8,
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
filterContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
yellowButton: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
paddingVertical: 12,
|
||||||
|
borderRadius: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
redButton: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#FF0000",
|
||||||
|
paddingVertical: 12,
|
||||||
|
borderRadius: 8,
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
redButtonText: {
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#FFFFFF",
|
||||||
|
},
|
||||||
|
divider: {
|
||||||
|
height: 1,
|
||||||
|
backgroundColor: "#EEEEEE",
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
foodGrid: {
|
||||||
|
flexDirection: "row",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
padding: 8,
|
||||||
|
},
|
||||||
|
foodItem: {
|
||||||
|
width: "50%",
|
||||||
|
padding: 8,
|
||||||
|
position: "relative",
|
||||||
|
},
|
||||||
|
foodImage: {
|
||||||
|
width: "100%",
|
||||||
|
height: 120,
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
foodLabel: {
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 16,
|
||||||
|
left: 16,
|
||||||
|
paddingVertical: 4,
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
foodLabelText: {
|
||||||
|
color: "#333333",
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -1,15 +1,15 @@
|
|||||||
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
|
import { DefaultTheme, ThemeProvider } from "@react-navigation/native";
|
||||||
import { useFonts } from 'expo-font';
|
import { useFonts } from "expo-font";
|
||||||
import { Stack } from 'expo-router';
|
import { Stack } from "expo-router";
|
||||||
import { StatusBar } from 'expo-status-bar';
|
import { StatusBar } from "expo-status-bar";
|
||||||
import 'react-native-reanimated';
|
import "react-native-reanimated";
|
||||||
|
|
||||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
import { useColorScheme } from "@/hooks/useColorScheme";
|
||||||
|
|
||||||
export default function RootLayout() {
|
export default function RootLayout() {
|
||||||
const colorScheme = useColorScheme();
|
const colorScheme = useColorScheme();
|
||||||
const [loaded] = useFonts({
|
const [loaded] = useFonts({
|
||||||
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
|
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
@ -18,7 +18,8 @@ export default function RootLayout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
// Use DarkTheme if need dark theme
|
||||||
|
<ThemeProvider value={colorScheme === "dark" ? DefaultTheme : DefaultTheme}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
||||||
<Stack.Screen name="+not-found" />
|
<Stack.Screen name="+not-found" />
|
||||||
|
|||||||
363
app/cooking/[id].tsx
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { IconSymbol } from "@/components/ui/IconSymbol";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
ScrollView,
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
export default function CookingSessionScreen() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [currentStep, setCurrentStep] = useState(0);
|
||||||
|
|
||||||
|
// Mock data - in a real app, you would fetch this based on the ID
|
||||||
|
const recipeData = {
|
||||||
|
id: 1,
|
||||||
|
name: "Pad Kra Pao Moo Sab with Eggs",
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
title: "Gather and prepare all ingredients",
|
||||||
|
description:
|
||||||
|
"Chop garlic, Thai chilies, and protein of choice (chicken, pork, beef, or tofu)",
|
||||||
|
image: require("@/assets/images/cooking/step1.png"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Heat oil in a wok or large frying pan",
|
||||||
|
description:
|
||||||
|
"Use medium-high heat. The oil should be hot but not smoking.",
|
||||||
|
image: require("@/assets/images/cooking/step2.png"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Fry the eggs sunny side up",
|
||||||
|
description:
|
||||||
|
"Heat oil in a separate pan and fry eggs until whites are set but yolks are still runny. Set aside.",
|
||||||
|
image: require("@/assets/images/cooking/step3.png"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Stir-fry garlic and chilies",
|
||||||
|
description:
|
||||||
|
"Add chopped garlic and chilies to the hot oil and stir-fry until fragrant, about 30 seconds.",
|
||||||
|
image: require("@/assets/images/cooking/step4.png"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Add ground pork and cook until browned",
|
||||||
|
description:
|
||||||
|
"Break up the meat with a spatula and cook until no longer pink, about 3-4 minutes.",
|
||||||
|
image: require("@/assets/images/cooking/step5.png"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Add sauces and basil",
|
||||||
|
description:
|
||||||
|
"Add soy sauce, oyster sauce, sugar, and holy basil. Stir well and cook for another minute. Serve with rice and top with the fried egg.",
|
||||||
|
image: require("@/assets/images/cooking/step6.png"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalSteps = recipeData.steps.length;
|
||||||
|
|
||||||
|
const goToNextStep = () => {
|
||||||
|
if (currentStep < totalSteps - 1) {
|
||||||
|
setCurrentStep(currentStep + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const goToPreviousStep = () => {
|
||||||
|
if (currentStep > 0) {
|
||||||
|
setCurrentStep(currentStep - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getHelpWithStep = () => {
|
||||||
|
Alert.alert(
|
||||||
|
"Need Help?",
|
||||||
|
`Tips for ${recipeData.steps[currentStep].title}:\n\n` +
|
||||||
|
"• Make sure ingredients are properly prepared\n" +
|
||||||
|
"• Watch your heat level\n" +
|
||||||
|
"• Don't overcook the ingredients\n\n" +
|
||||||
|
"Would you like to see a video tutorial?",
|
||||||
|
[
|
||||||
|
{ text: "No, thanks", style: "cancel" },
|
||||||
|
{
|
||||||
|
text: "Yes, show video",
|
||||||
|
onPress: () => console.log("Show video tutorial"),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopCookingSession = () => {
|
||||||
|
Alert.alert(
|
||||||
|
"Stop Cooking?",
|
||||||
|
"Are you sure you want to stop this cooking session?",
|
||||||
|
[
|
||||||
|
{ text: "Cancel", style: "cancel" },
|
||||||
|
{ text: "Yes, stop", onPress: () => router.back() },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container} edges={["top"]}>
|
||||||
|
<ScrollView style={styles.scrollView}>
|
||||||
|
{/* Header with back button */}
|
||||||
|
<View style={styles.header}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.backButton}
|
||||||
|
onPress={() => router.back()}
|
||||||
|
>
|
||||||
|
<IconSymbol name="chevron.left" size={24} color="#333333" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Step Illustration */}
|
||||||
|
<View style={styles.illustrationContainer}>
|
||||||
|
<Image
|
||||||
|
source={recipeData.steps[currentStep].image}
|
||||||
|
style={styles.stepImage}
|
||||||
|
contentFit="contain"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Step Information */}
|
||||||
|
<View style={styles.stepInfoContainer}>
|
||||||
|
<Text style={styles.stepCounter}>
|
||||||
|
Step {currentStep + 1} of {totalSteps}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.stepTitle}>
|
||||||
|
{recipeData.steps[currentStep].title}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.stepDescription}>
|
||||||
|
{recipeData.steps[currentStep].description}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Step Indicators */}
|
||||||
|
<View style={styles.stepIndicatorsContainer}>
|
||||||
|
<Text style={styles.stepsLabel}>Steps</Text>
|
||||||
|
<View style={styles.stepDots}>
|
||||||
|
{recipeData.steps.map((_, index) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={index}
|
||||||
|
onPress={() => setCurrentStep(index)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.stepDot,
|
||||||
|
currentStep === index && styles.activeStepDot,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Navigation Buttons */}
|
||||||
|
<View style={styles.navigationContainer}>
|
||||||
|
<TouchableOpacity style={styles.helpButton} onPress={getHelpWithStep}>
|
||||||
|
<Text style={styles.helpButtonText}>Help me!</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<View style={styles.stepNavigation}>
|
||||||
|
{currentStep > 0 && (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.navButton, styles.prevButton]}
|
||||||
|
onPress={goToPreviousStep}
|
||||||
|
>
|
||||||
|
<IconSymbol name="chevron.left" size={20} color="#333333" />
|
||||||
|
<Text style={styles.prevButtonText}>Previous</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{currentStep < totalSteps - 1 ? (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.navButton, styles.nextButton]}
|
||||||
|
onPress={goToNextStep}
|
||||||
|
>
|
||||||
|
<Text style={styles.nextButtonText}>Next Step</Text>
|
||||||
|
<IconSymbol name="chevron.right" size={20} color="#333333" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
) : (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.navButton, styles.finishButton]}
|
||||||
|
onPress={() => router.back()}
|
||||||
|
>
|
||||||
|
<Text style={styles.finishButtonText}>Finish</Text>
|
||||||
|
<IconSymbol name="checkmark" size={20} color="#FFFFFF" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
{/* Stop Session Button */}
|
||||||
|
<TouchableOpacity style={styles.stopButton} onPress={stopCookingSession}>
|
||||||
|
<Text style={styles.stopButtonText}>Stop Session</Text>
|
||||||
|
<IconSymbol name="fork.knife" size={20} color="#FFCC00" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
},
|
||||||
|
scrollView: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 12,
|
||||||
|
},
|
||||||
|
backButton: {
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 20,
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
illustrationContainer: {
|
||||||
|
alignItems: "center",
|
||||||
|
marginVertical: 20,
|
||||||
|
},
|
||||||
|
stepImage: {
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
borderRadius: 100,
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
},
|
||||||
|
stepInfoContainer: {
|
||||||
|
paddingHorizontal: 24,
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 30,
|
||||||
|
},
|
||||||
|
stepCounter: {
|
||||||
|
fontSize: 18,
|
||||||
|
color: "#8BC34A",
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
stepTitle: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
textAlign: "center",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
stepDescription: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#666666",
|
||||||
|
textAlign: "center",
|
||||||
|
lineHeight: 24,
|
||||||
|
},
|
||||||
|
stepIndicatorsContainer: {
|
||||||
|
paddingHorizontal: 24,
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
stepsLabel: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
stepDots: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
stepDot: {
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 20,
|
||||||
|
backgroundColor: "#EEEEEE",
|
||||||
|
marginHorizontal: 8,
|
||||||
|
},
|
||||||
|
activeStepDot: {
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
},
|
||||||
|
navigationContainer: {
|
||||||
|
paddingHorizontal: 24,
|
||||||
|
marginBottom: 80,
|
||||||
|
},
|
||||||
|
helpButton: {
|
||||||
|
backgroundColor: "#FF6B6B",
|
||||||
|
borderRadius: 8,
|
||||||
|
paddingVertical: 16,
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
helpButtonText: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#FFFFFF",
|
||||||
|
},
|
||||||
|
stepNavigation: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
navButton: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
paddingVertical: 16,
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
prevButton: {
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#DDDDDD",
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
prevButtonText: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
marginLeft: 8,
|
||||||
|
},
|
||||||
|
nextButton: {
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
},
|
||||||
|
nextButtonText: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
finishButton: {
|
||||||
|
backgroundColor: "#4CAF50",
|
||||||
|
},
|
||||||
|
finishButtonText: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#FFFFFF",
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
stopButton: {
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
backgroundColor: "#C62828",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingVertical: 16,
|
||||||
|
},
|
||||||
|
stopButtonText: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#FFCC00",
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
});
|
||||||
454
app/food/[id].tsx
Normal file
@ -0,0 +1,454 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { IconSymbol } from "@/components/ui/IconSymbol";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import {
|
||||||
|
ScrollView,
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
export default function FoodDetailScreen() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [activeTab, setActiveTab] = useState("Ingredients");
|
||||||
|
|
||||||
|
// Mock data - in a real app, you would fetch this based on the ID
|
||||||
|
const foodData = {
|
||||||
|
id: 1,
|
||||||
|
name: "Pad Kra Pao Moo Sab with Eggs",
|
||||||
|
image: require("@/assets/images/food/padkrapao.jpg"),
|
||||||
|
description:
|
||||||
|
"Pad kra pao, also written as pad gaprao, is a popular Thai stir-fry of ground meat and holy basil.",
|
||||||
|
time: "30 Mins",
|
||||||
|
skills: "Easy",
|
||||||
|
ingredients: [
|
||||||
|
{ name: "Ground pork", emoji: "🥩" },
|
||||||
|
{ name: "Holy basil", emoji: "🌿" },
|
||||||
|
{ name: "Garlic", emoji: "🧄" },
|
||||||
|
{ name: "Thai chili", emoji: "🌶️" },
|
||||||
|
{ name: "Soy sauce", emoji: "🍶" },
|
||||||
|
{ name: "Oyster sauce", emoji: "🦪" },
|
||||||
|
{ name: "Sugar", emoji: "🧂" },
|
||||||
|
{ name: "Eggs", emoji: "🥚" },
|
||||||
|
],
|
||||||
|
calories: "520 kcal",
|
||||||
|
nutrition: {
|
||||||
|
fat: 15,
|
||||||
|
fiber: 3,
|
||||||
|
protein: 25,
|
||||||
|
carbs: 40,
|
||||||
|
},
|
||||||
|
steps: [
|
||||||
|
"Gather and prepare all ingredients",
|
||||||
|
"Heat oil in a wok or large frying pan",
|
||||||
|
"Fry the eggs sunny side up and set aside",
|
||||||
|
"Stir-fry garlic and chilies until fragrant",
|
||||||
|
"Add ground pork and cook until browned",
|
||||||
|
"Add sauces and basil, serve with rice and egg on top",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const startCookingSession = () => {
|
||||||
|
router.push(`/cooking/[id]`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container} edges={["top"]}>
|
||||||
|
<ScrollView style={styles.scrollView}>
|
||||||
|
{/* Header with back and share buttons */}
|
||||||
|
<View style={styles.header}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.backButton}
|
||||||
|
onPress={() => router.back()}
|
||||||
|
>
|
||||||
|
<IconSymbol name="chevron.left" size={24} color="#333333" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.shareButton}>
|
||||||
|
<IconSymbol name="square.and.arrow.up" size={24} color="#FFCC00" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Food Image */}
|
||||||
|
<View style={styles.imageContainer}>
|
||||||
|
<Image
|
||||||
|
source={foodData.image}
|
||||||
|
style={styles.foodImage}
|
||||||
|
contentFit="cover"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Food Title and Description */}
|
||||||
|
<View style={styles.contentContainer}>
|
||||||
|
<Text style={styles.foodTitle}>{foodData.name}</Text>
|
||||||
|
<Text style={styles.foodDescription}>{foodData.description}</Text>
|
||||||
|
|
||||||
|
{/* Info Tabs */}
|
||||||
|
<View style={styles.tabsContainer}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.tabItem}
|
||||||
|
onPress={() => setActiveTab("Skills")}
|
||||||
|
>
|
||||||
|
<Text style={styles.tabLabel}>Skills</Text>
|
||||||
|
<Text style={styles.tabValue}>{foodData.skills}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.tabItem}
|
||||||
|
onPress={() => setActiveTab("Time")}
|
||||||
|
>
|
||||||
|
<Text style={styles.tabLabel}>Time</Text>
|
||||||
|
<Text style={styles.tabValue}>{foodData.time}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[
|
||||||
|
styles.tabItem,
|
||||||
|
activeTab === "Ingredients" && styles.activeTabItem,
|
||||||
|
]}
|
||||||
|
onPress={() => setActiveTab("Ingredients")}
|
||||||
|
>
|
||||||
|
<Text style={styles.tabLabel}>Ingredients</Text>
|
||||||
|
<Text style={styles.tabValue}>{foodData.ingredients.length}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.tabItem}
|
||||||
|
onPress={() => setActiveTab("Calories")}
|
||||||
|
>
|
||||||
|
<Text style={styles.tabLabel}>Calories</Text>
|
||||||
|
<Text style={styles.tabValue}>{foodData.calories}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Ingredients Section */}
|
||||||
|
<View style={styles.sectionContainer}>
|
||||||
|
<Text style={styles.sectionTitle}>Ingredients</Text>
|
||||||
|
<View style={styles.ingredientsGrid}>
|
||||||
|
{foodData.ingredients.map((ingredient, index) => (
|
||||||
|
<View key={index} style={styles.ingredientItem}>
|
||||||
|
<View style={styles.ingredientIconContainer}>
|
||||||
|
<Text style={styles.ingredientEmoji}>
|
||||||
|
{ingredient.emoji}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.ingredientName}>{ingredient.name}</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Nutrition Section - Improved UI */}
|
||||||
|
<View style={styles.nutritionSection}>
|
||||||
|
<Text style={styles.sectionTitle}>Nutrition Facts</Text>
|
||||||
|
<View style={styles.nutritionContainer}>
|
||||||
|
<View style={styles.nutritionItem}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.nutritionCircle,
|
||||||
|
{ backgroundColor: "#FFD700" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Text style={styles.nutritionValue}>
|
||||||
|
{foodData.nutrition.fat}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.nutritionUnit}>g</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.nutritionLabel}>Fat</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.nutritionItem}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.nutritionCircle,
|
||||||
|
{ backgroundColor: "#90EE90" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Text style={styles.nutritionValue}>
|
||||||
|
{foodData.nutrition.fiber}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.nutritionUnit}>g</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.nutritionLabel}>Fiber</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.nutritionItem}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.nutritionCircle,
|
||||||
|
{ backgroundColor: "#ADD8E6" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Text style={styles.nutritionValue}>
|
||||||
|
{foodData.nutrition.protein}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.nutritionUnit}>g</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.nutritionLabel}>Protein</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.nutritionItem}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.nutritionCircle,
|
||||||
|
{ backgroundColor: "#FFA07A" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Text style={styles.nutritionValue}>
|
||||||
|
{foodData.nutrition.carbs}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.nutritionUnit}>g</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.nutritionLabel}>Carbs</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Steps Preview */}
|
||||||
|
<View style={styles.sectionContainer}>
|
||||||
|
<Text style={styles.sectionTitle}>Cooking Steps</Text>
|
||||||
|
<View style={styles.stepsPreviewContainer}>
|
||||||
|
{foodData.steps.slice(0, 2).map((step, index) => (
|
||||||
|
<View key={index} style={styles.stepPreviewItem}>
|
||||||
|
<View style={styles.stepNumberCircle}>
|
||||||
|
<Text style={styles.stepNumber}>{index + 1}</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.stepPreviewText}>{step}</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
<Text style={styles.moreStepsText}>
|
||||||
|
...and {foodData.steps.length - 2} more steps
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
{/* Cook Button */}
|
||||||
|
<TouchableOpacity style={styles.cookButton} onPress={startCookingSession}>
|
||||||
|
<Text style={styles.cookButtonText}>Let's Cook!</Text>
|
||||||
|
<IconSymbol name="fork.knife" size={20} color="#FFCC00" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
},
|
||||||
|
scrollView: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 12,
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
zIndex: 10,
|
||||||
|
},
|
||||||
|
backButton: {
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 20,
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
shareButton: {
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 20,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
imageContainer: {
|
||||||
|
alignItems: "center",
|
||||||
|
marginTop: 60,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
foodImage: {
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
borderRadius: 100,
|
||||||
|
borderWidth: 5,
|
||||||
|
borderColor: "#FFFFFF",
|
||||||
|
},
|
||||||
|
contentContainer: {
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
},
|
||||||
|
foodTitle: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
foodDescription: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#666666",
|
||||||
|
marginBottom: 20,
|
||||||
|
lineHeight: 22,
|
||||||
|
},
|
||||||
|
tabsContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
tabItem: {
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
activeTabItem: {
|
||||||
|
borderBottomWidth: 2,
|
||||||
|
borderBottomColor: "#333333",
|
||||||
|
},
|
||||||
|
tabLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#666666",
|
||||||
|
},
|
||||||
|
tabValue: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
marginTop: 4,
|
||||||
|
},
|
||||||
|
sectionContainer: {
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
ingredientsGrid: {
|
||||||
|
flexDirection: "row",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
},
|
||||||
|
ingredientItem: {
|
||||||
|
width: "25%",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
ingredientIconContainer: {
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
borderRadius: 30,
|
||||||
|
backgroundColor: "#F8F8F8",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 8,
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOffset: { width: 0, height: 2 },
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 4,
|
||||||
|
elevation: 2,
|
||||||
|
},
|
||||||
|
ingredientEmoji: {
|
||||||
|
fontSize: 30,
|
||||||
|
},
|
||||||
|
ingredientName: {
|
||||||
|
fontSize: 12,
|
||||||
|
textAlign: "center",
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
nutritionSection: {
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
nutritionContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
borderRadius: 12,
|
||||||
|
padding: 16,
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOffset: { width: 0, height: 2 },
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 4,
|
||||||
|
elevation: 2,
|
||||||
|
},
|
||||||
|
nutritionItem: {
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
nutritionCircle: {
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
borderRadius: 30,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
nutritionValue: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
nutritionUnit: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#333333",
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 10,
|
||||||
|
right: 10,
|
||||||
|
},
|
||||||
|
nutritionLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: "500",
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
stepsPreviewContainer: {
|
||||||
|
backgroundColor: "#F8F8F8",
|
||||||
|
borderRadius: 12,
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
stepPreviewItem: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
stepNumberCircle: {
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
borderRadius: 15,
|
||||||
|
backgroundColor: "#FFCC00",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginRight: 12,
|
||||||
|
},
|
||||||
|
stepNumber: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333333",
|
||||||
|
},
|
||||||
|
stepPreviewText: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#333333",
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
moreStepsText: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#666666",
|
||||||
|
fontStyle: "italic",
|
||||||
|
textAlign: "center",
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
cookButton: {
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
backgroundColor: "#FF0000",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingVertical: 16,
|
||||||
|
},
|
||||||
|
cookButtonText: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#FFCC00",
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
});
|
||||||
BIN
assets/images/cooking/step1.png
Normal file
|
After Width: | Height: | Size: 650 KiB |
BIN
assets/images/cooking/step2.png
Normal file
|
After Width: | Height: | Size: 650 KiB |
BIN
assets/images/cooking/step3.png
Normal file
|
After Width: | Height: | Size: 650 KiB |
BIN
assets/images/cooking/step4.png
Normal file
|
After Width: | Height: | Size: 650 KiB |
BIN
assets/images/cooking/step5.png
Normal file
|
After Width: | Height: | Size: 650 KiB |
BIN
assets/images/cooking/step6.png
Normal file
|
After Width: | Height: | Size: 650 KiB |
BIN
assets/images/food/beef.jpg
Normal file
|
After Width: | Height: | Size: 650 KiB |
BIN
assets/images/food/jjajangmyeon.jpg
Normal file
|
After Width: | Height: | Size: 427 KiB |
BIN
assets/images/food/padkrapao.jpg
Normal file
|
After Width: | Height: | Size: 237 KiB |
BIN
assets/images/food/padthai.jpg
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
assets/images/food/ramen.jpg
Normal file
BIN
assets/images/food/tiramisu.jpg
Normal file
|
After Width: | Height: | Size: 254 KiB |
BIN
assets/images/food/wings.jpg
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
assets/images/notebook-orange.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
assets/images/placeholder-food.jpg
Normal file
|
After Width: | Height: | Size: 113 KiB |