updated add/delete favorite item functionality and created detail for donut page

This commit is contained in:
Juthatip McDevitt 2024-07-23 16:35:01 -05:00
parent 019357bcc0
commit 38d0aef5c7
5 changed files with 326 additions and 37 deletions

View 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({})

View file

@ -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 = () => {
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();
}
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>
)
}

View file

@ -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>

View file

@ -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>

View file

@ -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),
}