grocery-app/Customer App/src/screens/MenuItems/MenuItems.js

284 lines
8.1 KiB
JavaScript
Executable File

import { useQuery } from "@apollo/react-hooks";
import { useNavigation, useRoute } from "@react-navigation/native";
//import { useHeaderHeight } from '@react-navigation/stack'
import { useHeaderHeight } from "@react-navigation/elements";
import gql from "graphql-tag";
import { get } from "lodash";
import React, { useContext, useLayoutEffect, useRef, useState } from "react";
import {
FlatList,
ImageBackground,
Platform,
TouchableOpacity,
View,
} from "react-native";
import { Modalize } from "react-native-modalize";
import { foods } from "../../apollo/server";
import EmptyFood from "../../assets/images/SVG/imageComponents/EmptyFood";
import {
EnategaImage,
FilterModal,
FlashMessage,
RightButton,
Spinner,
TextDefault,
TextError,
WrapperView,
} from "../../components";
import ConfigurationContext from "../../context/Configuration";
import UserContext from "../../context/User";
import { alignment } from "../../utils/alignment";
import { ICONS_NAME, NAVIGATION_SCREEN, SORT_DATA } from "../../utils/constant";
import { moderateScale, scale } from "../../utils/scaling";
import useStyle from "./styles";
// constants
const FOODS = gql`
${foods}
`;
function MenuItems() {
const route = useRoute();
const styles = useStyle();
const headerHeight = useHeaderHeight();
const navigation = useNavigation();
const _id = route.params._id ?? null;
const imgMenu = route.params.img_menu ?? null;
const title = route.params.title ?? null;
const description = route.params.description ?? null;
const [filters, setFilters] = useState({});
const { loading, error, data, refetch, networkStatus } = useQuery(FOODS, {
variables: { category: _id, ...filters },
});
const { addCartItem } = useContext(UserContext);
const configuration = useContext(ConfigurationContext);
const modalizeRef = useRef(null);
const closeModal = () => {
modalizeRef.current.close();
};
useLayoutEffect(() => {
navigation.setOptions({
headerTitle: title,
headerRight: () => (
<RightButton
icon={ICONS_NAME.Filter}
onPress={() => modalizeRef.current.open()}
/>
),
});
}, [navigation]);
async function onAddToCart(food) {
if (food.stock < 1) {
FlashMessage({
message: "Item out of stock",
});
return;
}
if (
food.variations.length === 1 &&
food.variations[0].addons.length === 0
) {
await addCartItem(food._id, food.variations[0]._id);
navigation.navigate(NAVIGATION_SCREEN.Cart);
} else {
navigation.navigate(NAVIGATION_SCREEN.ItemDetail, { food });
}
}
function renderGridCards(item) {
return (
<TouchableOpacity
onPress={() => {
onAddToCart(item);
}}
activeOpacity={0.7}
style={styles.cardContainer}
>
<View style={styles.cardImageContainer}>
<EnategaImage
imgStyle={styles.imgResponsive}
imgSource={
item.img_url
? { uri: item.img_url }
: require("../../assets/images/food_placeholder.png")
}
resizeMode={"cover"}
spinnerProps={{ style: styles.loadingView }}
/>
{item.stock < 1 && (
<View style={styles.emtpyStockLabel}>
<TextDefault textColor={styles.whiteFont.color} center>
No Stock
</TextDefault>
</View>
)}
</View>
<View style={[styles.textContainer]}>
<TextDefault numberOfLines={2} style={alignment.MBxSmall} bolder H5>
{item.title}
</TextDefault>
<TextDefault
numberOfLines={2}
textColor={styles.lightColor.color}
small
medium
>
{item.description}
</TextDefault>
<View style={{ flexDirection: "row", alignItems: "center" }}>
{item.variations[0].discounted > 0 && (
<TextDefault
textColor={styles.lightColor.color}
style={[alignment.MRxSmall]}
small
bold
H5
lineOver
>
{configuration.currency_symbol}{" "}
{(
item.variations[0].price + item.variations[0].discounted
).toFixed(2)}
</TextDefault>
)}
<TextDefault textColor={styles.tagColor.color} H4 bolder>
{configuration.currency_symbol}{" "}
{item.variations[0].price.toFixed(2)}
</TextDefault>
</View>
</View>
</TouchableOpacity>
);
}
function sortData(foods) {
const VALUE = get(SORT_DATA, get(filters, "sort"));
switch (VALUE) {
case SORT_DATA.NameAsc:
return foods.sort((a, b) =>
a.title.toLowerCase() > b.title.toLowerCase() ? 1 : -1
);
case SORT_DATA.NameDesc:
return foods.sort((a, b) =>
a.title.toLowerCase() < b.title.toLowerCase() ? 1 : -1
);
case SORT_DATA.PriceAsc:
return foods.sort((a, b) =>
a.variations[0].price > b.variations[0].price ? 1 : -1
);
case SORT_DATA.PriceDesc:
return foods.sort((a, b) =>
a.variations[0].price < b.variations[0].price ? 1 : -1
);
default:
return foods.sort((a, b) => (a.img_url < b.img_url ? 1 : -1));
}
}
const setFilterss = (filterObj) => {
setFilters(filterObj);
};
function emptyView() {
if (loading) {
return <Spinner />;
} else if (error) {
return (
<TextError
text={error ? error.message : "No Foods"}
backColor="transparent"
/>
);
} else {
return (
<View style={styles.emptyContainer}>
<EmptyFood width={scale(250)} height={scale(250)} />
<TextDefault H4 bold style={alignment.MTlarge}>
No food item found
</TextDefault>
</View>
);
}
}
function renderListHeader() {
return (
<View style={styles.backgroundImageContainer}>
<ImageBackground
style={styles.backgroundImage}
borderRadius={moderateScale(20)}
source={
imgMenu
? { uri: imgMenu }
: require("../../assets/images/food_placeholder.png")
}
>
<View style={styles.shadeContainer}></View>
<View style={styles.backgroundImageTextContainer}>
<TextDefault
numberOfLines={1}
textColor={styles.whiteFont.color}
H4
bolder
>
{title}
</TextDefault>
<TextDefault
numberOfLines={1}
textColor={styles.whiteFont.color}
bold
>
{description}
</TextDefault>
</View>
</ImageBackground>
</View>
);
}
return (
<WrapperView>
<View style={[styles.flex]}>
<FlatList
style={styles.flex}
contentContainerStyle={styles.contentContaienr}
showsVerticalScrollIndicator={false}
ListHeaderComponent={renderListHeader()}
keyExtractor={(item) => item._id}
ListEmptyComponent={emptyView}
data={loading ? [] : error ? [] : sortData(data.foodByCategory)}
refreshing={networkStatus === 4}
onRefresh={() =>
refetch({
variables: { category: _id, ...filters },
})
}
renderItem={({ item }) => renderGridCards(item)}
/>
</View>
<Modalize
ref={modalizeRef}
adjustToContentHeight
handlePosition="inside"
modalTopOffset={headerHeight}
avoidKeyboardLikeIOS={Platform.select({
ios: true,
android: false,
})}
keyboardAvoidingOffset={2}
keyboardAvoidingBehavior="height"
>
<FilterModal
filterObj={filters}
setFilters={setFilterss}
closeFilterModal={closeModal}
/>
</Modalize>
</WrapperView>
);
}
export default MenuItems;