react_native/donutshop/app/screen/Menu.tsx

247 lines
No EOL
7.7 KiB
TypeScript

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, MaterialIcons} 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 = ({navigation}: any) => {
const DonutList = useStore((state: any) => state.AllDonutMenu);
const DrinkList = useStore((state: any) => state.AllDrinkMenu);
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)
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('');
}
//add to cart
const addToCart = useStore((state: any) => state.addToCart);
const calculateCartPrice = useStore((state: any) => state.calculateCartPrice);
const drinkCardAddToCart = ({
id,
index,
name,
image_item,
type,
prices
}: any) => {
addToCart({
id,
index,
name,
image_item,
type,
prices,
});
calculateCartPrice();
}
const DonutCardAddToCart = ({
id,
index,
donutname,
image_item,
type,
prices
}: any) => {
addToCart({
id,
index,
donutname,
image_item,
type,
prices,
});
calculateCartPrice();
}
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>
)}
<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>
</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}>
<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}
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}
type={item.type}
name={item.name}
donutname={item.donutname}
image_item={item.image_item}
average_rating={item.average_rating}
price={item.prices[0]}
buttonPressHandler={DonutCardAddToCart}
/>
</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={() => {
navigation.push('detailDrink', {
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}
price={item.prices[0]}
buttonPressHandler={drinkCardAddToCart}
/>
</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
}
})