initial commit
This commit is contained in:
parent
9e8c79c046
commit
cfb7924b57
26 changed files with 19505 additions and 0 deletions
22
donutshop/.gitignore
vendored
Normal file
22
donutshop/.gitignore
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
node_modules/
|
||||||
|
.expo/
|
||||||
|
dist/
|
||||||
|
npm-debug.*
|
||||||
|
*.jks
|
||||||
|
*.p8
|
||||||
|
*.p12
|
||||||
|
*.key
|
||||||
|
*.mobileprovision
|
||||||
|
*.orig.*
|
||||||
|
web-build/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
|
||||||
|
# The following patterns were generated by expo-cli
|
||||||
|
|
||||||
|
expo-env.d.ts
|
||||||
|
# @end expo-cli
|
||||||
|
|
||||||
|
assets/images/*
|
50
donutshop/README.md
Normal file
50
donutshop/README.md
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# Welcome to your Expo app 👋
|
||||||
|
|
||||||
|
This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
|
||||||
|
|
||||||
|
## Get started
|
||||||
|
|
||||||
|
1. Install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Start the app
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx expo start
|
||||||
|
```
|
||||||
|
|
||||||
|
In the output, you'll find options to open the app in a
|
||||||
|
|
||||||
|
- [development build](https://docs.expo.dev/develop/development-builds/introduction/)
|
||||||
|
- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
|
||||||
|
- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
|
||||||
|
- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
|
||||||
|
|
||||||
|
You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
|
||||||
|
|
||||||
|
## Get a fresh project
|
||||||
|
|
||||||
|
When you're ready, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run reset-project
|
||||||
|
```
|
||||||
|
|
||||||
|
This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
|
||||||
|
|
||||||
|
## Learn more
|
||||||
|
|
||||||
|
To learn more about developing your project with Expo, look at the following resources:
|
||||||
|
|
||||||
|
- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
|
||||||
|
- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
|
||||||
|
|
||||||
|
## Join the community
|
||||||
|
|
||||||
|
Join our community of developers creating universal apps.
|
||||||
|
|
||||||
|
- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
|
||||||
|
- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
|
36
donutshop/app.json
Normal file
36
donutshop/app.json
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"expo": {
|
||||||
|
"name": "donutshop",
|
||||||
|
"slug": "donutshop",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"orientation": "portrait",
|
||||||
|
"icon": "./assets/images/icon.png",
|
||||||
|
"scheme": "myapp",
|
||||||
|
"userInterfaceStyle": "automatic",
|
||||||
|
"splash": {
|
||||||
|
"image": "./assets/images/splash.png",
|
||||||
|
"resizeMode": "contain",
|
||||||
|
"backgroundColor": "#ffffff"
|
||||||
|
},
|
||||||
|
"ios": {
|
||||||
|
"supportsTablet": true
|
||||||
|
},
|
||||||
|
"android": {
|
||||||
|
"adaptiveIcon": {
|
||||||
|
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||||
|
"backgroundColor": "#ffffff"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"bundler": "metro",
|
||||||
|
"output": "static",
|
||||||
|
"favicon": "./assets/images/favicon.png"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"expo-router"
|
||||||
|
],
|
||||||
|
"experiments": {
|
||||||
|
"typedRoutes": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
donutshop/app/components/DrinkCard.tsx
Normal file
56
donutshop/app/components/DrinkCard.tsx
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import { Dimensions, ImageBackground, ImageProps, Pressable, StyleSheet, Text, View } from 'react-native'
|
||||||
|
import { AntDesign, MaterialIcons} from '@expo/vector-icons';
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
|
||||||
|
const card_width = Dimensions.get('window').width * 0.3;
|
||||||
|
|
||||||
|
interface DrinkCardProps {
|
||||||
|
id: string;
|
||||||
|
index: number;
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
image_item: ImageProps;
|
||||||
|
average_rating: number;
|
||||||
|
prices: any;
|
||||||
|
buttonPressHandler: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const DrinkCard:React.FC<DrinkCardProps> = ({
|
||||||
|
id,
|
||||||
|
index,
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
image_item,
|
||||||
|
average_rating,
|
||||||
|
prices,
|
||||||
|
buttonPressHandler,
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{justifyContent: 'space-between', borderWidth: 1, borderRightColor: '#DA7297', borderLeftColor: '#DA7297', borderTopColor: '#DA7297', borderBottomColor: '#DA7297', padding: 10, borderRadius: 10, height: 250, width: 150}}>
|
||||||
|
<View>
|
||||||
|
<ImageBackground source={image_item} style={{width:120, height: 120, overflow: 'hidden'}} resizeMode= "contain">
|
||||||
|
<View style={{flexDirection: 'row', gap: 3}}>
|
||||||
|
<AntDesign name="star" size={16} color="#DA7297"/>
|
||||||
|
<Text style={{color: '#EF5A6F', textAlign: 'right'}}>{average_rating}</Text>
|
||||||
|
</View>
|
||||||
|
</ImageBackground>
|
||||||
|
<View style={{margin: 10}}>
|
||||||
|
<Text style={{textAlign: 'center', color: '#DA7297', fontWeight: 500}}>{name}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={{flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'}}>
|
||||||
|
<Text style={{fontWeight: 600, color: '#EF5A6F'}}>$<Text>{prices.price}</Text></Text>
|
||||||
|
<Pressable onPress={() => {}}>
|
||||||
|
<MaterialIcons name="add-circle" size={24} color="#EF5A6F" />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DrinkCard
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({})
|
48
donutshop/app/components/HomeHeader.tsx
Normal file
48
donutshop/app/components/HomeHeader.tsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { Pressable, StyleSheet, Text, View } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
import { FontAwesome, Feather } from '@expo/vector-icons';
|
||||||
|
import { useNavigation } from '@react-navigation/native';
|
||||||
|
|
||||||
|
|
||||||
|
const HomeHeader = () => {
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
const hours = date.getHours();
|
||||||
|
let message;
|
||||||
|
|
||||||
|
if (hours < 12) {
|
||||||
|
message = <Text>Good Morning ☀</Text>;
|
||||||
|
} else if (hours < 18) {
|
||||||
|
message = <Text>Good Afternoon ☀</Text>;
|
||||||
|
} else {
|
||||||
|
message = <Text>Good Evening </Text>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<View style={{marginTop: 20, paddingHorizontal: 20, paddingVertical: 10}}>
|
||||||
|
<View>
|
||||||
|
<Text style={{fontSize: 30, fontWeight: 600}}>{message}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={{marginTop: 30, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'}}>
|
||||||
|
<Pressable onPress={() => navigation.navigate('inbox')} style={{flexDirection: 'row', gap: 5, alignItems: 'flex-end'}}>
|
||||||
|
<Feather name="mail" size={24} color="gray" /><Text style={{fontSize: 16}}>Inbox</Text>
|
||||||
|
</Pressable>
|
||||||
|
<Pressable onPress={() => navigation.navigate('profile')}>
|
||||||
|
<FontAwesome name="user-circle-o" size={24} color="gray" />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={{height: 1, backgroundColor: "#B4B4B8", shadowColor: '#B4B4B8', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.5, shadowRadius: 1, }}></View>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HomeHeader
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
Emoji:{
|
||||||
|
padding: 20
|
||||||
|
}
|
||||||
|
})
|
57
donutshop/app/components/MenuCard.tsx
Normal file
57
donutshop/app/components/MenuCard.tsx
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { Dimensions, ImageBackground, ImageProps, Pressable, StyleSheet, Text, View } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
import { AntDesign, MaterialIcons} from '@expo/vector-icons';
|
||||||
|
|
||||||
|
|
||||||
|
const card_width = Dimensions.get('window').width * 0.3;
|
||||||
|
|
||||||
|
interface donutCardProps {
|
||||||
|
id: string;
|
||||||
|
index: number;
|
||||||
|
type: string;
|
||||||
|
donutname: string;
|
||||||
|
name: string;
|
||||||
|
image_item: ImageProps;
|
||||||
|
average_rating: number;
|
||||||
|
prices: any;
|
||||||
|
buttonPressHandler: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MenuCard:React.FC<donutCardProps> = ({
|
||||||
|
id,
|
||||||
|
index,
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
donutname,
|
||||||
|
image_item,
|
||||||
|
average_rating,
|
||||||
|
prices,
|
||||||
|
buttonPressHandler,
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{justifyContent: 'space-between', borderWidth: 1, borderRightColor: '#DA7297', borderLeftColor: '#DA7297', borderTopColor: '#DA7297', borderBottomColor: '#DA7297', padding: 10, borderRadius: 10, height: 250, width: 150}}>
|
||||||
|
<View>
|
||||||
|
<ImageBackground source={image_item} style={{width:card_width, height: card_width, overflow: 'hidden'}} resizeMode= "contain">
|
||||||
|
<View style={{flexDirection: 'row', gap: 3}}>
|
||||||
|
<AntDesign name="star" size={16} color="#DA7297"/>
|
||||||
|
<Text style={{color: '#EF5A6F', textAlign: 'right'}}>{average_rating}</Text>
|
||||||
|
</View>
|
||||||
|
</ImageBackground>
|
||||||
|
<View style={{margin: 10}}>
|
||||||
|
<Text style={{textAlign: 'center', color: '#DA7297', fontWeight: 500}}>{donutname}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={{flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'}}>
|
||||||
|
<Text style={{fontWeight: 600, color: '#EF5A6F'}}>$<Text>{prices.price}</Text></Text>
|
||||||
|
<Pressable onPress={() => {}}>
|
||||||
|
<MaterialIcons name="add-circle" size={24} color="#EF5A6F" />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MenuCard
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({})
|
212
donutshop/app/data/DonutData.ts
Normal file
212
donutshop/app/data/DonutData.ts
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
const DonutData =[
|
||||||
|
{
|
||||||
|
id: 'D1',
|
||||||
|
name: 'Classic',
|
||||||
|
donutname: 'Chocolate Beurre noisette Walnut Cream',
|
||||||
|
description: `A decadent treat that combines rich, velvety chocolate with the nutty flavor of beurre noisette and the crunch of walnuts. The beurre noisette adds a deep, nutty flavor and aroma to the donut, while the cream filling provides a smooth and indulgent texture.`,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut1.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '4.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Classic Donut',
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D2',
|
||||||
|
name: 'Classic',
|
||||||
|
donutname: 'Black sesame matcha',
|
||||||
|
description: `A fusion of Asian-inspired flavors. On top or mixed into the dough, you'll find black sesame seeds, which add a nutty flavor and a contrasting texture.`,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut2.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '4.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Classic Donut',
|
||||||
|
index: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D3',
|
||||||
|
name: 'Classic',
|
||||||
|
donutname: 'Passionfruit Creamcheese',
|
||||||
|
description: `A delightful combination that brings together the tangy sweetness of passionfruit with the rich creaminess of cream cheese`,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut3.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '4.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Classic Donut',
|
||||||
|
index: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D4',
|
||||||
|
name: 'Classic',
|
||||||
|
donutname: 'Strawberry glazed with white chocolate',
|
||||||
|
description: `A decadent dessert that combines the fruity sweetness of strawberries with the rich creaminess of white chocolate.`,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut4.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '4.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Classic Donut',
|
||||||
|
index: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D5',
|
||||||
|
name: 'Classic',
|
||||||
|
donutname: 'Boston Caramel Cream',
|
||||||
|
description: `A rich and indulgent combination of flavors vanilla and caramel.`,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut5.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '4.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Classic Donut',
|
||||||
|
index: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D6',
|
||||||
|
name: 'Special',
|
||||||
|
donutname: 'Oreo Cookie Crumble',
|
||||||
|
description: `A delightful fusion of a classic American cookie and a beloved pastry.`,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut6.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '5.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Special Donut',
|
||||||
|
index: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D7',
|
||||||
|
name: 'Special',
|
||||||
|
donutname: 'Reeses peanut butter Cup',
|
||||||
|
description: `A decadent treat that combines the beloved flavors of chocolate and peanut butter into a delicious pastry.`,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut7.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '5.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Special Donut',
|
||||||
|
index: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D8',
|
||||||
|
name: 'Special',
|
||||||
|
donutname: 'M&M Chocolate Boston Cream',
|
||||||
|
description: `A delightful variation of the classic Boston Cream donut, incorporating colorful M&M candies for added texture and flavor.`,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut8.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '5.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Special Donut',
|
||||||
|
index: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D9',
|
||||||
|
name: 'Special',
|
||||||
|
donutname: 'White Chocolate & Nutella Bueno',
|
||||||
|
description: `A flavorful and indulgent treat that combines creamy white chocolate with the beloved hazelnut flavor of Nutella. `,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut9.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '6.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Special Donut',
|
||||||
|
index: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D10',
|
||||||
|
name: 'Special',
|
||||||
|
donutname: 'White chocolate matcha pistachio',
|
||||||
|
description: `Indulge in the creamy goodness of White Chocolate Matcha Donut with a delightful crunch of crushed pistachios.`,
|
||||||
|
calories: '295',
|
||||||
|
image_item: require('../../assets/images/menu/donut10.png'),
|
||||||
|
prices: [
|
||||||
|
{price: '5.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Special Donut',
|
||||||
|
index: 9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D11',
|
||||||
|
name: 'Party',
|
||||||
|
donutname: 'Classic Half Dozen',
|
||||||
|
description: `Staff-picked(just the classics). Please note that no modifications can be accommodated.`,
|
||||||
|
calories: '-',
|
||||||
|
image_item: require('../../assets/images/menu/box_half_dozen.jpg'),
|
||||||
|
prices: [
|
||||||
|
{price: '26.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Box Donut',
|
||||||
|
index: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D12',
|
||||||
|
name: 'Party',
|
||||||
|
donutname: 'Classic Dozen',
|
||||||
|
description: `Staff-picked(just the classics). Please note that no modifications can be accommodated.`,
|
||||||
|
calories: '-',
|
||||||
|
image_item: require('../../assets/images/menu/box_dozen.jpg'),
|
||||||
|
prices: [
|
||||||
|
{price: '52.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Box Donut',
|
||||||
|
index: 11,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D13',
|
||||||
|
name: 'Party',
|
||||||
|
donutname: 'Mothers Day Box',
|
||||||
|
description: `Five special donuts only on mother's day.`,
|
||||||
|
calories: '-',
|
||||||
|
image_item: require('../../assets/images/menu/box_special.jpg'),
|
||||||
|
prices: [
|
||||||
|
{price: '22.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Box Donut',
|
||||||
|
index: 12,
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
export default DonutData;
|
63
donutshop/app/data/DrinkData.ts
Normal file
63
donutshop/app/data/DrinkData.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
const DrinkData = [
|
||||||
|
{
|
||||||
|
id: 'D1',
|
||||||
|
name: 'Chocolate Milkshake',
|
||||||
|
description: `A creamy, thick chocolate shake topped with a nice dollop of whipped cream.`,
|
||||||
|
image_item: require('../../assets/images/menu/drink1.png'),
|
||||||
|
prices: [
|
||||||
|
{size: 'S', price: '6.99', currency: '$'},
|
||||||
|
{size: 'M', price: '8.49', currency: '$'},
|
||||||
|
{size: 'L', price: '8.99', currency: '$'},
|
||||||
|
{toping_name: 'Mini cookies', price: '1.5', currency: '$'},
|
||||||
|
{toping_name: 'Sprinkles', price: '0.5', currency: '$'},
|
||||||
|
{toping_name: 'Marshmallows', price: '1.25', currency: '$'},
|
||||||
|
{toping_name: 'Pretzels', price: '1.25', currency: '$'},
|
||||||
|
{toping_name: 'Popcorn', price: '1.25', currency: '$'},
|
||||||
|
{toping_name: 'Chocolate Chips', price: '1.25', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Drink',
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D2',
|
||||||
|
name: 'Strawberry Milkshake',
|
||||||
|
description: `A creamy, thick strawberry shake topped with nice dollop of whipped cream and fresh strawberries.`,
|
||||||
|
image_item: require('../../assets/images/menu/drink3.png'),
|
||||||
|
prices: [
|
||||||
|
{size: 'S', price: '6.99', currency: '$'},
|
||||||
|
{size: 'M', price: '8.49', currency: '$'},
|
||||||
|
{size: 'L', price: '8.99', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Drink',
|
||||||
|
index: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'D3',
|
||||||
|
name: 'Coffee Affogato Milkshake',
|
||||||
|
description: `A creamy, thick coffee affogato shake topped with dollop of whipped cream and caramel syrup.`,
|
||||||
|
image_item: require('../../assets/images/menu/drink2.png'),
|
||||||
|
prices: [
|
||||||
|
{size: 'S', price: '7.99', currency: '$'},
|
||||||
|
{size: 'M', price: '9.49', currency: '$'},
|
||||||
|
{size: 'L', price: '9.99', currency: '$'},
|
||||||
|
{toping_name: 'Mini cookies', price: '1.5', currency: '$'},
|
||||||
|
{toping_name: 'Sprinkles', price: '0.5', currency: '$'},
|
||||||
|
{toping_name: 'Marshmallows', price: '1.25', currency: '$'},
|
||||||
|
{toping_name: 'Pretzels', price: '1.25', currency: '$'},
|
||||||
|
{toping_name: 'Popcorn', price: '1.25', currency: '$'},
|
||||||
|
{toping_name: 'Chocolate Chips', price: '1.25', currency: '$'},
|
||||||
|
],
|
||||||
|
average_rating: 4.7,
|
||||||
|
ratings_count: '6,879',
|
||||||
|
favourite: false,
|
||||||
|
type: 'Drink',
|
||||||
|
index: 2,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
export default DrinkData;
|
30
donutshop/app/index.js
Normal file
30
donutshop/app/index.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { KeyboardAvoidingView, SafeAreaView, View} from "react-native";
|
||||||
|
import { NavigationContainer } from "@react-navigation/native";
|
||||||
|
import { createStackNavigator } from '@react-navigation/stack';
|
||||||
|
import HomeNavigator from "./navigation/HomeNavigator";
|
||||||
|
import Detail from "./screen/Detail";
|
||||||
|
import Payment from "./screen/Payment";
|
||||||
|
import Inbox from "./screen/Inbox"
|
||||||
|
import Profile from "./screen/Profile"
|
||||||
|
|
||||||
|
|
||||||
|
const Stack = createStackNavigator();
|
||||||
|
|
||||||
|
export default function Index() {
|
||||||
|
return (
|
||||||
|
<NavigationContainer independent={true}>
|
||||||
|
<KeyboardAvoidingView>
|
||||||
|
<View style={{height: '100%', width: '100%'}}>
|
||||||
|
<Stack.Navigator screenOptions={{headerShown: false}}>
|
||||||
|
<Stack.Screen name='Tab' component={HomeNavigator}/>
|
||||||
|
<Stack.Screen name='detail' component={Detail}/>
|
||||||
|
<Stack.Screen name='payment' component={Payment}/>
|
||||||
|
<Stack.Screen name='inbox' component={Inbox}/>
|
||||||
|
<Stack.Screen name='profile' component={Profile}/>
|
||||||
|
</Stack.Navigator>
|
||||||
|
</View>
|
||||||
|
</KeyboardAvoidingView>
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
}
|
93
donutshop/app/navigation/HomeNavigator.tsx
Normal file
93
donutshop/app/navigation/HomeNavigator.tsx
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {StyleSheet} from "react-native";
|
||||||
|
import {createBottomTabNavigator} from "@react-navigation/bottom-tabs";
|
||||||
|
import {Entypo, MaterialCommunityIcons, Fontisto, MaterialIcons, Ionicons} from '@expo/vector-icons';
|
||||||
|
import Home from '../screen/Home';
|
||||||
|
import Menu from '../screen/Menu';
|
||||||
|
import Cart from '../screen/Cart';
|
||||||
|
import Favorite from '../screen/Favorite';
|
||||||
|
import OrderReceipt from '../screen/OrderReceipt';
|
||||||
|
|
||||||
|
|
||||||
|
const Tab = createBottomTabNavigator();
|
||||||
|
|
||||||
|
const HomeNavigator = () => {
|
||||||
|
return (
|
||||||
|
<Tab.Navigator screenOptions={{headerShown: false, tabBarHideOnKeyboard: true, tabBarStyle: styles.tabBarStyle}}>
|
||||||
|
|
||||||
|
<Tab.Screen name='home' component={Home}
|
||||||
|
options={{
|
||||||
|
tabBarLabel: "Home",
|
||||||
|
tabBarActiveTintColor: '#DA7297',
|
||||||
|
tabBarInactiveTintColor: 'gray',
|
||||||
|
tabBarIcon:({focused}) =>
|
||||||
|
focused? (
|
||||||
|
<Entypo name="home" size={26} color="#DA7297" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
) : (
|
||||||
|
<Entypo name="home" size={26} color="gray" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tab.Screen name='menu' component={Menu}
|
||||||
|
options={{
|
||||||
|
tabBarLabel: "Menu",
|
||||||
|
tabBarActiveTintColor: '#DA7297',
|
||||||
|
tabBarInactiveTintColor: 'gray',
|
||||||
|
tabBarIcon:({focused}) =>
|
||||||
|
focused? (
|
||||||
|
<Ionicons name="fast-food-sharp" size={26} color="#DA7297" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
) : (
|
||||||
|
<Ionicons name="fast-food-sharp" size={26} color="gray" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tab.Screen name='favorit' component={Favorite}
|
||||||
|
options={{
|
||||||
|
tabBarLabel: "Favorite",
|
||||||
|
tabBarActiveTintColor: '#DA7297',
|
||||||
|
tabBarInactiveTintColor: 'gray',
|
||||||
|
tabBarIcon:({focused}) =>
|
||||||
|
focused? (
|
||||||
|
<MaterialIcons name="favorite" size={26} color="#DA7297" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
) : (
|
||||||
|
<MaterialIcons name="favorite" size={26} color="gray" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tab.Screen name='cart' component={Cart}
|
||||||
|
options={{
|
||||||
|
tabBarLabel: "Your order",
|
||||||
|
tabBarActiveTintColor: '#DA7297',
|
||||||
|
tabBarInactiveTintColor: 'gray',
|
||||||
|
tabBarIcon:({focused}) =>
|
||||||
|
focused? (
|
||||||
|
<Fontisto name="shopping-bag" size={22} color="#DA7297" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
) : (
|
||||||
|
<Fontisto name="shopping-bag" size={22} color="gray" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tab.Screen name='receipt' component={OrderReceipt}
|
||||||
|
options={{
|
||||||
|
tabBarLabel: "Receipt",
|
||||||
|
tabBarActiveTintColor: '#DA7297',
|
||||||
|
tabBarInactiveTintColor: 'gray',
|
||||||
|
tabBarIcon:({focused}) =>
|
||||||
|
focused? (
|
||||||
|
<Ionicons name="receipt" size={24} color="#DA7297" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
) : (
|
||||||
|
<Ionicons name="receipt" size={24} color="gray" style={{marginTop: 5, marginBottom: 5}}/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tab.Navigator>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HomeNavigator
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
tabBarStyle: {
|
||||||
|
height: 80,
|
||||||
|
}
|
||||||
|
})
|
12
donutshop/app/screen/Cart.tsx
Normal file
12
donutshop/app/screen/Cart.tsx
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { View, Text } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const Cart = () => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text>Cart</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Cart
|
12
donutshop/app/screen/Detail.tsx
Normal file
12
donutshop/app/screen/Detail.tsx
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { View, Text } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const Detail = () => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text>Detail</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Detail
|
12
donutshop/app/screen/Favorite.tsx
Normal file
12
donutshop/app/screen/Favorite.tsx
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { View, Text } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const Favorite = () => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text>Favorite</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Favorite
|
24
donutshop/app/screen/Home.tsx
Normal file
24
donutshop/app/screen/Home.tsx
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { View, Text, ScrollView, StyleSheet } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
import HomeHeader from '../components/HomeHeader'
|
||||||
|
import { StatusBar } from 'expo-status-bar';
|
||||||
|
|
||||||
|
const Home = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1, backgroundColor: 'white'}}>
|
||||||
|
<StatusBar style="dark"/>
|
||||||
|
<ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={styles.ScrollViewFlex}>
|
||||||
|
<HomeHeader />
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Home
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
ScrollViewFlex:{
|
||||||
|
flexGrow: 1,
|
||||||
|
}
|
||||||
|
})
|
28
donutshop/app/screen/Inbox.tsx
Normal file
28
donutshop/app/screen/Inbox.tsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { View, Text, Pressable, Image, StyleSheet } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import { useNavigation } from '@react-navigation/native';
|
||||||
|
|
||||||
|
const Inbox = () => {
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1, backgroundColor: "white"}}>
|
||||||
|
<View style={{marginTop: 20, paddingHorizontal: 20, paddingVertical: 10}}>
|
||||||
|
<Pressable onPress={() => navigation.goBack()} style={{flexDirection: 'row', gap: 5, alignItems: 'flex-end'}}>
|
||||||
|
<Ionicons name="chevron-back" size={24} color="gray" />
|
||||||
|
</Pressable>
|
||||||
|
<Text style={{paddingHorizontal: 10, paddingTop: 10, fontSize: 30, fontWeight: 600}}>Inbox</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{height: 1, backgroundColor: "#B4B4B8", shadowColor: '#B4B4B8', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.5, shadowRadius: 1, }}></View>
|
||||||
|
|
||||||
|
<View style={{marginVertical: 50, alignItems: 'center'}}>
|
||||||
|
<Image source={require('../../assets/images/misc/empty-inbox.png')} style={{ width: 200, height: 200, resizeMode: "contain"}} />
|
||||||
|
<Text style={{marginTop: 30, fontSize: 16, fontWeight: 500}}>No messages right now</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Inbox
|
146
donutshop/app/screen/Menu.tsx
Normal file
146
donutshop/app/screen/Menu.tsx
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import { View, Text, ScrollView, StyleSheet, Pressable } from 'react-native'
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { useStore } from '../store/store';
|
||||||
|
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
|
||||||
|
import { FlatList, TextInput } from 'react-native-gesture-handler';
|
||||||
|
import { AntDesign } from '@expo/vector-icons';
|
||||||
|
import MenuCard from "../components/MenuCard";
|
||||||
|
import DrinkCard from "../components/DrinkCard";
|
||||||
|
|
||||||
|
const getCategoriesFromData = (data: any) => {
|
||||||
|
let temp: any = {};
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
if (temp[data[i].name] == undefined) {
|
||||||
|
temp[data[i].name] = 1;
|
||||||
|
} else {
|
||||||
|
temp[data[i].name]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let categories = Object.keys(temp);
|
||||||
|
categories.unshift('All');
|
||||||
|
return categories;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDonutList = (category: string, data: any) => {
|
||||||
|
if (category == 'All') {
|
||||||
|
return data;
|
||||||
|
} else {
|
||||||
|
let donutlist = data.filter((item: any) => item.name == category);
|
||||||
|
return donutlist;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Menu = () => {
|
||||||
|
const DonutList = useStore((state: any) => state.AllDonut);
|
||||||
|
const DrinkList = useStore((state: any) => state.AllDrinkList);
|
||||||
|
|
||||||
|
const [categories, setCategories] = useState(getCategoriesFromData(DonutList));
|
||||||
|
const [searchMenu, setSearchMenu] = useState('');
|
||||||
|
const [categoryIndex, setCategoryIndex] = useState({index: 0, category: categories[0]});
|
||||||
|
const [sortItem, setSortItem] = useState(getDonutList(categoryIndex.category, DonutList));
|
||||||
|
|
||||||
|
|
||||||
|
const tabBar = useBottomTabBarHeight();
|
||||||
|
//console.log(sortItem.length)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1, backgroundColor: 'white'}}>
|
||||||
|
<ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={styles.ScrollViewFlex}>
|
||||||
|
<View style={{marginTop: 20, paddingHorizontal: 20, paddingVertical: 10}}>
|
||||||
|
<Text style={{fontSize: 30, fontWeight: 600}}>Menu</Text>
|
||||||
|
|
||||||
|
<View style={{marginVertical: 20, backgroundColor: '#EEEEEE', padding: 10, borderRadius: 10, flexDirection: 'row', justifyContent: 'space-between'}}>
|
||||||
|
<TextInput value={searchMenu} onChangeText={text =>setSearchMenu(text)} placeholder='Search...' style={{fontSize: 18, flex:1}}/>
|
||||||
|
<Pressable onPress={() => {}}>
|
||||||
|
<AntDesign name="search1" size={24} color="gray" />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text style={{fontSize: 26, fontWeight: 600, color: '#EF5A6F'}}>Donuts</Text>
|
||||||
|
</View>
|
||||||
|
{/*===== Tab category =====*/}
|
||||||
|
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.CategoryView}>
|
||||||
|
{categories.map((item, index) => (
|
||||||
|
<View key={index.toString()} style={styles.CategoryScroll}>
|
||||||
|
<Pressable onPress={() => {setCategoryIndex({index:index, category:categories[index]}); setSortItem([...getDonutList(categories[index], DonutList)])}}>
|
||||||
|
<Text style={[styles.catText,
|
||||||
|
categoryIndex.index == index ? {color: '#DA7297'} : {}, ]}>
|
||||||
|
{item}
|
||||||
|
</Text>
|
||||||
|
{categoryIndex.index == index ? (
|
||||||
|
<View style={styles.activeCategory}/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
{/*===== donuts=====*/}
|
||||||
|
<FlatList horizontal showsHorizontalScrollIndicator={false} data={sortItem} contentContainerStyle={styles.MenuListContainer} keyExtractor={item => item.id} renderItem={({item}) => {
|
||||||
|
return <Pressable onPress={() => {}}>
|
||||||
|
<MenuCard
|
||||||
|
id={item.id}
|
||||||
|
index={item.index}
|
||||||
|
type={item.type}
|
||||||
|
name={item.name}
|
||||||
|
donutname={item.donutname}
|
||||||
|
image_item={item.image_item}
|
||||||
|
average_rating={item.average_rating}
|
||||||
|
prices={item.prices[0]}
|
||||||
|
buttonPressHandler={() => {}}
|
||||||
|
/>
|
||||||
|
</Pressable>
|
||||||
|
}}/>
|
||||||
|
{/*===== drinks =====*/}
|
||||||
|
<View>
|
||||||
|
<Text style={{fontSize: 26, fontWeight: 600, color: '#EF5A6F' ,marginTop: 20, paddingHorizontal: 20}}>Drinks</Text>
|
||||||
|
<FlatList horizontal showsHorizontalScrollIndicator={false} data={DrinkList} contentContainerStyle={[styles.MenuListContainer, {marginBottom: tabBar}]} keyExtractor={item => item.id} renderItem={({item}) => {
|
||||||
|
return <Pressable onPress={() => {}}>
|
||||||
|
<DrinkCard
|
||||||
|
id={item.id}
|
||||||
|
index={item.index}
|
||||||
|
type={item.type}
|
||||||
|
name={item.name}
|
||||||
|
image_item={item.image_item}
|
||||||
|
average_rating={item.average_rating}
|
||||||
|
prices={item.prices[0]}
|
||||||
|
buttonPressHandler={() => {}}
|
||||||
|
/>
|
||||||
|
</Pressable>
|
||||||
|
}}/>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Menu
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
ScrollViewFlex:{
|
||||||
|
flexGrow: 1,
|
||||||
|
},
|
||||||
|
CategoryView:{
|
||||||
|
paddingHorizontal: 5
|
||||||
|
},
|
||||||
|
CategoryScroll:{
|
||||||
|
paddingHorizontal: 20
|
||||||
|
},
|
||||||
|
catText:{
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 600,
|
||||||
|
color: 'gray'
|
||||||
|
},
|
||||||
|
activeCategory:{
|
||||||
|
backgroundColor: '#DA7297',
|
||||||
|
padding: 1
|
||||||
|
},
|
||||||
|
MenuListContainer:{
|
||||||
|
gap: 20,
|
||||||
|
paddingVertical: 20,
|
||||||
|
paddingHorizontal: 20
|
||||||
|
}
|
||||||
|
})
|
12
donutshop/app/screen/OrderReceipt.tsx
Normal file
12
donutshop/app/screen/OrderReceipt.tsx
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { View, Text } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const OrderReceipt = () => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text>OrderHistory</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrderReceipt
|
12
donutshop/app/screen/Payment.tsx
Normal file
12
donutshop/app/screen/Payment.tsx
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { View, Text } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const Payment = () => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text>Payment</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Payment
|
29
donutshop/app/screen/Profile.tsx
Normal file
29
donutshop/app/screen/Profile.tsx
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { View, Text, Pressable, Image, StyleSheet } from 'react-native'
|
||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import React from 'react'
|
||||||
|
import { useNavigation } from '@react-navigation/native';
|
||||||
|
|
||||||
|
const Profile = () => {
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1, backgroundColor: "white"}}>
|
||||||
|
<View style={{marginTop: 20, paddingHorizontal: 20, paddingVertical: 10}}>
|
||||||
|
<Pressable onPress={() => navigation.goBack()} style={{flexDirection: 'row', gap: 5, alignItems: 'flex-end'}}>
|
||||||
|
<Ionicons name="chevron-back" size={24} color="gray" />
|
||||||
|
</Pressable>
|
||||||
|
<Text style={{paddingHorizontal: 10, paddingTop: 10, fontSize: 30, fontWeight: 600}}>Account</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{height: 1, backgroundColor: "#B4B4B8", shadowColor: '#B4B4B8', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.5, shadowRadius: 1, }}></View>
|
||||||
|
|
||||||
|
<View style={{marginVertical: 50, alignItems: 'center'}}>
|
||||||
|
<Image source={require('../../assets/images/misc/cannot_load.png')} style={{ width: 200, height: 200, resizeMode: "contain"}} />
|
||||||
|
<Text style={{marginTop: 30, fontSize: 22, fontWeight: 500}}>Something went wrong</Text>
|
||||||
|
<Text style={{margin: 10, fontSize: 16, color: "gray", textAlign: 'center'}}>There was a problem and the page could not be loaded at this moment.</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Profile
|
22
donutshop/app/store/store.ts
Normal file
22
donutshop/app/store/store.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import {create} from "zustand";
|
||||||
|
import {produce} from "immer";
|
||||||
|
import {persist, createJSONStorage} from "zustand/middleware";
|
||||||
|
import AsynStorage from "@react-native-async-storage/async-storage";
|
||||||
|
import DonutData from "../data/DonutData";
|
||||||
|
import DrinkData from "../data/DrinkData";
|
||||||
|
|
||||||
|
export const useStore = create(
|
||||||
|
persist(
|
||||||
|
(set, get) => ({
|
||||||
|
AllDonut: DonutData,
|
||||||
|
AllDrinkList: DrinkData,
|
||||||
|
CartPrice: 0,
|
||||||
|
FavoriteList: [],
|
||||||
|
CartList: [],
|
||||||
|
ReceiptList: []
|
||||||
|
}), {
|
||||||
|
name: 'donutshop',
|
||||||
|
storage: createJSONStorage(() => AsynStorage),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
BIN
donutshop/assets/fonts/SpaceMono-Regular.ttf
Executable file
BIN
donutshop/assets/fonts/SpaceMono-Regular.ttf
Executable file
Binary file not shown.
6
donutshop/babel.config.js
Normal file
6
donutshop/babel.config.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = function (api) {
|
||||||
|
api.cache(true);
|
||||||
|
return {
|
||||||
|
presets: ['babel-preset-expo'],
|
||||||
|
};
|
||||||
|
};
|
18378
donutshop/package-lock.json
generated
Normal file
18378
donutshop/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
55
donutshop/package.json
Normal file
55
donutshop/package.json
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
"name": "donutshop",
|
||||||
|
"main": "expo-router/entry",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"start": "expo start",
|
||||||
|
"reset-project": "node ./scripts/reset-project.js",
|
||||||
|
"android": "expo start --android",
|
||||||
|
"ios": "expo start --ios",
|
||||||
|
"web": "expo start --web",
|
||||||
|
"test": "jest --watchAll",
|
||||||
|
"lint": "expo lint"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"preset": "jest-expo"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@expo/vector-icons": "^14.0.2",
|
||||||
|
"@react-native-async-storage/async-storage": "^1.24.0",
|
||||||
|
"@react-navigation/bottom-tabs": "^6.6.1",
|
||||||
|
"@react-navigation/native": "^6.1.18",
|
||||||
|
"@react-navigation/stack": "^6.4.1",
|
||||||
|
"expo": "~51.0.21",
|
||||||
|
"expo-blur": "^13.0.2",
|
||||||
|
"expo-constants": "~16.0.2",
|
||||||
|
"expo-font": "~12.0.9",
|
||||||
|
"expo-linking": "~6.3.1",
|
||||||
|
"expo-router": "~3.5.18",
|
||||||
|
"expo-splash-screen": "~0.27.5",
|
||||||
|
"expo-status-bar": "~1.12.1",
|
||||||
|
"expo-system-ui": "~3.0.7",
|
||||||
|
"expo-web-browser": "~13.0.3",
|
||||||
|
"immer": "^10.1.1",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"react-native": "0.74.3",
|
||||||
|
"react-native-gesture-handler": "~2.16.1",
|
||||||
|
"react-native-reanimated": "~3.10.1",
|
||||||
|
"react-native-safe-area-context": "4.10.5",
|
||||||
|
"react-native-screens": "3.31.1",
|
||||||
|
"react-native-web": "~0.19.10",
|
||||||
|
"zustand": "^4.5.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.20.0",
|
||||||
|
"@types/jest": "^29.5.12",
|
||||||
|
"@types/react": "~18.2.45",
|
||||||
|
"@types/react-test-renderer": "^18.0.7",
|
||||||
|
"jest": "^29.2.1",
|
||||||
|
"jest-expo": "~51.0.3",
|
||||||
|
"react-test-renderer": "18.2.0",
|
||||||
|
"typescript": "~5.3.3"
|
||||||
|
},
|
||||||
|
"private": true
|
||||||
|
}
|
73
donutshop/scripts/reset-project.js
Executable file
73
donutshop/scripts/reset-project.js
Executable file
|
@ -0,0 +1,73 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This script is used to reset the project to a blank state.
|
||||||
|
* It moves the /app directory to /app-example and creates a new /app directory with an index.tsx and _layout.tsx file.
|
||||||
|
* You can remove the `reset-project` script from package.json and safely delete this file after running it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const root = process.cwd();
|
||||||
|
const oldDirPath = path.join(root, 'app');
|
||||||
|
const newDirPath = path.join(root, 'app-example');
|
||||||
|
const newAppDirPath = path.join(root, 'app');
|
||||||
|
|
||||||
|
const indexContent = `import { Text, View } from "react-native";
|
||||||
|
|
||||||
|
export default function Index() {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text>Edit app/index.tsx to edit this screen.</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const layoutContent = `import { Stack } from "expo-router";
|
||||||
|
|
||||||
|
export default function RootLayout() {
|
||||||
|
return (
|
||||||
|
<Stack>
|
||||||
|
<Stack.Screen name="index" />
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
fs.rename(oldDirPath, newDirPath, (error) => {
|
||||||
|
if (error) {
|
||||||
|
return console.error(`Error renaming directory: ${error}`);
|
||||||
|
}
|
||||||
|
console.log('/app moved to /app-example.');
|
||||||
|
|
||||||
|
fs.mkdir(newAppDirPath, { recursive: true }, (error) => {
|
||||||
|
if (error) {
|
||||||
|
return console.error(`Error creating new app directory: ${error}`);
|
||||||
|
}
|
||||||
|
console.log('New /app directory created.');
|
||||||
|
|
||||||
|
const indexPath = path.join(newAppDirPath, 'index.tsx');
|
||||||
|
fs.writeFile(indexPath, indexContent, (error) => {
|
||||||
|
if (error) {
|
||||||
|
return console.error(`Error creating index.tsx: ${error}`);
|
||||||
|
}
|
||||||
|
console.log('app/index.tsx created.');
|
||||||
|
|
||||||
|
const layoutPath = path.join(newAppDirPath, '_layout.tsx');
|
||||||
|
fs.writeFile(layoutPath, layoutContent, (error) => {
|
||||||
|
if (error) {
|
||||||
|
return console.error(`Error creating _layout.tsx: ${error}`);
|
||||||
|
}
|
||||||
|
console.log('app/_layout.tsx created.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
17
donutshop/tsconfig.json
Normal file
17
donutshop/tsconfig.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "expo/tsconfig.base",
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".expo/types/**/*.ts",
|
||||||
|
"expo-env.d.ts"
|
||||||
|
, "app/index.js", "app/components/MenuDrink.js" ]
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue