import React, { useState, useEffect, useMemo } from 'react'; import { View, StyleSheet, BackHandler, Platform, Linking, RefreshControl, SafeAreaView } from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; import IconAntDesign from 'react-native-vector-icons/AntDesign'; import { _setStoreData } from '../../providers/StoreUtil'; import { useLanguage, OrderDetails as OrderDetailsConTableoller, useUtils, useOrder, useConfig, useToast, ToastType } from 'ordering-components/native'; import { useTheme } from 'styled-components/native'; import { showLocation } from 'react-native-map-link'; import { OrderDetailsContainer, Header, OrderContent, OrderBusiness, OrderData, OrderInfo, StaturBar, OrderCustomer, InfoBlock, HeaderInfo, Customer, OrderProducts, Table, OrderBill, Total, Icons, OrderDriver, Map, Divider, OrderAction, PlaceSpotWrapper, ProfessionalPhoto, TopHeader, TopActions } from './styles'; import { OButton, OIcon, OModal, OText } from '../shared'; import { ProductItemAccordion } from '../ProductItemAccordion'; import { TouchableOpacity } from 'react-native-gesture-handler'; import { OrderDetailsParams } from '../../types'; import { GoogleMap } from '../GoogleMap'; import { verifyDecimals, getOrderStatus, getOrderStatuPickUp } from '../../utils'; import { OSRow } from '../OrderSummary/styles'; import AntIcon from 'react-native-vector-icons/AntDesign' import { TaxInformation } from '../TaxInformation'; import { Placeholder, PlaceholderLine } from 'rn-placeholder'; import NavBar from '../NavBar' import { OrderHistory } from './OrderHistory'; import { PlaceSpot } from '../PlaceSpot' import { SendGiftCard } from '../GiftCard/SendGiftCard' import { OrderEta } from './OrderEta' export const OrderDetailsUI = (props: OrderDetailsParams) => { const { navigation, messages, setMessages, readMessages, isFromCheckout, driverLocation, onNavigationRedirect, reorderState, handleReorder, getOrder } = props; const theme = useTheme(); const [, { showToast }] = useToast() const styles = StyleSheet.create({ rowDirection: { flexDirection: 'row', }, statusBar: { height: 12, borderRadius: 8 }, logo: { width: 75, height: 75, borderRadius: 10, }, textBold: { fontWeight: 'bold', }, btnBackArrow: { borderWidth: 0, backgroundColor: theme.colors.clear, borderColor: theme.colors.clear, shadowColor: theme.colors.clear, alignItems: 'flex-start', justifyContent: 'flex-start', paddingLeft: 0, height: 30, width: 30, marginTop: Platform.OS === 'ios' ? 0 : 30 }, linkWrapper: { display: 'flex', alignItems: 'center', flexDirection: 'row' }, professionalBlock: { borderBottomColor: theme.colors.border, borderBottomWidth: 1, marginVertical: 10, paddingVertical: 5 }, wrapperNavbar: { paddingHorizontal: 20, paddingTop: 0, } }); const [, t] = useLanguage(); const [{ parsePrice, parseNumber, parseDate }] = useUtils(); const [{ configs }] = useConfig(); const [{ carts }] = useOrder() const [isReviewed, setIsReviewed] = useState(false) const [isGiftCardSent, setIsGiftCardSent] = useState(false) const [isOrderHistory, setIsOrderHistory] = useState(false) const [openTaxModal, setOpenTaxModal] = useState({ open: false, tax: null, type: '' }) const [refreshing] = useState(false); const [showTitle, setShowTitle] = useState(false) const { order, businessData } = props.order; const mapValidStatuses = [9, 18, 19, 23, 26] const placeSpotTypes = [3, 4, 5] const directionTypes = [2, 3, 4, 5] const activeStatus = [0, 3, 4, 7, 8, 9, 13, 14, 18, 19, 20, 21, 22, 23, 24, 25, 26] const reorderStatus = [1, 2, 5, 6, 10, 11, 12] const cateringTypes = [7, 8] const deliveryTypes = [1, 7] const [isPickup, setIsPickup] = useState(order?.delivery_type === 2) const enabledPoweredByOrdering = configs?.powered_by_ordering_module?.value const isGiftCardOrder = !order?.business_id const hideDeliveryDate = theme?.confirmation?.components?.order?.components?.date?.hidden const hideDeliveryProgress = theme?.confirmation?.components?.order?.components?.progress?.hidden const hideBusinessPhone = theme?.confirmation?.components?.business?.components?.phone?.hidden const hideBusinessMessages = theme?.confirmation?.components?.business?.components?.messages?.hidden const hideBusinessEmail = theme?.confirmation?.components?.business?.components?.email?.hidden const hideBusinessAddress = theme?.confirmation?.components?.business?.components?.address?.hidden const hideDriverName = theme?.confirmation?.components?.driver?.components?.name?.hidden const hideDriverPhone = theme?.confirmation?.components?.driver?.components?.phone?.hidden const hideDriverMessages = theme?.confirmation?.components?.driver?.components?.messages?.hidden const hideCustomerPhone = theme?.confirmation?.components?.customer?.components?.phone?.hidden const hideCustomerAddress = theme?.confirmation?.components?.customer?.components?.address?.hidden const changeIdToExternalId = configs?.change_order_id?.value === '1' const progressBarObjt = isPickup ? getOrderStatuPickUp : getOrderStatus const walletName: any = { cash: { name: t('PAY_WITH_CASH_WALLET', 'Pay with Cash Wallet'), }, credit_point: { name: t('PAY_WITH_CREDITS_POINTS_WALLET', 'Pay with Credit Points Wallet'), } } const handleGoToMessages = (type: string) => { readMessages && readMessages(); navigation.navigate( 'MessageDetails', { type, order, messages, setMessages, orderId: order?.id, business: type === 'business', driver: type === 'driver', onClose: () => navigation?.canGoBack() ? navigation.goBack() : navigation.navigate('BottomTab', { screen: 'MyOrders' }), } ) } const handleArrowBack: any = () => { if (!isFromCheckout) { navigation?.canGoBack() && navigation.goBack(); return; } navigation.navigate('BottomTab'); }; const getIncludedTaxes = (isDeliveryFee?: boolean) => { if (order?.taxes?.length === 0 || !order?.taxes) { return order.tax_type === 1 ? order?.summary?.tax ?? 0 : 0 } else { return order?.taxes.reduce((taxIncluded: number, tax: any) => { return taxIncluded + (((!isDeliveryFee && tax.type === 1 && tax.target === 'product') || (isDeliveryFee && tax.type === 1 && tax.target === 'delivery_fee')) ? tax.summary?.tax : 0) }, 0) } } const getIncludedTaxesDiscounts = () => { return order?.taxes?.filter((tax: any) => tax?.type === 1 && tax?.target === 'product')?.reduce((carry: number, tax: any) => carry + (tax?.summary?.tax_after_discount ?? tax?.summary?.tax), 0) } const handleClickOrderReview = (order: any) => { navigation.navigate( 'ReviewOrder', { order: { id: order?.id, business_id: order?.business_id, logo: order.business?.logo || theme.images.dummies.businessLogo, driver: order?.driver, products: order?.products, review: order?.review, user_review: order?.user_review }, setIsReviewed } ) } const handleTriggerReview = () => { setIsOrderHistory(false); ( parseInt(order?.status) === 1 || parseInt(order?.status) === 11 || parseInt(order?.status) === 15 ) && !order.review && !isReviewed && handleClickOrderReview(order) } const resfreshOrder = () => { getOrder() } const handleScroll = ({ nativeEvent: { contentOffset } }: any) => { setShowTitle(contentOffset.y > 30) } useEffect(() => { const _businessId = 'businessId:' + businessData?.id if (reorderState?.error) { if (businessData?.id) { _setStoreData('adjust-cart-products', JSON.stringify(_businessId)) navigation.navigate('Business', { store: businessData?.slug }) } } if (!reorderState?.error && reorderState.loading === false && businessData?.id) { const products = carts?.[_businessId]?.products const available = products?.every((product: any) => product.valid === true) if (available && reorderState?.result?.uuid && (products?.length === order?.products.length)) { onNavigationRedirect && onNavigationRedirect('CheckoutNavigator', { cartUuid: reorderState?.result.uuid }) } else { _setStoreData('adjust-cart-products', JSON.stringify(_businessId)) products?.length !== order?.products.length && _setStoreData('already-removed', JSON.stringify('removed')) navigation.navigate('Business', { store: businessData?.slug }) } } }, [reorderState]) useEffect(() => { BackHandler.addEventListener('hardwareBackPress', handleArrowBack); return () => { BackHandler.removeEventListener('hardwareBackPress', handleArrowBack); }; }, []); const locations = [ { ...order?.driver?.location, title: t('DRIVER', 'Driver'), icon: order?.driver?.photo || theme?.images?.general?.driverPng, }, { ...order?.business?.location, title: order?.business?.name, icon: order?.business?.logo || theme.images.dummies.businessLogo, }, { ...order?.customer?.location, title: t('YOUR_LOCATION', 'Your Location'), icon: order?.customer?.photo || 'https://res.cloudinary.com/demo/image/upload/c_thumb,g_face,r_max/d_avatar.png/non_existing_id.png', }, ]; const driverLocationString = typeof order?.driver?.location?.location === 'string' && order?.driver?.location?.location?.split(',').map((l: string) => l.replace(/[^-.0-9]/g, '')) const parsedLocations = locations.map(location => typeof location?.location === 'string' ? { ...location, lat: parseFloat(location?.location?.split(',')[0].replace(/[^-.0-9]/g, '')), lng: parseFloat(location?.location?.split(',')[1].replace(/[^-.0-9]/g, '')) } : location) const getProductList = () => { const professionalList = order?.products.reduce((prev: any, current: any) => { const found = prev.find((item: any) => item.id === current?.calendar_event?.professional?.id) if (found || !current?.calendar_event) { return prev } return [...prev, current?.calendar_event?.professional] }, []) return ( <> {professionalList?.length > 0 && professionalList.map((professional: any, i: number) => ( {professional?.photo ? ( ) : ( )} {professional?.name} {professional?.lastname} {order?.products.filter((product: any) => product?.calendar_event?.professional?.id === professional?.id).map((product: any, i: number) => ( ))} ))} {order?.products.filter((product: any) => !product?.calendar_event).map((product: any, i: number) => ( ))} ) } const sortedProductList = useMemo(() => getProductList(), [order?.products]) useEffect(() => { if (driverLocation) { parsedLocations[0] = { ...locations[0], ...driverLocation } } }, [driverLocation]); useEffect(() => { if (props?.order?.error && !props?.order?.loading) { showToast(ToastType.Error, props?.order?.error) navigation.navigate('BusinessList') } }, [props?.order?.error, props?.order?.loading]) useEffect(() => { if (!order?.delivery_type) return setIsPickup(order?.delivery_type === 2) }, [order?.delivery_type]) return ( <> <> handleArrowBack()}> {showTitle && ( {`${t('ORDER', 'Order')} ${(changeIdToExternalId && order?.external_id) || `#${order?.id}`}`} )} resfreshOrder()} /> } onScroll={handleScroll} > {(!order || Object.keys(order).length === 0) && (
)} {order && Object.keys(order).length > 0 && ( <>
{activeStatus.includes(order?.status) ? ( <> {cateringTypes.includes(order?.delivery_type) ? `${t('CREATED_AT', 'Created at')}: ${parseDate(order?.created_at)}\n` : ''} {cateringTypes.includes(order?.delivery_type) ? `${t('PLACED_TO', 'Placed to')}:` : ''} ) : ( parseDate(order?.reporting_data?.at[`status:${order.status}`], { outputFormat: `YYYY-MM-DD ${configs?.general_hour_format?.value}` }) )} } /> {enabledPoweredByOrdering && ( Powered By Ordering.co )} {!isGiftCardOrder && ( { ( parseInt(order?.status) === 1 || parseInt(order?.status) === 11 || parseInt(order?.status) === 15 ) && !order.review && !isReviewed && ( handleClickOrderReview(order)} > {t('REVIEW_YOUR_ORDER', 'Review your order')} )} setIsOrderHistory(true)} > {t('VIEW_DETAILS', 'View Details')} {!hideDeliveryProgress && ( <> {progressBarObjt(order?.status, t)?.value} )} )}
{!isGiftCardOrder && ( {t('FROM', 'From')} {order?.business?.name} {!!order?.business?.cellphone && !hideBusinessPhone && ( order?.business?.cellphone && Linking.openURL(`tel:${order?.business?.cellphone}`) } style={{ paddingEnd: 5 }} > )} {!hideBusinessMessages && ( handleGoToMessages('business')}> )} {!hideBusinessEmail && ( {order?.business?.email} )} {!!order?.business?.cellphone && !hideBusinessPhone && ( {order?.business?.cellphone} )} {!hideBusinessAddress && ( {order?.business?.address} )} {directionTypes.includes(order?.delivery_type) && ( showLocation({ latitude: order?.business?.location?.lat, longitude: order?.business?.location?.lng, naverCallerName: 'com.reactnativeappstemplate5', dialogTitle: t('GET_DIRECTIONS', 'Get Directions'), dialogMessage: t('WHAT_APP_WOULD_YOU_USE', 'What app would you like to use?'), cancelText: t('CANCEL', 'Cancel'), })} /> )} )} {!isGiftCardOrder && placeSpotTypes.includes(order?.delivery_type) && ( )} {isGiftCardOrder ? t('CUSTOMER', 'Customer') : t('TO', 'To')} {order?.customer?.name} {order?.customer?.lastname} {!hideCustomerAddress && ( {order?.customer?.address} )} {(!!(order?.customer?.cellphone || order?.customer?.guest_cellphone) && !hideCustomerPhone) && ( {`${!!order?.customer?.country_phone_code ? '+' + order?.customer?.country_phone_code : ''} ${order?.customer?.guest_id ? order?.customer?.guest_cellphone : order?.customer?.cellphone}`} )} {!isGiftCardOrder && order?.delivery_option !== undefined && deliveryTypes?.includes?.(order?.delivery_type) && ( {t('DELIVERY_PREFERENCE', 'Delivery Preference')} {order?.delivery_option?.name ? t(order?.delivery_option?.name.toUpperCase().replace(/\s/g, '_')) : t('EITHER_WAY', 'Either way')} )} {!!order?.comment && ( {t('COMMENT', 'Comment')} {order?.comment} )} {order?.driver && ( <> {order?.driver?.location && mapValidStatuses.includes(parseInt(order?.status)) && ( )} )} {order?.driver && ( <> {t('YOUR_DRIVER', 'Your Driver')} {!hideDriverName && ( {order?.driver?.name} {order?.driver?.lastname} )} {!hideDriverMessages && ( handleGoToMessages('driver')}> )} {!hideDriverPhone && ( {order?.driver?.cellphone} )} )} {t( 'YOUR_ORDER_HAS_BEEN_RECEIVED', 'Your Order has been received', )} {t( 'ORDER_MESSAGE_HEADER_TEXT', 'Once business accepts your order, we will send you an email, thank you!', )} navigation.navigate('BottomTab', { screen: 'MyOrders' })} /> {(reorderStatus?.includes(parseInt(order?.status)) && order?.cart) && !isGiftCardOrder && ( handleReorder && handleReorder(order.id)} /> )} {sortedProductList} {t('SUBTOTAL', 'Subtotal')} {parsePrice(((order?.summary?.subtotal ?? order?.subtotal) + getIncludedTaxes()))}
{(order?.summary?.discount > 0 ?? order?.discount > 0) && order?.offers?.length === 0 && ( {order?.offer_type === 1 ? ( {t('DISCOUNT', 'Discount')} {`(${verifyDecimals( order?.offer_rate, parsePrice, )}%)`} ) : ( {t('DISCOUNT', 'Discount')} )} - {parsePrice(order?.summary?.discount || order?.discount)}
)} { order?.offers?.length > 0 && order?.offers?.filter((offer: any) => offer?.target === 1)?.map((offer: any) => ( {offer.name} {offer.rate_type === 1 && ( {`(${verifyDecimals(offer?.rate, parsePrice)}%)`} )} setOpenTaxModal({ open: true, data: offer, type: 'offer_target_1' })}> - {parsePrice(offer?.summary?.discount)}
)) } {!isGiftCardOrder && ( )} {order?.summary?.subtotal_with_discount > 0 && order?.summary?.discount > 0 && order?.summary?.total >= 0 && ( {t('SUBTOTAL_WITH_DISCOUNT', 'Subtotal with discount')} {order?.tax_type === 1 ? ( {parsePrice((order?.summary?.subtotal_with_discount + getIncludedTaxesDiscounts() ?? 0))} ) : ( {parsePrice(order?.summary?.subtotal_with_discount ?? 0)} )}
)} { order?.taxes?.length === 0 && order?.tax_type === 2 && ( {t('TAX', 'Tax')} {`(${verifyDecimals(order?.tax, parseNumber)}%)`} {parsePrice(order?.summary?.tax || 0)}
) } { order?.fees?.length === 0 && ( {t('SERVICE_FEE', 'Service fee')} {`(${verifyDecimals(order?.service_fee, parseNumber)}%)`} {parsePrice(order?.summary?.service_fee || 0)}
) } { order?.taxes?.length > 0 && order?.taxes?.filter((tax: any) => tax?.type === 2 && tax?.rate !== 0 && tax?.target === 'product').map((tax: any) => ( {tax.name || t('INHERIT_FROM_BUSINESS', 'Inherit from business')} {`(${verifyDecimals(tax?.rate, parseNumber)}%)`}{' '} setOpenTaxModal({ open: true, data: tax, type: 'tax' })}> {parsePrice(tax?.summary?.tax_after_discount ?? tax?.summary?.tax ?? 0)}
)) } { order?.fees?.length > 0 && order?.fees?.filter((fee: any) => !(fee.fixed === 0 && fee.percentage === 0))?.map((fee: any) => ( {t(fee.name?.toUpperCase()?.replace(/ /g, '_'), fee.name) || t('INHERIT_FROM_BUSINESS', 'Inherit from business')} ({fee?.fixed > 0 && `${parsePrice(fee?.fixed)}${fee.percentage > 0 ? ' + ' : ''}`}{fee.percentage > 0 && `${fee.percentage}%`}){' '} setOpenTaxModal({ open: true, data: fee, type: 'fee' })}> {parsePrice(fee?.summary?.fixed + (fee?.summary?.percentage_after_discount ?? fee?.summary?.percentage) ?? 0)}
)) } { order?.offers?.length > 0 && order?.offers?.filter((offer: any) => offer?.target === 3)?.map((offer: any) => ( {offer.name} {offer.rate_type === 1 && ( {`(${verifyDecimals(offer?.rate, parsePrice)}%)`} )} setOpenTaxModal({ open: true, data: offer, type: 'offer_target_3' })}> - {parsePrice(offer?.summary?.discount)}
)) } {typeof order?.summary?.delivery_price === 'number' && !isPickup && ( {t('DELIVERY_FEE', 'Delivery Fee')}{parsePrice(order?.summary?.delivery_price + getIncludedTaxes(true))}
)} { order?.taxes?.length > 0 && order?.taxes?.filter((tax: any) => tax?.type === 2 && tax?.rate !== 0 && tax?.target === 'delivery_fee').map((tax: any, i: number) => ( {t(tax?.name?.toUpperCase()?.replace(/ /g, '_'), tax?.name) || t('INHERIT_FROM_BUSINESS', 'Inherit from business')} {`(${verifyDecimals(tax?.rate, parseNumber)}%)`} {setOpenTaxModal && ( setOpenTaxModal({ open: true, data: tax, type: 'tax' })}> )} {parsePrice(tax?.summary?.tax_after_discount ?? tax?.summary?.tax ?? 0)}
)) } { order?.offers?.length > 0 && order?.offers?.filter((offer: any) => offer?.target === 2)?.map((offer: any) => ( {offer.name} {offer.rate_type === 1 && ( {`(${verifyDecimals(offer?.rate, parsePrice)}%)`} )} setOpenTaxModal({ open: true, data: offer, type: 'offer_target_2' })}> - {parsePrice(offer?.summary?.discount)}
)) } {order?.summary?.driver_tip > 0 && ( {t('DRIVER_TIP', 'Driver tip')} {order?.summary?.driver_tip > 0 && parseInt(configs?.driver_tip_type?.value, 10) === 2 && !parseInt(configs?.driver_tip_use_custom?.value, 10) && ( `(${verifyDecimals(order?.summary?.driver_tip, parseNumber)}%)` )} {parsePrice(order?.summary?.driver_tip ?? order?.totalDriverTip)}
)} {t('TOTAL', 'Total')} {parsePrice(order?.summary?.total ?? order?.total)}
{order?.payment_events?.length > 0 && ( {t('PAYMENTS', 'Payments')} {order?.payment_events?.map((event: any) => event.amount > 0 && ( {event?.wallet_event ? walletName[event?.wallet_event?.wallet?.type]?.name : t(event?.paymethod?.name.toUpperCase()?.replace(/ /g, '_'), event?.paymethod?.name)} {/* {event?.data?.charge_id && ( {`${t('CODE', 'Code')}: ${event?.data?.charge_id}`} )} */} -{parsePrice(event.amount, { isTruncable: true })} ))} )}
{isGiftCardOrder && order?.products[0]?.gift_card?.status === 'pending' && !isGiftCardSent && ( <> )}
)} setOpenTaxModal({ open: false, data: null, type: '' })} entireModal > setIsOrderHistory(false)} entireModal > setIsOrderHistory(false)} handleTriggerReview={handleTriggerReview} />
); }; export const OrderDetails = (props: OrderDetailsParams) => { const orderDetailsProps = { ...props, UIComponent: OrderDetailsUI, }; return ; };