updated add/delete favorite item functionality and created detail for donut page
This commit is contained in:
parent
019357bcc0
commit
38d0aef5c7
5 changed files with 326 additions and 37 deletions
76
donutshop/app/components/BackgroundInfo.tsx
Normal file
76
donutshop/app/components/BackgroundInfo.tsx
Normal file
|
@ -0,0 +1,76 @@
|
|||
import { ImageBackground, ImageProps, Pressable, StyleSheet, Text, View } from 'react-native'
|
||||
import React from 'react'
|
||||
import { Ionicons, AntDesign } from '@expo/vector-icons';
|
||||
|
||||
|
||||
interface BackgroundInfoProps{
|
||||
EnableBackHandler: boolean;
|
||||
type: string,
|
||||
id: string,
|
||||
image_item: ImageProps,
|
||||
favourite: boolean,
|
||||
donutname: string,
|
||||
calories: string,
|
||||
average_rating: number,
|
||||
ratings_count: string,
|
||||
BackHandler?: any;
|
||||
ToggleFavorite: any
|
||||
}
|
||||
|
||||
|
||||
const BackgroundInfo: React.FC<BackgroundInfoProps> = ({
|
||||
EnableBackHandler,
|
||||
type,
|
||||
id,
|
||||
image_item,
|
||||
favourite,
|
||||
donutname,
|
||||
calories,
|
||||
average_rating,
|
||||
ratings_count,
|
||||
BackHandler,
|
||||
ToggleFavorite,
|
||||
}) => {
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<View>
|
||||
<ImageBackground source={image_item} style={{width: '100%', aspectRatio: 20/25, justifyContent: 'space-between'}}>
|
||||
{EnableBackHandler ? (
|
||||
<View style={{padding:10, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'}}>
|
||||
<Pressable onPress={() => {BackHandler()}} style={{paddingHorizontal: 10, paddingVertical: 10}}>
|
||||
<Ionicons name="chevron-back" size={30} color="gray"/>
|
||||
</Pressable>
|
||||
<Pressable onPress={() => {ToggleFavorite(favourite, type, id);}} style={{paddingHorizontal: 10, paddingVertical: 10}}>
|
||||
<AntDesign name="heart" size={24} color={favourite ? '#EF5A6F' : 'gray'} />
|
||||
</Pressable>
|
||||
</View>
|
||||
) : (
|
||||
<View style={{padding:10, flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-end'}}>
|
||||
<Pressable onPress={() => {ToggleFavorite(favourite, type, id);}} style={{paddingHorizontal: 10, paddingVertical: 10}}>
|
||||
<AntDesign name="heart" size={24} color={favourite ? '#EF5A6F' : 'gray'} />
|
||||
</Pressable>
|
||||
</View>
|
||||
)}
|
||||
<View style={{backgroundColor: 'rgba(255, 255, 255, 0.8)', borderTopRightRadius: 10, borderTopLeftRadius: 10}}>
|
||||
<View style={{padding: 10, marginHorizontal: 10, marginVertical: 10}}>
|
||||
<Text style={{color: '#DA7297', fontSize: 22, fontWeight: 500}}>{donutname}</Text>
|
||||
</View>
|
||||
<View style={{flexDirection: 'row', justifyContent: 'space-between', paddingHorizontal: 20, marginVertical: 10}}>
|
||||
<Text style={{color: '#DA7297', fontSize: 18}}>{calories} calories</Text>
|
||||
<View style={{flexDirection: 'row', gap: 3, alignItems: 'center'}}>
|
||||
<AntDesign name="star" size={20} color="#EF5A6F"/>
|
||||
<Text style={{color: '#DA7297', textAlign: 'right', fontSize: 18}}>{average_rating}</Text>
|
||||
<Text style={{color: 'gray'}}>({ratings_count})</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ImageBackground>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default BackgroundInfo
|
||||
|
||||
const styles = StyleSheet.create({})
|
|
@ -1,10 +1,48 @@
|
|||
import { View, Text } from 'react-native'
|
||||
import React from 'react'
|
||||
import { View, Text, ScrollView } from 'react-native';
|
||||
import React from 'react';
|
||||
import { useStore } from '../store/store';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import BackgroundInfo from "../components/BackgroundInfo";
|
||||
|
||||
|
||||
|
||||
const Detail = ({navigation, route}: any) => {
|
||||
const ItemOfIndex = useStore((state: any) =>
|
||||
route.params.type == 'Donut' ? state.AllDonutList1 : state.AllDrinkList,
|
||||
)[route.params.index];
|
||||
|
||||
const addToFavoriteList = useStore((state: any) => state.addToFavoriteList);
|
||||
const deleteFromFavoriteList = useStore((state: any) => state.deleteFromFavoriteList);
|
||||
|
||||
//favorite functionality
|
||||
const ToggleFavorite = (favourite: boolean, type: string, id: string) => {
|
||||
favourite ? deleteFromFavoriteList(type, id) : addToFavoriteList(type, id)
|
||||
}
|
||||
|
||||
//backhandler functionality
|
||||
const BackHandler = () => {
|
||||
navigation.pop();
|
||||
}
|
||||
|
||||
|
||||
const Detail = () => {
|
||||
return (
|
||||
<View>
|
||||
<Text>Detail</Text>
|
||||
<View style={{flex: 1, backgroundColor: 'white'}}>
|
||||
<StatusBar backgroundColor='dark'/>
|
||||
<ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={{flexGrow: 1}}>
|
||||
<BackgroundInfo
|
||||
EnableBackHandler={true}
|
||||
type={ItemOfIndex.type}
|
||||
id={ItemOfIndex.id}
|
||||
image_item={ItemOfIndex.image_item}
|
||||
favourite={ItemOfIndex.favourite}
|
||||
donutname={ItemOfIndex.donutname}
|
||||
calories={ItemOfIndex.calories}
|
||||
average_rating={ItemOfIndex.average_rating}
|
||||
ratings_count={ItemOfIndex.ratings_count}
|
||||
BackHandler={BackHandler}
|
||||
ToggleFavorite={ToggleFavorite}
|
||||
/>
|
||||
</ScrollView>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ const Inbox = () => {
|
|||
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'}}>
|
||||
<Pressable onPress={() => navigation.goBack()} >
|
||||
<Ionicons name="chevron-back" size={24} color="gray" />
|
||||
</Pressable>
|
||||
<Text style={{paddingHorizontal: 10, paddingTop: 10, fontSize: 30, fontWeight: 600}}>Inbox</Text>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { View, Text, ScrollView, StyleSheet, Pressable } from 'react-native'
|
||||
import { View, Text, ScrollView, StyleSheet, Pressable, Dimensions} 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 { AntDesign, MaterialIcons} from '@expo/vector-icons';
|
||||
import MenuCard from "../components/MenuCard";
|
||||
import DrinkCard from "../components/DrinkCard";
|
||||
|
||||
|
@ -31,8 +31,8 @@ const getDonutList = (category: string, data: any) => {
|
|||
};
|
||||
|
||||
|
||||
const Menu = () => {
|
||||
const DonutList = useStore((state: any) => state.AllDonut);
|
||||
const Menu = ({navigation}: any) => {
|
||||
const DonutList = useStore((state: any) => state.AllDonutList1);
|
||||
const DrinkList = useStore((state: any) => state.AllDrinkList);
|
||||
|
||||
const [categories, setCategories] = useState(getCategoriesFromData(DonutList));
|
||||
|
@ -43,23 +43,52 @@ const Menu = () => {
|
|||
|
||||
const tabBar = useBottomTabBarHeight();
|
||||
//console.log(sortItem.length)
|
||||
const searchMenuItem = (search:string) => {
|
||||
if(search != ''){
|
||||
setCategoryIndex({index: 0, category: categories[0]});
|
||||
setSortItem([...DonutList.filter((item: any) =>
|
||||
item.donutname.toLowerCase().includes(search.toLocaleLowerCase()),),]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const resetSearch = () => {
|
||||
setCategoryIndex({index: 0, category: categories[0]});
|
||||
setSortItem([...DonutList]);
|
||||
setSearchMenu('');
|
||||
}
|
||||
|
||||
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>
|
||||
{/*===== search =====*/}
|
||||
<View style={{marginTop: 20, marginBottom: 10, backgroundColor: '#EEEEEE', padding: 10, borderRadius: 10, flexDirection: 'row', justifyContent: 'space-between'}}>
|
||||
{searchMenu.length == 0 ? (
|
||||
<Pressable onPress={() => {searchMenuItem(searchMenu)}}>
|
||||
<AntDesign name="search1" size={24} color="gray" />
|
||||
</Pressable>
|
||||
) : (
|
||||
<Pressable onPress={() => {resetSearch()}}>
|
||||
<MaterialIcons name="close" size={24} color="black" />
|
||||
</Pressable>
|
||||
)}
|
||||
|
||||
<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>
|
||||
<TextInput value={searchMenu} onChangeText={text => {setSearchMenu(text); searchMenuItem(text)}} placeholder='Search...' style={{fontSize: 18, flex:1, marginLeft: 5}}/>
|
||||
|
||||
{searchMenu.length > 0 ? (
|
||||
<Pressable onPress={() => {searchMenuItem(searchMenu)}}>
|
||||
<AntDesign name="search1" size={24} color="gray" />
|
||||
</Pressable>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<Text style={{fontSize: 26, fontWeight: 600, color: '#EF5A6F'}}>Donuts</Text>
|
||||
</View>
|
||||
{/*===== Tab category =====*/}
|
||||
<Text style={{fontSize: 26, fontWeight: 600, color: '#EF5A6F', paddingHorizontal: 20, marginBottom: 20}}>Donuts</Text>
|
||||
|
||||
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.CategoryView}>
|
||||
{categories.map((item, index) => (
|
||||
<View key={index.toString()} style={styles.CategoryScroll}>
|
||||
|
@ -79,8 +108,25 @@ const Menu = () => {
|
|||
</ScrollView>
|
||||
|
||||
{/*===== donuts=====*/}
|
||||
<FlatList horizontal showsHorizontalScrollIndicator={false} data={sortItem} contentContainerStyle={styles.MenuListContainer} keyExtractor={item => item.id} renderItem={({item}) => {
|
||||
return <Pressable onPress={() => {}}>
|
||||
<FlatList
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
data={sortItem}
|
||||
contentContainerStyle={styles.MenuListContainer}
|
||||
keyExtractor={item => item.id}
|
||||
ListEmptyComponent={
|
||||
<View style={{width: Dimensions.get('window').width - 20*2, alignItems: 'center', justifyContent: 'center'}}>
|
||||
<Text style={{fontWeight: 500, flex: 1,}}>Sorry, this item is not on our menu</Text>
|
||||
</View>
|
||||
}
|
||||
renderItem={({item}) => {
|
||||
return <Pressable onPress={() => {
|
||||
navigation.push('detail', {
|
||||
index: item.index,
|
||||
id: item.id,
|
||||
type: item.type,
|
||||
});
|
||||
}}>
|
||||
<MenuCard
|
||||
id={item.id}
|
||||
index={item.index}
|
||||
|
@ -96,21 +142,33 @@ const Menu = () => {
|
|||
}}/>
|
||||
{/*===== 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>
|
||||
}}/>
|
||||
<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={() => {
|
||||
navigation.push('detail', {
|
||||
index: item.index,
|
||||
id: item.id,
|
||||
type: item.type,
|
||||
});
|
||||
}}>
|
||||
<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>
|
||||
|
|
|
@ -8,13 +8,130 @@ import DrinkData from "../data/DrinkData";
|
|||
export const useStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
AllDonut: DonutData,
|
||||
AllDonutList1: DonutData,
|
||||
AllDrinkList: DrinkData,
|
||||
CartPrice: 0,
|
||||
FavoriteList: [],
|
||||
CartList: [],
|
||||
ReceiptList: []
|
||||
}), {
|
||||
ReceiptList: [],
|
||||
addToCart:(cartItem: any) =>
|
||||
set(
|
||||
produce(state => {
|
||||
let found = false;
|
||||
for(let i = 0; i < state.CartList.length; i++){
|
||||
if(state.CartList[i].id == cartItem.id){
|
||||
found = true;
|
||||
let size = false;
|
||||
for(let j = 0; j < state.CartList[i].prices.length; j++){
|
||||
if(state.CartList[i].prices[j].size == cartItem.prices[0].size){
|
||||
size = true;
|
||||
state.CartList[i].prices[j].quantity++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(size == false){
|
||||
state.CartList[i].prices.push(cartItem.prices[0]);
|
||||
}
|
||||
state.CartList[i].prices.sort((a: any, b: any) => {
|
||||
if(a.size > b.size){
|
||||
return -1;
|
||||
}
|
||||
if(a.size < b.size) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found == false){
|
||||
state.CartList.push(cartItem)
|
||||
}
|
||||
}),
|
||||
),
|
||||
calculateCartPrice:() =>
|
||||
set(
|
||||
produce(state => {
|
||||
let totalPrice = 0;
|
||||
for(let i = 0; i < state.CartList.length; i++){
|
||||
let tempPrice = 0;
|
||||
for(let j = 0; j < state.CartList[i].prices.length; j++){
|
||||
tempPrice = tempPrice + parseFloat(state.CartList[i].prices[j].price) * state.CartList[i].prices[j].quantity;
|
||||
}
|
||||
state.CartList[i].ItemPrice = tempPrice.toFixed(2).toString();
|
||||
totalPrice = totalPrice + tempPrice;
|
||||
}
|
||||
state.CartPrice = totalPrice.toFixed(2).toString();
|
||||
})
|
||||
),
|
||||
addToFavoriteList:(type: string, id: string) =>
|
||||
set(
|
||||
produce(state => {
|
||||
if(type == 'Donut'){
|
||||
for(let i = 0; i < state.AllDonutList1.length; i++){
|
||||
if(state.AllDonutList1[i].id == id){
|
||||
if(state.AllDonutList1[i].favourite == false){
|
||||
state.AllDonutList1[i].favourite = true;
|
||||
state.FavoriteList.unshift(state.AllDonutList1[i]);
|
||||
} else{
|
||||
state.AllDonutList1[i].favourite = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(type == 'Drink'){
|
||||
for(let i = 0; i< state.AllDrinkList.length; i++){
|
||||
if(state.AllDrinkList[i].id == id){
|
||||
if(state.AllDrinkList[i].favourite == false){
|
||||
state.AllDrinkList[i].favourite = true;
|
||||
state.FavoriteList.unshift(state.AllDrinkList[i]);
|
||||
} else{
|
||||
state.AllDrinkList[i].favourite = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
),
|
||||
deleteFromFavoriteList:(type: string, id: string) =>
|
||||
set(
|
||||
produce(state => {
|
||||
if(type = 'Donut'){
|
||||
for(let i = 0; i < state.AllDonutList1.length; i++){
|
||||
if(state.AllDonutList1[i].id == id){
|
||||
if(state.AllDonutList1[i].favourite == true){
|
||||
state.AllDonutList1[i].favourite = false;
|
||||
} else{
|
||||
state.AllDonutList1[i].favourite = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(type = 'Drink'){
|
||||
for(let i = 0; i < state.AllDrinkList.length; i++){
|
||||
if(state.AllDrinkList[i].id == id){
|
||||
if(state.AllDrinkList[i].favourite == true){
|
||||
state.AllDrinkList[i].favourite = false;
|
||||
} else{
|
||||
state.AllDrinkList[i].favourite = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let spliceIndex = -1;
|
||||
for(let i = 0; i < state.FavoriteList.length; i++){
|
||||
if (state.FavoriteList[i].id == id){
|
||||
spliceIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.FavoriteList.splice(spliceIndex, 1);
|
||||
}),
|
||||
),
|
||||
}),
|
||||
{
|
||||
name: 'donutshop',
|
||||
storage: createJSONStorage(() => AsynStorage),
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue