import React, { useEffect, useState } from 'react'
import { View, StyleSheet, BackHandler, Alert, Keyboard } from 'react-native'
import Spinner from 'react-native-loading-spinner-overlay'
import { useForm, Controller } from 'react-hook-form'
import {
useLanguage,
OrderDetails as OrderDetailsConTableoller,
useUtils,
useApi,
useSession,
useToast,
ToastType,
useConfig
} from 'ordering-components/native'
import { PhoneInputNumber } from '../PhoneInputNumber'
import {
OSOrderDetailsWrapper,
OSTable,
OSActions,
OSInputWrapper,
SentReceipt,
Table,
OrderBill,
Total,
OSRow,
} from './styles'
import { OrderDetailsParams, Product } from '../../types'
import { Container } from '../../layouts/Container';
import NavBar from '../../components/NavBar';
import { OButton, OIconButton, OImage, OInput, OText } from '../../components/shared';
import GridContainer from '../../layouts/GridContainer';
import OptionSwitch, { Opt } from '../../components/shared/OOptionToggle';
import { verifyDecimals } from '../../../../../src/utils'
import { LANDSCAPE, PORTRAIT, useDeviceOrientation } from '../../../../../src/hooks/DeviceOrientation'
import { useTheme } from 'styled-components/native'
import { _retrieveStoreData, _setStoreData } from '../../../../../src/providers/StoreUtil';
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'
import EvilIcons from 'react-native-vector-icons/EvilIcons'
const _EMAIL = 'email';
const _SMS = 'sms';
export const OrderDetailsUI = (props: OrderDetailsParams) => {
const { navigation, isFromCheckout } = props;
const theme = useTheme();
const [, t] = useLanguage()
const [ordering] = useApi()
const [, { showToast }] = useToast()
const [{ parsePrice, parseNumber }] = useUtils()
const [orientationState] = useDeviceOrientation()
const [{ token }] = useSession()
const [{ configs }] = useConfig()
const { control, handleSubmit, errors } = useForm();
const [customerName, setCustomerName] = useState(null)
const [countReceipts, setCountReceipts] = useState(5)
const [isLoading, setIsLoading] = useState(false)
const [phoneInputData, setPhoneInputData] = useState({
error: '',
phone: {
country_phone_code: null,
cellphone: null,
},
});
const { order } = props.order;
const isTaxIncluded = order?.tax_type === 1
const styles = StyleSheet.create({
inputsStyle: {
borderColor: theme.colors.disabled,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 8,
borderTopRightRadius: 0,
borderTopLeftRadius: 8,
flex: 1,
height: 52
},
buttonApplyStyle: {
borderBottomRightRadius: 8,
borderBottomLeftRadius: 0,
borderTopRightRadius: 8,
borderTopLeftRadius: 0,
},
textButtonApplyStyle: {
color: theme.colors.primary,
marginLeft: 0,
marginRight: 0
},
disabledTextButtonApplyStyle: {
color: theme.colors.white,
marginLeft: 0,
marginRight: 0
},
textBold: {
fontWeight: 'bold'
},
});
const optionsToSendReceipt: Opt[] = [
{
key: _EMAIL,
label: t('EMAIL', 'Email'),
value: _EMAIL,
isDefault: true,
},
{
key: _SMS,
label: t('SMS', 'SMS'),
value: _SMS,
},
];
const [optionToSendReceipt, setOptionToSendReceipt] = useState(
optionsToSendReceipt?.find(o => o?.isDefault),
);
const handleArrowBack: any = () => {
if (!isFromCheckout) {
navigation?.canGoBack() && navigation.goBack();
return
}
navigation.navigate('BottomTab');
}
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', handleArrowBack);
return () => {
BackHandler.removeEventListener('hardwareBackPress', handleArrowBack);
}
}, [])
const handleChangeInputEmail = (value: string, onChange: any) => {
onChange(value.toLowerCase().replace(/[&,()%";:รง?<>{}\\[\]\s]/g, ''));
};
const onSubmit = async (values: any) => {
Keyboard.dismiss();
if (countReceipts <= 0) {
showToast(ToastType.Error, t('MAXIMUM_RECEIPTS_SEND_EXCEEDED', 'The maximum receipts sent has been exceeded'))
return
}
if (phoneInputData.error) {
showToast(ToastType.Error, phoneInputData.error);
return;
}
setIsLoading(true)
let body
if (optionToSendReceipt?.value === _EMAIL) {
body = {
channel: 1,
email: values.email,
name: customerName
}
}
else if (optionToSendReceipt?.value === _SMS) {
body = {
channel: 2,
cellphone: phoneInputData?.phone?.cellphone,
country_phone_code: phoneInputData?.phone?.country_phone_code,
name: customerName
}
}
try {
const response = await fetch(`${ordering.root}/orders/${order.id}/receipt`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
body: JSON.stringify(body),
})
const { error, result } = await response.json()
if (error) {
showToast(ToastType.Error, result)
} else {
showToast(ToastType.Success, t('RECEIPT_SEND_SUCCESSFULLY', 'Receipt send successfully'))
setCountReceipts(countReceipts - 1)
}
} catch (error: any) {
showToast(ToastType.Error, error.message)
}
setIsLoading(false)
}
const getIncludedTaxes = () => {
if (order?.taxes?.length === 0) {
return order.tax_type === 1 ? order?.summary?.tax ?? 0 : 0
} else {
return order?.taxes.reduce((taxIncluded: number, tax: any) => {
return taxIncluded + (tax.type === 1 ? tax.summary?.tax : 0)
}, 0)
}
}
const getIncludedTaxesDiscounts = () => {
return order?.taxes?.filter((tax: any) => tax?.type === 1)?.reduce((carry: number, tax: any) => carry + (tax?.summary?.tax_after_discount ?? tax?.summary?.tax), 0)
}
useEffect(() => {
const backAction = () => {
Alert.alert(`${t('HOLD_ON', 'Hold on')}!`, `${t('ARE_YOU_SURE_YOU_WANT_TO_GO_BACK', 'Are you sure you want to go back')}?`, [
{
text: t('CANCEL', 'cancel'),
onPress: () => null,
style: "cancel"
},
{
text: t('YES', 'yes'), onPress: () => {
navigation.reset({
routes: [{ name: 'Intro' }]
});
}
}
]);
return true;
};
const backHandler = BackHandler.addEventListener(
"hardwareBackPress",
backAction
);
return () => backHandler.remove();
}, []);
useEffect(() => {
const getCustomerName = async () => {
try {
const { customerName: name } = await _retrieveStoreData('customer_name')
setCustomerName(name)
} catch (e) {
if (e) {
setCustomerName(null)
}
}
}
getCustomerName()
const redirectHome = setTimeout(() => {
_setStoreData('customer_name', { customerName: '' });
navigation.reset({
routes: [{ name: 'Intro' }],
});
}, 60000);
return () => {
clearTimeout(redirectHome);
}
}, [])
useEffect(() => {
if (Object.keys(errors).length > 0) {
// Convert all errors in one string to show in toast provider
const list = Object.values(errors);
let stringError = '';
if (phoneInputData.error) {
list.unshift({ message: phoneInputData.error });
}
if (
optionToSendReceipt?.value === _SMS &&
!phoneInputData.error &&
!phoneInputData.phone.country_phone_code &&
!phoneInputData.phone.cellphone
) {
list.unshift({
message: t(
'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
'The field Mobile phone is required.',
),
});
}
list.map((item: any, i: number) => {
stringError +=
i + 1 === list.length ? `- ${item.message}` : `- ${item.message}\n`;
});
showToast(ToastType.Error, stringError);
}
}, [errors]);
const actionsContent = (
{t('SEND_RECEIPT', 'Send receipt')}
{countReceipts}/5 {t('RECIPTS_REMAINING', 'Recipts remaining')}
{/* */}
{optionToSendReceipt?.value === _EMAIL && (
(
handleChangeInputEmail(e, onChange)}
style={styles.inputsStyle}
value={value}
autoCapitalize="none"
autoCorrect={false}
returnKeyType="done"
onSubmitEditing={handleSubmit(onSubmit)}
blurOnSubmit
type="email-address"
/>
)}
name="email"
rules={{
required: t(
'VALIDATION_ERROR_EMAIL_REQUIRED',
'The field Email is required',
).replace('_attribute_', t('EMAIL', 'Email')),
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: t(
'INVALID_ERROR_EMAIL',
'Invalid email address',
).replace('_attribute_', t('EMAIL', 'Email')),
},
}}
defaultValue=""
/>
)}
{optionToSendReceipt?.value === _SMS && (
setPhoneInputData(val)}
textInputProps={{
returnKeyType: 'done',
onSubmitEditing: handleSubmit(onSubmit),
}}
/>
)}
{
_setStoreData('customer_name', { customerName: '' });
navigation.reset({
routes: [{ name: 'Intro' }],
});
}}
/>
);
const orderDetailsContent = (
{t('ORDER_NUMBER', 'Order No.')} {' '}
{order?.id}
{order?.products?.length > 0 && (
<>
{`${order?.products?.length} ${t('ITEMS', 'items')}`}
{parsePrice((order?.summary?.total || order?.total) - (order?.summary?.discount || order?.discount))}
{order?.products.map((product: Product, i: number) => (
))}
>
)}
{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)}%)`}
)}
- {parsePrice(offer?.summary?.discount)}
))
}
{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).map((tax: any) => (
{tax.name || t('INHERIT_FROM_BUSINESS', 'Inherit from business')}
{`(${verifyDecimals(tax?.rate, parseNumber)}%)`}{' '}
{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) => (
{fee.name || t('INHERIT_FROM_BUSINESS', 'Inherit from business')}
({fee?.fixed > 0 && `${parsePrice(fee?.fixed)}${fee.percentage > 0 ? ' + ' : ''}`}{fee.percentage > 0 && `${fee.percentage}%`}){' '}
{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)}%)`}
)}
- {parsePrice(offer?.summary?.discount)}
))
}
{order?.summary?.delivery_price > 0 && (
{t('DELIVERY_FEE', 'Delivery Fee')}
{parsePrice(order?.summary?.delivery_price)}
)}
{
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)}%)`}
)}
- {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)}
);
return (
<>
{!!order && Object.keys(order).length > 0 && (
<>
}
style={{ flex: 1, justifyContent: 'flex-end', left: 30 }}
onClick={() => {
navigation.reset({
routes: [{ name: 'Intro' }],
});
}}
/>
}
/>
{orderDetailsContent}
{t('WE_KNOW_YOU_ARE', 'We know you are')} {'\n'}
{t('HUNGRY', 'hungry')}{!!customerName && `, ${customerName}`}
{t('TO_FINISH_TAKE_YOUR_RECEIPT_AND_GO_TO_THE_FRONT_COUNTER', "We`ve received your order and we will call you by your name or your order number.")}
{orientationState?.orientation === LANDSCAPE && actionsContent}
{orientationState?.orientation === PORTRAIT && (
{actionsContent}
)}
>
)}
>
)
}
export const OrderDetails = (props: OrderDetailsParams) => {
const orderDetailsProps = {
...props,
UIComponent: OrderDetailsUI
}
return (
)
}