import React, { useState, useEffect } from 'react'; import moment from 'moment'; import CalendarStrip from 'react-native-calendar-strip' import { useLanguage, useConfig, useUtils, useOrder, MomentOption as MomentOptionController, } from 'ordering-components/native'; import { useTheme } from 'styled-components/native'; import IconAntDesign from 'react-native-vector-icons/AntDesign' import { StyleSheet, View, Platform, Pressable } from 'react-native'; import Spinner from 'react-native-loading-spinner-overlay'; import { MomentOptionParams } from '../../types'; import NavBar from '../NavBar'; import { OButton, OIcon, OText } from '../shared'; import { Container } from '../../layouts/Container'; import { WrapSelectOption, OrderTimeWrapper, TimeListWrapper, TimeContentWrapper, TimeItem } from './styles'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { monthsEnum, setLocalMoment } from '../../utils'; import { TimeListItem } from './TimeListItem'; const MomentOptionUI = (props: MomentOptionParams) => { const { navigation, datesList, hoursList, dateSelected, timeSelected, cateringPreorder, isCart, preorderLeadTime, business, getActualSchedule, preorderMaximumDays, preorderMinimumDays, isPage, handleAsap, handleChangeDate, handleChangeTime, } = props; const theme = useTheme(); const styles = StyleSheet.create({ icon: { marginRight: 10, }, dayNameStyle: { textTransform: 'uppercase', }, selectStyle: { zIndex: 10, }, dateLabel: { borderWidth: 1, borderColor: theme.colors.border, borderRadius: 7.6, paddingHorizontal: 12, paddingVertical: 9, marginBottom: 12, }, dateWrap: { marginTop: 40, borderRadius: 7.6, borderColor: theme.colors.border, borderWidth: 1, padding: 17, marginBottom: 23, }, timeLabel: { borderWidth: 1, borderColor: theme.colors.border, borderRadius: 7.6, height: 44, paddingHorizontal: 16, flexDirection: 'row', alignItems: 'center' }, calendar: { paddingBottom: 15, borderBottomWidth: 1, borderColor: theme.colors.backgroundGray200, height: 100 }, calendarHeaderContainer: { flex: 1, justifyContent: 'flex-start', textAlign: 'left', marginBottom: 17, borderBottomWidth: 1, borderColor: theme.colors.backgroundGray200 }, calendarHeader: { color: '#344050', alignSelf: 'flex-start', fontSize: 14, fontWeight: '400' }, dateNumber: { color: '#B1BCCC', fontSize: 16, fontWeight: '500', }, dateName: { color: '#B1BCCC', fontSize: 12, textTransform: 'capitalize', }, highlightDateName: { color: '#344050', fontSize: 12, textTransform: 'capitalize', }, highlightDateNumber: { color: '#344050', fontSize: 16, textTransform: 'capitalize', }, disabledDateName: { color: '#B1BCCC', fontSize: 10, textTransform: 'capitalize', opacity: 1, }, disabledDateNumber: { color: '#B1BCCC', fontSize: 14, fontWeight: '500' } }); const [, t] = useLanguage(); const [{ configs }] = useConfig(); const [{ parseTime }] = useUtils() const [orderState] = useOrder(); const [optionSelected, setOptionSelected] = useState({ isAsap: false, isSchedule: false, }); const [momentState, setMomentState] = useState({ isLoading: 0, isEditing: false, }); const { bottom } = useSafeAreaInsets(); const is12hours = configs?.general_hour_format?.value?.includes('hh:mm') const [selectedTime, setSelectedTime] = useState(null); const [datesWhitelist, setDateWhitelist] = useState([{ start: null, end: null }]) const [selectDate, setSelectedDate] = useState(dateSelected) const [timeList, setTimeList] = useState(hoursList) const [nextTime, setNextTime] = useState(null) const [isEnabled, setIsEnabled] = useState(false) const goToBack = () => navigation?.canGoBack() && navigation.goBack(); const _handleAsap = () => { setMomentState({ isLoading: 1, isEditing: true }); handleAsap(); setOptionSelected({ isAsap: true, isSchedule: false }); if (!orderState.options?.moment) { setMomentState({ isLoading: 2, isEditing: false }); } }; const handleChangeMoment = (time?: any) => { setMomentState({ isLoading: 1, isEditing: true }); handleChangeTime(time ?? selectedTime); }; const validateSelectedDate = (curdate: any, menu: any) => { const day = moment(curdate).format('d') setIsEnabled(menu?.schedule?.[day]?.enabled || false) } const getTimes = (curdate: any, menu: any) => { validateSelectedDate(curdate, menu) const date = new Date() var dateSeleted = new Date(curdate) var times = [] for (var k = 0; k < menu.schedule[dateSeleted.getDay()].lapses.length; k++) { var open = { hour: menu.schedule[dateSeleted.getDay()].lapses[k].open.hour, minute: menu.schedule[dateSeleted.getDay()].lapses[k].open.minute } var close = { hour: menu.schedule[dateSeleted.getDay()].lapses[k].close.hour, minute: menu.schedule[dateSeleted.getDay()].lapses[k].close.minute } for (var i = open.hour; i <= close.hour; i++) { if (date.getDate() !== dateSeleted.getDate() || i >= date.getHours()) { let hour = '' let meridian = '' if (is12hours) { if (i === 0) { hour = '12' meridian = ' ' + t('AM', 'AM') } else if (i > 0 && i < 12) { hour = (i < 10 ? '0' + i : i) meridian = ' ' + t('AM', 'AM') } else if (i === 12) { hour = '12' meridian = ' ' + t('PM', 'PM') } else { hour = ((i - 12 < 10) ? '0' + (i - 12) : `${(i - 12)}`) meridian = ' ' + t('PM', 'PM') } } else { hour = i < 10 ? '0' + i : i } for (let j = (i === open.hour ? open.minute : 0); j <= (i === close.hour ? close.minute : 59); j += 15) { if (i !== date.getHours() || j >= date.getMinutes() || date.getDate() !== dateSeleted.getDate()) { times.push({ text: hour + ':' + (j < 10 ? '0' + j : j) + meridian, value: (i < 10 ? '0' + i : i) + ':' + (j < 10 ? '0' + j : j) }) } } } } } return times } const momento = moment( `${dateSelected} ${timeSelected}`, 'YYYY-MM-DD HH:mm', ).toDate(); const momentUnix = momento.getTime() / 1000; const momentFormat = moment .unix(momentUnix) .utc() .format('YYYY-MM-DD HH:mm:ss'); useEffect(() => { if (orderState.options?.moment) { setOptionSelected({ isAsap: false, isSchedule: true }); } else { setOptionSelected({ isAsap: true, isSchedule: false }); } if ( momentState.isEditing && (momentFormat === orderState.options?.moment || timeSelected === null) ) { setMomentState({ isLoading: 2, isEditing: false }); } }, [orderState.options?.moment]); useEffect(() => { if (momentState.isLoading === 2 && !orderState?.loading) { goToBack(); } }, [momentState.isLoading]); const onSelectDate = (val: any) => { setSelectedDate(val) if (handleChangeDate) handleChangeDate(moment(val).format('YYYY-MM-DD')) } const handleChangeTimeSelected = (time: any) => { if (cateringPreorder) { handleChangeMoment(time) } else { setSelectedTime(time) } } const LeftSelector = () => { return ( ) } const RightSelector = () => { return ( ) } useEffect(() => { if (datesList?.length > 0) { const _datesList = datesList.slice((cateringPreorder && preorderMinimumDays) || 0, Number(cateringPreorder ? preorderMaximumDays || configs?.max_days_preorder?.value : configs?.max_days_preorder?.value ?? 6)) if (_datesList?.length > 0) { const minDateParts = _datesList?.[0]?.split('-') const maxDateParts = _datesList[_datesList.length - 1].split('-') const _minDate = new Date(minDateParts[0], minDateParts[1] - 1, minDateParts[2]) const _maxDate = new Date(maxDateParts[0], maxDateParts[1] - 1, maxDateParts[2]) setDateWhitelist([{ start: _minDate, end: _maxDate }]) } } }, [JSON.stringify(datesList), preorderMinimumDays, preorderMaximumDays]) useEffect(() => { if (dateSelected) { const dateParts = dateSelected.split('-') const _dateSelected = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]) setSelectedDate(_dateSelected) if (cateringPreorder) { onSelectDate(_dateSelected) } } }, [dateSelected]) useEffect(() => { setSelectedTime(timeSelected) }, [timeSelected]) useEffect(() => { if (cateringPreorder) { let _timeLists = [] const schedule = business && getActualSchedule() if (!schedule && business) { setTimeList([]) return } _timeLists = hoursList .filter(hour => { return (Object.keys(business || {})?.length === 0 || schedule?.lapses?.some((lapse: any) => { const openHour = lapse.open.hour < 10 ? `0${lapse.open.hour}` : lapse.open.hour const openMinute = lapse.open.minute < 10 ? `0${lapse.open.minute}` : lapse.open.minute const closeHour = lapse.close.hour < 10 ? `0${lapse.close.hour}` : lapse.close.hour const closeMinute = lapse.close.minute < 10 ? `0${lapse.close.minute}` : lapse.close.minute return moment(dateSelected + ` ${hour.startTime}`) >= moment(dateSelected + ` ${openHour}:${openMinute}`).add(preorderLeadTime, 'minutes') && moment(dateSelected + ` ${hour.endTime}`) <= moment(dateSelected + ` ${closeHour}:${closeMinute}`) })) && (moment(dateSelected + ` ${hour.startTime}`) < moment(dateSelected + ` ${hour.endTime}`)) && (moment().add(preorderLeadTime, 'minutes') < moment(dateSelected + ` ${hour.startTime}`) || !cateringPreorder) }) .map(hour => { return { value: hour.startTime, text: is12hours ? ( hour.startTime.includes('12') ? `${hour.startTime}PM` : parseTime(moment(hour.startTime, 'HH:mm'), { outputFormat: 'hh:mma' }) ) : ( parseTime(moment(hour.startTime, 'HH:mm'), { outputFormat: 'HH:mm' }) ), endText: is12hours ? ( hour.endTime.includes('12') ? `${hour.endTime}PM` : parseTime(moment(hour.endTime, 'HH:mm'), { outputFormat: 'hh:mma' }) ) : ( parseTime(moment(hour.endTime, 'HH:mm'), { outputFormat: 'HH:mm' }) ) } }) if (_timeLists?.length > 0) { setTimeList(_timeLists) } } else { let _times: any = [] if (business) { _times = getTimes(selectDate, business) } else { _times = hoursList.map(hour => { return { value: hour.startTime, text: is12hours ? ( hour.startTime.includes('12') ? `${hour.startTime}PM` : parseTime(moment(hour.startTime, 'HH:mm'), { outputFormat: 'hh:mma' }) ) : ( parseTime(moment(hour.startTime, 'HH:mm'), { outputFormat: 'HH:mm' }) ) } }) setIsEnabled(true) } setTimeList(_times) } }, [dateSelected, hoursList?.length, JSON.stringify(datesWhitelist), JSON.stringify(business)]) useEffect(() => { setLocalMoment(moment, t) }, []) useEffect(() => { if (preorderMinimumDays === 0 && preorderLeadTime === 0) return const isToday = dateSelected === moment().format('YYYY-MM-DD') if (isCart && isToday && !orderState?.loading && timeList?.length > 0) { setNextTime(timeList?.[0] ?? null) } }, [timeList?.length]) useEffect(() => { if (nextTime?.value && timeList?.length > 0 && isCart && !orderState?.loading && !(preorderMinimumDays === 0 && preorderLeadTime === 0)) { const notime = timeList?.filter((_: any, i: number) => i !== 0)?.find?.((time: any) => time?.value === timeSelected) if (!notime) { handleChangeTime(nextTime?.value) } } }, [nextTime?.value]) return ( <> {!isCart && ( goToBack()} btnStyle={{ paddingLeft: 0 }} style={{ paddingBottom: 0 }} paddingTop={Platform.OS === 'ios' ? 10 : 0} title={t('QUESTION_WHEN_ORDER', 'When do you want your order?')} titleAlign={'center'} titleStyle={{ fontSize: 20, marginRight: 0, marginLeft: 0 }} titleWrapStyle={{ paddingHorizontal: 0 }} /> )} {((preorderMinimumDays === 0 && preorderLeadTime === 0) || !cateringPreorder) && ( _handleAsap()} disabled={orderState.loading} style={{ alignItems: 'flex-start' }}> {optionSelected.isAsap ? ( ) : ( )} {t('ASAP_ABBREVIATION', 'ASAP') + ` (${t(moment().format('dddd')?.toLocaleUpperCase(), moment().format('dddd'))}, ${t(monthsEnum[moment().format('MMM')], moment().format('MMM'))}${moment().format(' D, yyyy h:mm A')} + ${t('DELIVERY_TIME', 'delivery time')})`} )} setOptionSelected({ isAsap: false, isSchedule: true })} disabled={orderState.loading}> {optionSelected.isSchedule ? ( ) : ( )} {t('SCHEDULE_FOR_LATER', 'Schedule for later')} {optionSelected.isSchedule && ( {datesWhitelist[0]?.start === datesWhitelist[0]?.end && ( {moment(selectDate).format('Do MMMM, YYYY')} )} {datesWhitelist[0]?.start !== datesWhitelist[0]?.end && ( {selectDate && datesWhitelist[0]?.start !== null && ( onSelectDate(date)} leftSelector={} rightSelector={} /> )} )} {isEnabled && timeList?.length > 0 ? ( {timeList.map((time: any, i: number) => ( ))} {timeList.length % 3 === 2 && ( )} ) : ( {t('ERROR_ADD_PRODUCT_BUSINESS_CLOSED', 'The business is closed at the moment')} )} )} {!isCart && !cateringPreorder && ( handleChangeMoment()} isDisabled={!selectedTime} text={t('CONTINUE', 'Continue')} style={{ borderRadius: 7.6, height: 44, shadowOpacity: 0 }} textStyle={{ fontSize: 14 }} showNextIcon /> )} ); }; export const MomentOption = (props: any) => { const momentOptionProps = { ...props, UIComponent: MomentOptionUI, }; return ; };