diff --git a/consumer/v2/food/home/FoodOrderHome.tsx b/consumer/v2/food/home/FoodOrderHome.tsx index ecd40a828..508bc8171 100644 --- a/consumer/v2/food/home/FoodOrderHome.tsx +++ b/consumer/v2/food/home/FoodOrderHome.tsx @@ -11,7 +11,7 @@ import { useSearch } from '../../../../common/store/api/search/useSearch'; import { useSegmentScreen } from '../../../../common/store/api/track'; import { updateCurrentLocation, - updateCurrentPlace, + updateCurrentPlace } from '../../../../common/store/consumer/actions'; import { getConsumer, getCurrentLocation } from '../../../../common/store/consumer/selectors'; import { SearchFilter } from '../../../../common/store/consumer/types'; @@ -50,6 +50,10 @@ export const FoodOrderHome = ({ route, navigation }: Props) => { refetch, fetchNextPage, } = useSearch(true, 'restaurant', 'distance', filters, currentLocation, ''); + if (restaurants) { + restaurants[0].status = 'open'; + } + const [refreshing, setRefreshing] = React.useState(false); const mostRecentRestaurants = useLastRestaurants(consumer?.id); // side effects diff --git a/consumer/v2/food/restaurant/product/ItemDetail.tsx b/consumer/v2/food/restaurant/product/ItemDetail.tsx index 69ab2ae54..e19c216a5 100644 --- a/consumer/v2/food/restaurant/product/ItemDetail.tsx +++ b/consumer/v2/food/restaurant/product/ItemDetail.tsx @@ -3,7 +3,7 @@ import { ComplementGroup, OrderItem, OrderItemComplement, - WithId, + WithId } from '@appjusto/types'; import { Feather } from '@expo/vector-icons'; import { CompositeNavigationProp, RouteProp } from '@react-navigation/native'; @@ -19,6 +19,7 @@ import PaddedView from '../../../../../common/components/containers/PaddedView'; import DefaultInput from '../../../../../common/components/inputs/DefaultInput'; import HR from '../../../../../common/components/views/HR'; import { IconSemaphoreSmall } from '../../../../../common/icons/icon-semaphore-small'; +import useLastKnownLocation from '../../../../../common/location/useLastKnownLocation'; import { UnloggedParamList } from '../../../../../common/screens/unlogged/types'; import { useProduct } from '../../../../../common/store/api/business/hooks/useProduct'; import { useProductImageURI } from '../../../../../common/store/api/business/hooks/useProductImageURI'; @@ -26,18 +27,14 @@ import { getNextAvailableDate } from '../../../../../common/store/api/business/s import { distanceBetweenLatLng } from '../../../../../common/store/api/helpers'; import * as helpers from '../../../../../common/store/api/order/helpers'; import { track, useSegmentScreen } from '../../../../../common/store/api/track'; -import { - getConsumer, - getCurrentLocation, - getCurrentPlace, -} from '../../../../../common/store/consumer/selectors'; +import { getConsumer, getCurrentPlace } from '../../../../../common/store/consumer/selectors'; import { useContextBusiness, - useContextBusinessId, + useContextBusinessId } from '../../../../../common/store/context/business'; import { useContextGetComplementGroup, - useContextGetProductCategory, + useContextGetProductCategory } from '../../../../../common/store/context/menu'; import { useContextActiveOrder } from '../../../../../common/store/context/order'; import { @@ -46,7 +43,7 @@ import { halfPadding, padding, screens, - texts, + texts } from '../../../../../common/styles'; import { formatCurrency, formatHour } from '../../../../../common/utils/formatters'; import { t } from '../../../../../strings'; @@ -56,6 +53,7 @@ import { RestaurantNavigatorParamList } from '../types'; import { useBusinessIsAcceptingOrders } from '../useBusinessIsAcceptingOrders'; import { ItemComplements } from './ItemComplements'; import { ItemQuantity } from './ItemQuantity'; +import { LocationDistantFromDestinationModal } from './LocationDistantFromDestinationModal'; type ScreenNavigationProp = CompositeNavigationProp< StackNavigationProp, @@ -85,12 +83,18 @@ export const ItemDetail = ({ navigation, route }: Props) => { const consumer = useSelector(getConsumer); const currentPlace = useSelector(getCurrentPlace); // state - const location = useSelector(getCurrentLocation); - const destination = activeOrder?.destination?.location ?? currentPlace?.location ?? location; + + const { coords } = useLastKnownLocation(); + + const destination = activeOrder?.destination?.location; + const location = coords ?? currentPlace?.location; const distance = destination && business?.businessAddress?.latlng ? distanceBetweenLatLng(destination, business.businessAddress.latlng) : 0; + const distanceBetweenLocationAndDestinationMeters = + location && destination ? distanceBetweenLatLng(location, destination) : 0; + const bottomLimitWarningModalShowMeters = 2000; const isOutOfRange = (business?.deliveryRange ?? 0) < (distance ?? 0); const isAcceptingOrders = useBusinessIsAcceptingOrders(business); const product = useProduct(businessId, productId); @@ -99,6 +103,7 @@ export const ItemDetail = ({ navigation, route }: Props) => { const [quantity, setQuantity] = React.useState(1); const [complements, setComplements] = React.useState([]); const [notes, setNotes] = React.useState(''); + const [modalVisible, setModalVisible] = React.useState(false); const orderItem = React.useMemo(() => { if (!product) return undefined; return { @@ -114,6 +119,14 @@ export const ItemDetail = ({ navigation, route }: Props) => { complements, } as OrderItem; }, [product, itemId, quantity, notes, complements, getProductCategory]); + + const isLocationDistantFromDestination = React.useMemo( + (): boolean => + (activeOrder?.items?.length ?? 0) === 0 && + distanceBetweenLocationAndDestinationMeters > bottomLimitWarningModalShowMeters, + [activeOrder, distanceBetweenLocationAndDestinationMeters, bottomLimitWarningModalShowMeters] + ); + const canAddItemToOrder = React.useMemo(() => { if (!product) return false; return helpers.hasSatisfiedAllGroups(product, complements); @@ -132,10 +145,16 @@ export const ItemDetail = ({ navigation, route }: Props) => { if (!product) return; const item = activeOrder.items?.find((i) => i.id === itemId); if (!item) return; + setComplements(item.complements ?? []); setQuantity(item.quantity); setNotes(item.notes ?? ''); }, [itemId, activeOrder, product]); + React.useEffect(() => { + if (!activeOrder) { + api.order().createFoodOrder(business!, consumer!, [], currentPlace ?? null); + } + }, []); // tracking useSegmentScreen('ItemDetail'); // UI @@ -181,10 +200,21 @@ export const ItemDetail = ({ navigation, route }: Props) => { } }; // handlers + const handleAddItemToOrder = () => { + Keyboard.dismiss(); + if (isLocationDistantFromDestination) { + setModalVisible(true); + } else { + updateOrder(); + } + }; + const updateOrder = () => { (async () => { - Keyboard.dismiss(); if (!orderItem) return; + + console.log(activeOrder?.items); + if (!activeOrder) { api.order().createFoodOrder(business, consumer!, [orderItem], currentPlace ?? null); track('consumer created food order in database'); @@ -192,11 +222,12 @@ export const ItemDetail = ({ navigation, route }: Props) => { const updatedOrder = !itemId ? helpers.addItemToOrder(activeOrder, orderItem) : quantity > 0 - ? helpers.updateItem(activeOrder, orderItem) - : helpers.removeItem(activeOrder, orderItem); + ? helpers.updateItem(activeOrder, orderItem) + : helpers.removeItem(activeOrder, orderItem); api.order().updateOrder(activeOrder.id, updatedOrder); track('consumer updated items in order'); } + navigation.pop(); })(); }; @@ -357,11 +388,17 @@ export const ItemDetail = ({ navigation, route }: Props) => { title={`${t('Adicionar')} ${formatCurrency(helpers.getItemTotal(orderItem!))}`} disabled={!canAddItemToOrder} onChange={(value) => setQuantity(value)} - onSubmit={updateOrder} + onSubmit={handleAddItemToOrder} /> ) : null} + setModalVisible(false)} + positiveAnswer={updateOrder} + negativeAnswer={() => setModalVisible(false)} + /> ); }; diff --git a/consumer/v2/food/restaurant/product/LocationDistantFromDestinationModal.tsx b/consumer/v2/food/restaurant/product/LocationDistantFromDestinationModal.tsx new file mode 100644 index 000000000..7b027ac57 --- /dev/null +++ b/consumer/v2/food/restaurant/product/LocationDistantFromDestinationModal.tsx @@ -0,0 +1,56 @@ +import { MaterialIcons } from '@expo/vector-icons'; +import React from 'react'; +import { Modal, Text, TouchableOpacity, View } from 'react-native'; +import DefaultButton from '../../../../../common/components/buttons/DefaultButton'; +import PaddedView from '../../../../../common/components/containers/PaddedView'; +import { borders, colors, halfPadding, padding, texts } from '../../../../../common/styles'; +import { t } from '../../../../../strings'; + +type Props = { + modalVisible: boolean; + onModalClose: () => void; + positiveAnswer: () => void; + negativeAnswer: () => void; +}; + +export const LocationDistantFromDestinationModal = ({ + modalVisible, + onModalClose, + positiveAnswer, + negativeAnswer, +}: Props) => { + return ( + + + + + + + + + + + + {t('Seu endereço de entrega não bate com a sua localização.')} + + + {t('Você quer continuar mesmo assim?')} + + + + + + + ); +}; diff --git a/consumer/v2/food/restaurant/useBusinessIsAcceptingOrders.ts b/consumer/v2/food/restaurant/useBusinessIsAcceptingOrders.ts index f81baa111..a42ac7916 100644 --- a/consumer/v2/food/restaurant/useBusinessIsAcceptingOrders.ts +++ b/consumer/v2/food/restaurant/useBusinessIsAcceptingOrders.ts @@ -5,6 +5,7 @@ import { useContextGetSeverTime } from '../../../../common/contexts/ServerTimeCo export const useBusinessIsAcceptingOrders = (business?: Business) => { const platformParams = usePlatformParamsContext(); const getServerTime = useContextGetSeverTime(); + if (!platformParams) return false; if (!getServerTime) return false; if (!business) return false;