':\r\n getAvailableOffersBySearch.length > 0\r\n ? bonusDealLink\r\n : earnCopySelection(loyaltyEarnThresholdNights, numberOfNights)\r\n };\r\n\r\n const nwithPointsCopy = {\r\n '': boldText,\r\n '': getAvailableOffersBySearch.length > 0 ? bonusDealLink : COPY.SELECT_SUITE\r\n };\r\n\r\n const textForMobileTest = {\r\n '': boldText,\r\n '': bonusDealLink\r\n };\r\n\r\n const copyToUse = getAvailableOffersBySearch.length > 0 ? COPY.YOU_HAVE_POINTS_BONUS_LINK : COPY.YOU_HAVE;\r\n\r\n const LoyaltyContainer = (\r\n \r\n \r\n \r\n \r\n {isMobile ? (\r\n <>\r\n \r\n {getAvailableOffersBySearch.length > 0\r\n ? COPY_FUNCTIONS.editCopyByReplaceWithMultipleComponent(copyToUse, textForMobileTest)\r\n : COPY_FUNCTIONS.editCopyByReplaceString(COPY.YOU_HAVE_POINTS, adventureBucks, '')}\r\n \r\n {adventureBucks === 0 ? (\r\n \r\n {earnCopySelection(loyaltyEarnThresholdNights, numberOfNights)}\r\n \r\n ) : (\r\n \r\n {COPY.SELECT_SUITE}\r\n \r\n )}\r\n >\r\n ) : (\r\n <>\r\n {adventureBucks === 0 ? (\r\n \r\n {COPY_FUNCTIONS.editCopyByReplaceWithMultipleComponent(copyToUse, noPointsCopy)}\r\n \r\n ) : (\r\n \r\n {COPY_FUNCTIONS.editCopyByReplaceWithMultipleComponent(copyToUse, nwithPointsCopy)}\r\n \r\n )}\r\n >\r\n )}\r\n \r\n \r\n \r\n );\r\n\r\n return <>{showLoyalty ? LoyaltyContainer : null}>;\r\n};\r\nLoyaltyAvailable.propTypes = {\r\n adventureBucks: PropTypes.number,\r\n iconLink: PropTypes.string,\r\n iconSize: PropTypes.string\r\n};\r\nLoyaltyAvailable.defaultProps = {\r\n adventureBucks: '153',\r\n iconLink: LOYALTY_IMAGES.ADVENTURE_BUCK_COIN\r\n};\r\n\r\nexport default connect(state => {\r\n return {\r\n showLoyalty: showLoyalty(state),\r\n getAvailableOffersBySearch: getAvailableOffersBySearch(state)\r\n };\r\n})(LoyaltyAvailable);\r\n\r\nfunction earnCopySelection(loyaltyEarnThresholdNights = 2, numberOfNights) {\r\n if (numberOfNights < loyaltyEarnThresholdNights) {\r\n return COPY_FUNCTIONS.editCopyByReplaceString(COPY.EARN_POINTS, loyaltyEarnThresholdNights, '');\r\n }\r\n return COPY.START_EARNING;\r\n}\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { connect } from 'react-redux';\r\nimport { getUserIsLoggedIn } from '../../../store/componentStores/Account/account.selectors';\r\nimport { showLoyalty } from '../../../store/reducers';\r\nimport { Box, Flex, Text } from '../../ui-kit';\r\nimport theme from '../../ui-kit/themes/theme';\r\nimport { editCopyByReplaceWithMultipleComponent } from '../../utilities/copyFunctions';\r\nimport { LOYALTY_IMAGES } from '../assets/images';\r\nimport { Icon, LoyaltyGenericContainer, TextBoldWithNormal } from '../assets/styles';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nconst LoyaltyAvailableMobileSearch = ({ amount, iconLink, showLoyalty, isUserLoggedIn, isNewWidgetStyleActive }) => {\r\n const loggedUserCopy = {\r\n '': amount\r\n };\r\n\r\n return showLoyalty && isUserLoggedIn ? (\r\n \r\n \r\n \r\n \r\n \r\n {editCopyByReplaceWithMultipleComponent(COPY.LOYALTY_USER_COPY, loggedUserCopy)}\r\n \r\n \r\n {COPY.AVAILABLE}\r\n \r\n \r\n \r\n \r\n ) : (\r\n \r\n {COPY.USER_COPY}\r\n \r\n );\r\n};\r\n\r\nLoyaltyAvailableMobileSearch.propTypes = {\r\n amount: PropTypes.number,\r\n iconLink: PropTypes.string\r\n};\r\nLoyaltyAvailableMobileSearch.defaultProps = {\r\n amount: '0',\r\n iconLink: LOYALTY_IMAGES.ADVENTURE_BUCK_COIN\r\n};\r\n\r\nexport default connect(state => {\r\n return {\r\n showLoyalty: showLoyalty(state),\r\n isUserLoggedIn: getUserIsLoggedIn(state.account)\r\n };\r\n})(LoyaltyAvailableMobileSearch);\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\n\r\nimport { Box, Flex, Text } from '../../ui-kit';\r\nimport theme from '../../ui-kit/themes/theme';\r\nimport { LOYALTY_IMAGES } from '../assets/images';\r\nimport { BookNowButton, Icon, LoyaltyWithExpirationDateContainer } from '../assets/styles';\r\n\r\nconst LoyaltyAvailableWithButton = ({ amount, iconLink }) => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n ${amount} Wolf Dollars\r\n \r\n \r\n \r\n Book now\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nLoyaltyAvailableWithButton.propTypes = {\r\n amount: PropTypes.number,\r\n iconLink: PropTypes.string\r\n};\r\nLoyaltyAvailableWithButton.defaultProps = {\r\n amount: '153',\r\n iconLink: LOYALTY_IMAGES.ADVENTURE_BUCK_COIN\r\n};\r\n\r\nexport default LoyaltyAvailableWithButton;\r\n","import PropTypes from 'prop-types';\r\nimport React, { useCallback } from 'react';\r\nimport { Box, Flex, Text } from '../../ui-kit';\r\nimport CarouselChevronRightIcon from '../../ui-kit/icons/CarouselChevronRigthThin';\r\nimport theme from '../../ui-kit/themes/theme';\r\nimport { LOYALTY_IMAGES } from '../assets/images';\r\nimport { Icon, LoyaltyAppliedContainer } from '../assets/styles';\r\nimport * as COPY from '../utilities/copy';\r\nimport { editCopyByReplaceString, editCopyByReplaceWithComponent } from './../../utilities/copyFunctions';\r\n\r\nconst calculatePointsToEarn = ({\r\n userOffers,\r\n activeOffers,\r\n pointsBalance,\r\n suitNightRate,\r\n currentSelectedPackages,\r\n pointsMultiplier\r\n}) => {\r\n let total = 0;\r\n\r\n // USE VOYAGERS POINTS\r\n let roomRateWithPoints = 0;\r\n if (!pointsBalance || pointsBalance === 0) {\r\n roomRateWithPoints = suitNightRate;\r\n } else {\r\n if (pointsBalance > suitNightRate) {\r\n roomRateWithPoints = 0;\r\n } else {\r\n roomRateWithPoints = suitNightRate - pointsBalance;\r\n }\r\n }\r\n\r\n // USE PACKAGES\r\n let packagesTotal = 0;\r\n\r\n if (currentSelectedPackages && currentSelectedPackages.length > 0) {\r\n currentSelectedPackages.forEach(currentPackage => {\r\n if (currentPackage.amount && currentPackage.quantity) {\r\n let calculateQuantityPrice = currentPackage.amount * currentPackage.quantity;\r\n packagesTotal = packagesTotal + calculateQuantityPrice;\r\n }\r\n });\r\n }\r\n\r\n // USE OFFERS\r\n let offersSavings = 0;\r\n if (userOffers && userOffers.length > 0) {\r\n offersSavings = userOffers.reduce((previousValue, currentValue) => {\r\n if (activeOffers.length > 0 && activeOffers.includes(currentValue.id)) {\r\n return previousValue + currentValue.dollarValue;\r\n } else {\r\n return previousValue;\r\n }\r\n }, 0);\r\n }\r\n\r\n // USE MULTIPLIER\r\n total = roomRateWithPoints + packagesTotal - offersSavings;\r\n let points = total * pointsMultiplier;\r\n return points.toFixed(0);\r\n};\r\n\r\nconst LoyaltyEarn = ({\r\n iconLink,\r\n numberOfNights,\r\n isUserAuthenticated,\r\n suitNightRate,\r\n pointsMultiplier,\r\n userOffers,\r\n activeOffers,\r\n currentSelectedPackages,\r\n pointsBalance,\r\n arrowVariation,\r\n loyaltyEarnThresholdNights = 2\r\n}) => {\r\n const points =\r\n suitNightRate && suitNightRate > 0\r\n ? calculatePointsToEarn({\r\n suitNightRate,\r\n pointsMultiplier,\r\n currentSelectedPackages,\r\n pointsBalance,\r\n userOffers,\r\n activeOffers\r\n })\r\n : 0;\r\n\r\n const openSignUp = useCallback(() => {\r\n if (!isUserAuthenticated && window.openSignUp) {\r\n window.openSignUp('sign-up-voyagers');\r\n }\r\n }, [isUserAuthenticated]);\r\n\r\n const pointsToEarn = () => {\r\n return {editCopyByReplaceString(COPY.NUMBER_POINTS, points, '')};\r\n };\r\n\r\n const voyagersPointsCopy = () => {\r\n return {COPY.VOYAGERS_POINTS};\r\n };\r\n\r\n const joinVoyagerUnderline = () => {\r\n return (\r\n \r\n {COPY.JOIN_VOYAGERS}\r\n \r\n );\r\n };\r\n\r\n return (\r\n \r\n \r\n \r\n {isUserAuthenticated && numberOfNights >= loyaltyEarnThresholdNights && (\r\n \r\n \r\n \r\n {editCopyByReplaceWithComponent(COPY.YOU_WILL_EARN, pointsToEarn(), '')}\r\n \r\n \r\n {COPY.POINTS_EARNED_UPPON_COMPLETION}\r\n \r\n \r\n {arrowVariation ? (\r\n \r\n \r\n \r\n ) : null}\r\n \r\n )}\r\n {isUserAuthenticated && numberOfNights < loyaltyEarnThresholdNights && (\r\n \r\n \r\n \r\n {editCopyByReplaceWithComponent(COPY.ADD_MORE_NIGHTS, voyagersPointsCopy(), '')}\r\n \r\n \r\n {COPY.POINTS_EARNED_UPPON_COMPLETION}\r\n \r\n \r\n {arrowVariation ? (\r\n \r\n \r\n \r\n ) : null}\r\n \r\n )}\r\n {!isUserAuthenticated && !arrowVariation && numberOfNights < loyaltyEarnThresholdNights && (\r\n <>\r\n \r\n \r\n {COPY.JOIN_VOYAGERS}\r\n \r\n {editCopyByReplaceWithComponent(COPY.JOIN_COPY, voyagersPointsCopy(), '')}\r\n \r\n >\r\n )}\r\n {!isUserAuthenticated && !arrowVariation && numberOfNights >= loyaltyEarnThresholdNights && (\r\n <>\r\n \r\n \r\n {COPY.JOIN_VOYAGERS}\r\n {' '}\r\n {editCopyByReplaceWithComponent(COPY.EARN_BY_JOIN, voyagersPointsCopy(), '')}\r\n \r\n \r\n {COPY.POINTS_EARNED_UPPON_COMPLETION}\r\n \r\n >\r\n )}\r\n {!isUserAuthenticated && arrowVariation ? (\r\n \r\n \r\n \r\n {editCopyByReplaceWithComponent(\r\n COPY.JOIN_VOYAGERS_CLUB_COPY,\r\n joinVoyagerUnderline(),\r\n ''\r\n )}\r\n \r\n \r\n {COPY.POINTS_EARNED_UPPON_COMPLETION}\r\n \r\n \r\n \r\n \r\n \r\n \r\n ) : null}\r\n \r\n \r\n );\r\n};\r\n\r\nLoyaltyEarn.propTypes = {\r\n iconLink: PropTypes.string,\r\n numberOfNights: PropTypes.number\r\n};\r\nLoyaltyEarn.defaultProps = {\r\n iconLink: LOYALTY_IMAGES.ADVENTURE_BUCK_COIN_WHITE,\r\n numberOfNights: 1\r\n};\r\n\r\nexport default LoyaltyEarn;\r\n","import React from 'react';\r\nimport { ImageBox, Text, TextLink } from '../../ui-kit';\r\nimport { editCopyByReplaceWithMultipleComponent } from '../../utilities/copyFunctions';\r\nimport { LOYALTY_IMAGES } from '../assets/images';\r\nimport { LoyaltyJoinMessageContainer } from '../assets/styles';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nconst LoyaltyJoinMessage = () => {\r\n const signIn = () => {\r\n if (window.openSignIn) {\r\n window.openSignIn(true);\r\n }\r\n };\r\n\r\n const signUp = () => {\r\n if (window.openSignUp) {\r\n window.openSignUp(true);\r\n }\r\n };\r\n const objectForReplace = {\r\n '': (\r\n \r\n {COPY.JOIN_VOYAGERS_MESSAGE_SIGNIN}\r\n \r\n ),\r\n '': (\r\n \r\n {COPY.JOIN_VOYAGERS_MESSAGE_SIGNUP}\r\n \r\n )\r\n };\r\n return (\r\n \r\n \r\n \r\n {editCopyByReplaceWithMultipleComponent(COPY.JOIN_VOYAGERS_MESSAGE, objectForReplace)}\r\n \r\n \r\n );\r\n};\r\n\r\nexport default LoyaltyJoinMessage;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { connect } from 'react-redux';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { getExpirationPoints } from '../../../store/componentStores/Account/account.selectors';\r\nimport {\r\n getCurrentResortPhone,\r\n getResortLocationUrlParam\r\n} from '../../../store/componentStores/CurrentLodge/currentLodge.selectors';\r\nimport { getIsLoyaltyPointsExpirationOnProfileEnabled } from '../../../store/componentStores/LodgeConfig/lodgeConfig.selectors';\r\nimport { showLoyalty } from '../../../store/reducers';\r\nimport { getTermsAndConditionUrl } from '../../../utilities/navigationUtils';\r\nimport { GwDatesWrapper } from '../../_internal_date_/gwDatesWrapper';\r\nimport { Box, Button, Flex, Text, TextLink } from '../../ui-kit';\r\nimport theme from '../../ui-kit/themes/theme';\r\nimport { editCopyByReplaceMultipleStrings, editCopyByReplaceString } from '../../utilities/copyFunctions';\r\nimport { LOYALTY_IMAGES } from '../assets/images';\r\nimport {\r\n BookNowWhite,\r\n Icon,\r\n LoyaltyProfileContainer,\r\n PointConditionsAndTerms,\r\n PointsContainer,\r\n PointsExpirationContainer,\r\n SpanDot\r\n} from '../assets/styles';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nconst LoyaltyProfilePoints = ({\r\n amount,\r\n iconLink,\r\n showLoyalty,\r\n currentResortPhone,\r\n resortLocationUrlParam,\r\n expirationPointsObject,\r\n isLoyaltyPointsExpirationOnProfileEnabled\r\n}) => {\r\n const isMobile = useMediaQuery({\r\n query: `(max-width: ${theme.breakpoints.xl})`\r\n });\r\n\r\n const { nextExpirationDate, expiringMetricValue } = expirationPointsObject;\r\n\r\n const expirationObject = {\r\n '': expiringMetricValue ?? 0,\r\n '': GwDatesWrapper.format(nextExpirationDate, 'MMM DD, YYYY')\r\n };\r\n\r\n return (\r\n <>\r\n {showLoyalty ? (\r\n \r\n {expirationPointsObject && expiringMetricValue !== 0 && isLoyaltyPointsExpirationOnProfileEnabled ? (\r\n \r\n \r\n \r\n {editCopyByReplaceMultipleStrings(COPY.EXPIRATION_POINTS, expirationObject)}\r\n \r\n \r\n ) : null}\r\n\r\n \r\n \r\n \r\n \r\n \r\n {COPY.AVAILABLE_VOYAGERS_POINTS}\r\n \r\n \r\n\r\n \r\n \r\n \r\n {amount}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {COPY.USE_POINTS_NEXT_BOOKING}\r\n \r\n \r\n \r\n \r\n \r\n {COPY.POINTS_ADDED_UPON_COMPLETION}\r\n \r\n \r\n \r\n \r\n \r\n {COPY.TEMP_EXPIRATION_NOTICE}\r\n \r\n \r\n \r\n \r\n {COPY.SEE_TERMS_AND_CONDITIONS}\r\n \r\n \r\n \r\n \r\n \r\n {editCopyByReplaceString(COPY.CLOSE_ACCOUNT, currentResortPhone, '<>')}\r\n \r\n \r\n \r\n \r\n ) : null}\r\n >\r\n );\r\n};\r\n\r\nLoyaltyProfilePoints.propTypes = {\r\n amount: PropTypes.number,\r\n iconLink: PropTypes.string,\r\n showLoyalty: PropTypes.bool,\r\n locationPhone: PropTypes.string,\r\n expirationPointsObject: PropTypes.object\r\n};\r\nLoyaltyProfilePoints.defaultProps = {\r\n amount: '0',\r\n iconLink: LOYALTY_IMAGES.ADVENTURE_BUCK_COIN_WHITE,\r\n showLoyalty: false,\r\n locationPhone: '',\r\n expirationPointsObject: {\r\n nextExpirationDate: '',\r\n expiringMetricValue: 0\r\n }\r\n};\r\n\r\nconst mapStateToProps = state => ({\r\n showLoyalty: showLoyalty(state),\r\n currentResortPhone: getCurrentResortPhone(state.currentLodge),\r\n resortLocationUrlParam: getResortLocationUrlParam(state.currentLodge),\r\n expirationPointsObject: getExpirationPoints(state.account),\r\n isLoyaltyPointsExpirationOnProfileEnabled: getIsLoyaltyPointsExpirationOnProfileEnabled(state.lodgeConfig)\r\n});\r\n\r\nexport default connect(mapStateToProps, null)(LoyaltyProfilePoints);\r\n","import { useCallback, useEffect, useMemo, useState } from 'react';\r\nimport UserAccountApiClientTioga from '../../api/clients/UserAccountApiClient';\r\n\r\nconst useHistoryPagination = (profileId, initialPage = 1) => {\r\n // Set Values for the page\r\n const [page, setPage] = useState(initialPage);\r\n const [pageLimit, setPageLimit] = useState(1);\r\n const [paginationContent, setPaginationContent] = useState([]);\r\n const [rowCount, setRowCount] = useState(5);\r\n const [displayArray, setDisplayArray] = useState([]);\r\n const [nextPageAvailable, setNextPageAvailable] = useState(false);\r\n const [resetAvailable, setResetAvailable] = useState(false);\r\n const rowCountLimit = useMemo(() => 50 * page, [page]);\r\n const [hasError, toggleError] = useState(false);\r\n const [errorMessage, setErrorMessage] = useState('');\r\n const [total, setTotal] = useState(0);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n // Reset function\r\n const reset = useCallback(() => {\r\n toggleError(false);\r\n setErrorMessage('');\r\n }, []);\r\n\r\n // Update pagination on success for the useEffect\r\n const updatePaginationOnSuccessEffect = useCallback(historyData => {\r\n const { history } = historyData;\r\n // Set total array (quantity)\r\n setTotal(history.data.length || 0);\r\n // Set the initial history\r\n const initialHistory = addUUID(history.data);\r\n setPaginationContent(initialHistory);\r\n // Set the initial display array\r\n const initialDisplayArray = spliceArrayAndAddItToAnother(initialHistory, []);\r\n setDisplayArray(initialDisplayArray);\r\n // Set the next page available\r\n const isNextPagePossible = history.totalPages > 1;\r\n if (isNextPagePossible) {\r\n setNextPageAvailable(true);\r\n }\r\n // Set the page limit\r\n setPageLimit(history.totalPages);\r\n }, []);\r\n\r\n // Update pagination on success for check next page\r\n const updatePaginationOnSuccessNextPage = useCallback(\r\n historyData => {\r\n const { history } = historyData;\r\n // Get new data\r\n const nextPageData = addUUID(history.data);\r\n // Create new pagination content\r\n const newPaginationContent = [...paginationContent, ...nextPageData];\r\n // Set the new pagination content\r\n setPaginationContent(newPaginationContent);\r\n // Update the row count\r\n setRowCount(prevState => prevState + 5);\r\n // Add more rows to the display array\r\n const newDisplayArray = spliceArrayAndAddItToAnother(newPaginationContent, displayArray, rowCount, rowCount + 5);\r\n setDisplayArray(newDisplayArray);\r\n // Set new page\r\n setPage(prevState => prevState + 1);\r\n // Check if next page is possible\r\n const isNextPagePossible = page + 1 < pageLimit;\r\n if (isNextPagePossible) {\r\n setNextPageAvailable(true);\r\n } else {\r\n setNextPageAvailable(false);\r\n }\r\n },\r\n [displayArray, page, pageLimit, paginationContent, rowCount]\r\n );\r\n\r\n // Log error on failure\r\n const updatePaginationOnFailure = useCallback(error => {\r\n console.log('Error', error);\r\n }, []);\r\n\r\n /**\r\n * Fetch function\r\n * This function return dynaic tile value\r\n */\r\n const fetch = useCallback(\r\n async (id, page, { toggleLoading, onSuccess, onFailure }) => {\r\n reset();\r\n toggleLoading(true);\r\n\r\n const apiClient = new UserAccountApiClientTioga('v1');\r\n\r\n const payload = {\r\n queryParams: { page }\r\n };\r\n let result = null;\r\n\r\n try {\r\n result = await apiClient.fetchUserPointsHistory(payload);\r\n toggleLoading(false);\r\n onSuccess(result.data);\r\n } catch (error) {\r\n toggleLoading(false);\r\n toggleError(true);\r\n setErrorMessage(error);\r\n onFailure(error);\r\n }\r\n },\r\n [reset]\r\n );\r\n\r\n // Reset rows\r\n const resetRows = () => {\r\n // Reset row count\r\n setRowCount(5);\r\n // Reset display array\r\n const newDisplayArray = spliceArrayAndAddItToAnother(displayArray, []);\r\n setDisplayArray(newDisplayArray);\r\n // Reset reset available\r\n setResetAvailable(false);\r\n };\r\n\r\n // Rows to display\r\n const seeMoreRows = useCallback(() => {\r\n // If limit reached and more pages available fetch next page\r\n if (verifyIfSmallerByFive(rowCount, rowCountLimit) && nextPageAvailable) {\r\n // Get new data\r\n fetch(profileId, page + 1, {\r\n toggleLoading: setIsLoading,\r\n onSuccess: updatePaginationOnSuccessNextPage,\r\n onFailure: updatePaginationOnFailure\r\n });\r\n return;\r\n }\r\n\r\n // Update the row count\r\n const newRowCount = rowCount + 5;\r\n setRowCount(newRowCount);\r\n // Add more rows to the display array\r\n const newDisplayArray = spliceArrayAndAddItToAnother(paginationContent, displayArray, rowCount, rowCount + 5);\r\n setDisplayArray(newDisplayArray);\r\n // Check if new row count is higher than the pagination content\r\n if (newRowCount >= paginationContent.length && !nextPageAvailable) {\r\n setResetAvailable(true);\r\n }\r\n }, [\r\n displayArray,\r\n fetch,\r\n nextPageAvailable,\r\n page,\r\n paginationContent,\r\n profileId,\r\n rowCount,\r\n rowCountLimit,\r\n updatePaginationOnFailure,\r\n updatePaginationOnSuccessNextPage\r\n ]);\r\n\r\n // Set Initial Values\r\n // Best solution to avoid calling the API several times?\r\n useEffect(() => {\r\n const timer = setTimeout(() => {\r\n // Set the initial history\r\n if (profileId) {\r\n fetch(profileId, 1, {\r\n toggleLoading: setIsLoading,\r\n onSuccess: updatePaginationOnSuccessEffect,\r\n onFailure: updatePaginationOnFailure\r\n });\r\n }\r\n }, 1500);\r\n return () => clearTimeout(timer);\r\n }, [fetch, profileId, updatePaginationOnFailure, updatePaginationOnSuccessEffect]);\r\n\r\n return {\r\n displayArray,\r\n seeMoreRows,\r\n resetAvailable,\r\n resetRows,\r\n isLoading,\r\n hasError,\r\n errorMessage,\r\n total\r\n };\r\n};\r\n\r\nexport default useHistoryPagination;\r\n\r\n// Add UIUID to each object in the array\r\nfunction addUUID(array) {\r\n return array.map(obj => ({ ...obj, uuid: `${obj.type}-${obj.date}-${obj.points}` }));\r\n}\r\n\r\n// Order array by date from the most recent to the oldest\r\nfunction orderByDate(array) {\r\n return array.sort((a, b) => new Date(b.date) - new Date(a.date));\r\n}\r\n\r\n// Splice section of the array and add it to new array\r\nfunction spliceArrayAndAddItToAnother(rawArray, displayArray, start = 0, end = 5) {\r\n const rawCopy = [...rawArray];\r\n const displayCopy = [...displayArray];\r\n\r\n const canNotSpliceByFive = displayArray.length + 5 > rawArray.length;\r\n\r\n const rawCopySlice = canNotSpliceByFive ? rawCopy.slice(start, rawArray.length) : rawCopy.slice(start, end);\r\n rawCopySlice.forEach(item => {\r\n displayCopy.push(item);\r\n });\r\n\r\n return orderByDate(displayCopy);\r\n}\r\n\r\n// Check if value is smaller by 5 than other value\r\nfunction verifyIfSmallerByFive(currentCount, countLimit) {\r\n return currentCount === countLimit - 5;\r\n}\r\n","import React, { useRef } from 'react';\r\nimport useHistoryPagination from '../../../hooks/api_hooks/useHistoryPagination';\r\nimport useScrollToItem from '../../../hooks/ui_hooks/useScrollToItem';\r\nimport { GwDatesWrapper } from '../../_internal_date_/gwDatesWrapper';\r\nimport { Box, Text } from '../../ui-kit';\r\nimport { editCopyByReplaceString } from '../../utilities/copyFunctions';\r\nimport {\r\n LoyaltyProfilePointsHistoryContainer,\r\n LoyaltyProfilePointsHistoryDate,\r\n LoyaltyProfilePointsHistoryDisclaimer,\r\n LoyaltyProfilePointsHistoryTableRow,\r\n LoyaltyProfilePointsHistoryTableRowJoinColum,\r\n SeeMoreContainer,\r\n SpanDot,\r\n StyledChevronDownIcon\r\n} from '../assets/styles';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nconst HISTORY_TYPES = {\r\n referred_a_friend: 'Referred a friend',\r\n points_used_on_a_booking: 'Reservation',\r\n points_returned_from_a_cancellation: 'Canceled Booking',\r\n completed_stay: 'Stayed at lodge',\r\n sl_expire: 'Points expired'\r\n};\r\n\r\nconst LoyaltyProfilePointsHistory = ({ profileId }) => {\r\n const { displayArray, seeMoreRows, resetAvailable, resetRows, total } = useHistoryPagination(profileId);\r\n const { customScrollTo } = useScrollToItem();\r\n const seeMore = useRef(null);\r\n const historyTitle = useRef(null);\r\n\r\n const handleSeeMore = () => {\r\n resetAvailable ? resetRows() : seeMoreRows();\r\n customScrollTo({\r\n ref: resetAvailable ? historyTitle : seeMore,\r\n behavior: 'smooth',\r\n block: 'end',\r\n delay: 500,\r\n custom: {\r\n yOffset: -380\r\n }\r\n });\r\n };\r\n\r\n return (\r\n \r\n {displayArray.length > 0 ? (\r\n <>\r\n \r\n {COPY.VOYAGERS_POINTS_HISTORY}\r\n \r\n \r\n \r\n {displayArray.map(item => (\r\n \r\n \r\n \r\n {HISTORY_TYPES[item.type]}\r\n \r\n \r\n {GwDatesWrapper.format(item.date, 'MMM DD, YYYY')}\r\n \r\n \r\n \r\n {editCopyByReplaceString(\r\n COPY.HISTORY_POINTS,\r\n verifyIfNegative(item.points) ? item.points : `+${item.points}`,\r\n ''\r\n )}\r\n \r\n \r\n ))}\r\n \r\n {total && total > 5 ? (\r\n \r\n \r\n {resetAvailable ? COPY.SEE_LESS : COPY.SEE_MORE}\r\n \r\n \r\n \r\n ) : null}\r\n \r\n >\r\n ) : null}\r\n\r\n \r\n \r\n \r\n {COPY.VOYAGERS_EXPIRATION_HISTORY}\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default LoyaltyProfilePointsHistory;\r\n\r\n// Check if number is negative or positive\r\nfunction verifyIfNegative(number) {\r\n return number < 0 ? true : false;\r\n}\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\n\r\nimport { Button, Flex, Text } from '../../ui-kit';\r\nimport { LOYALTY_IMAGES } from '../assets/images';\r\nimport { ButtonAndTermContainer, Icon, LoyaltyWithExpirationDateContainer, TermText } from '../assets/styles';\r\n\r\nconst LoyaltyWithExpirationDate = ({ amount, expirationDate, iconLink }) => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n Available Wolf Dollars\r\n ${amount}\r\n \r\n \r\n Expiration Date\r\n {expirationDate}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n See Terms & Conditions\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nLoyaltyWithExpirationDate.propTypes = {\r\n amount: PropTypes.number,\r\n expirationDate: PropTypes.string,\r\n iconLink: PropTypes.string\r\n};\r\nLoyaltyWithExpirationDate.defaultProps = {\r\n amount: '153',\r\n expirationDate: '08/21/2022',\r\n iconLink: LOYALTY_IMAGES.ADVENTURE_BUCK_COIN\r\n};\r\n\r\nexport default LoyaltyWithExpirationDate;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\n\r\nimport LoyaltyApplied from './components/LoyaltyApplied';\r\nimport LoyaltyAvailable from './components/LoyaltyAvailable';\r\nimport LoyaltyAvailableMobileSearch from './components/LoyaltyAvailableMobileSearch';\r\nimport LoyaltyAvailableWithButton from './components/LoyaltyAvailableWithButton';\r\nimport LoyaltyEarn from './components/LoyaltyEarn';\r\nimport LoyaltyJoinMessage from './components/LoyaltyJoinMessage';\r\nimport LoyaltyProfilePoints from './components/LoyaltyProfilePoints';\r\nimport LoyaltyProfilePointsHistory from './components/LoyaltyProfilePointsHistory';\r\nimport LoyaltyWithExpirationDate from './components/LoyaltyWithExpirationDate';\r\nimport { LOYALTY_TYPES } from './utilities/constants';\r\n\r\nconst Loyalty = ({ isNewWidgetStyleActive, loyaltyType, ...props }) => {\r\n const LoyaltyOptions = {\r\n [LOYALTY_TYPES.available]: ,\r\n [LOYALTY_TYPES.applied]: ,\r\n [LOYALTY_TYPES.availableWithButton]: ,\r\n [LOYALTY_TYPES.withExpirationDate]: ,\r\n [LOYALTY_TYPES.earn]: ,\r\n [LOYALTY_TYPES.profilePoints]: ,\r\n [LOYALTY_TYPES.availableMobileSearch]: (\r\n \r\n ),\r\n [LOYALTY_TYPES.profilePointsHistory]: ,\r\n [LOYALTY_TYPES.joinVoyagersMessage]: \r\n };\r\n\r\n return LoyaltyOptions[loyaltyType];\r\n};\r\n\r\nLoyalty.propTypes = {\r\n amount: PropTypes.number,\r\n location: PropTypes.string,\r\n loyaltyType: PropTypes.string.isRequired,\r\n iconSize: PropTypes.string\r\n};\r\n\r\nLoyalty.defaultProps = {\r\n amount: '153',\r\n location: 'Great Wolf Lodge-Chicago / Gurnee, IL',\r\n loyaltyType: 'available',\r\n iconSize: '24px'\r\n};\r\n\r\nexport default Loyalty;\r\n","// Import types\r\nimport routes from '../../../routes';\r\nimport cartActionTypes from './cart.types';\r\n\r\n// Set cart location\r\nexport const setCartResortLocation = location => dispatch => {\r\n dispatch({\r\n type: cartActionTypes.SET_CART_RESORT_LOCATION,\r\n cartResortLocation: location\r\n });\r\n};\r\n\r\n// Reset cart location\r\nexport const resetCartResortLocation = () => dispatch => {\r\n dispatch({\r\n type: cartActionTypes.RESET_CART_RESORT_LOCATION\r\n });\r\n};\r\n\r\n// Set last visited step\r\nexport const setCartLastVisitedStep = step => dispatch => {\r\n dispatch({\r\n type: cartActionTypes.SET_CART_LAST_VISITED_STEP,\r\n cartLastVisitedStep: step\r\n });\r\n};\r\n\r\n// Push to last visited step\r\nexport const pushToLastVisitedStep = () => (dispatch, getState) => {\r\n const { cartLastVisitedStep } = getState().cart;\r\n const { resortLocationUrl } = getState().currentLodge;\r\n const { selectedPackages } = getState().packages;\r\n const hasDiningPackages = selectedPackages?.some(pkg => pkg.packageType?.includes('dining'));\r\n if (!cartLastVisitedStep || !resortLocationUrl) return;\r\n\r\n if (cartLastVisitedStep === routes.plan.dining.replace(/\\/$/, '') && hasDiningPackages) {\r\n return (window.location.href = resortLocationUrl.replace(/\\/$/, '') + routes.plan.payment.replace(/\\/$/, ''));\r\n }\r\n\r\n window.location.href = resortLocationUrl.replace(/\\/$/, '') + cartLastVisitedStep;\r\n};\r\n\r\n// Set expired cart\r\nexport const setExpiredCart = () => dispatch => {\r\n dispatch({\r\n type: cartActionTypes.SET_EXPIRED_CART,\r\n expiredCart: true\r\n });\r\n};\r\n\r\n// Reset expired cart\r\nexport const resetExpiredCart = () => dispatch => {\r\n dispatch({\r\n type: cartActionTypes.RESET_EXPIRED_CART,\r\n expiredCart: false\r\n });\r\n};\r\n","const countries = [\r\n { name: 'Afghanistan', code: 'AF' },\r\n { name: 'Åland Islands', code: 'AX' },\r\n { name: 'Albania', code: 'AL' },\r\n { name: 'Algeria', code: 'DZ' },\r\n { name: 'American Samoa', code: 'AS' },\r\n { name: 'AndorrA', code: 'AD' },\r\n { name: 'Angola', code: 'AO' },\r\n { name: 'Anguilla', code: 'AI' },\r\n { name: 'Antarctica', code: 'AQ' },\r\n { name: 'Antigua and Barbuda', code: 'AG' },\r\n { name: 'Argentina', code: 'AR' },\r\n { name: 'Armenia', code: 'AM' },\r\n { name: 'Aruba', code: 'AW' },\r\n { name: 'Australia', code: 'AU' },\r\n { name: 'Austria', code: 'AT' },\r\n { name: 'Azerbaijan', code: 'AZ' },\r\n { name: 'Bahamas', code: 'BS' },\r\n { name: 'Bahrain', code: 'BH' },\r\n { name: 'Bangladesh', code: 'BD' },\r\n { name: 'Barbados', code: 'BB' },\r\n { name: 'Belarus', code: 'BY' },\r\n { name: 'Belgium', code: 'BE' },\r\n { name: 'Belize', code: 'BZ' },\r\n { name: 'Benin', code: 'BJ' },\r\n { name: 'Bermuda', code: 'BM' },\r\n { name: 'Bhutan', code: 'BT' },\r\n { name: 'Bolivia', code: 'BO' },\r\n { name: 'Bosnia and Herzegovina', code: 'BA' },\r\n { name: 'Botswana', code: 'BW' },\r\n { name: 'Bouvet Island', code: 'BV' },\r\n { name: 'Brazil', code: 'BR' },\r\n { name: 'British Indian Ocean Territory', code: 'IO' },\r\n { name: 'Brunei Darussalam', code: 'BN' },\r\n { name: 'Bulgaria', code: 'BG' },\r\n { name: 'Burkina Faso', code: 'BF' },\r\n { name: 'Burundi', code: 'BI' },\r\n { name: 'Cambodia', code: 'KH' },\r\n { name: 'Cameroon', code: 'CM' },\r\n { name: 'Canada', code: 'CA' },\r\n { name: 'Cape Verde', code: 'CV' },\r\n { name: 'Cayman Islands', code: 'KY' },\r\n { name: 'Central African Republic', code: 'CF' },\r\n { name: 'Chad', code: 'TD' },\r\n { name: 'Chile', code: 'CL' },\r\n { name: 'China', code: 'CN' },\r\n { name: 'Christmas Island', code: 'CX' },\r\n { name: 'Cocos (Keeling) Islands', code: 'CC' },\r\n { name: 'Colombia', code: 'CO' },\r\n { name: 'Comoros', code: 'KM' },\r\n { name: 'Congo', code: 'CG' },\r\n { name: 'Congo, The Democratic Republic of the', code: 'CD' },\r\n { name: 'Cook Islands', code: 'CK' },\r\n { name: 'Costa Rica', code: 'CR' },\r\n { name: \"Cote D'Ivoire\", code: 'CI' },\r\n { name: 'Croatia', code: 'HR' },\r\n { name: 'Cuba', code: 'CU' },\r\n { name: 'Cyprus', code: 'CY' },\r\n { name: 'Czech Republic', code: 'CZ' },\r\n { name: 'Denmark', code: 'DK' },\r\n { name: 'Djibouti', code: 'DJ' },\r\n { name: 'Dominica', code: 'DM' },\r\n { name: 'Dominican Republic', code: 'DO' },\r\n { name: 'Ecuador', code: 'EC' },\r\n { name: 'Egypt', code: 'EG' },\r\n { name: 'El Salvador', code: 'SV' },\r\n { name: 'Equatorial Guinea', code: 'GQ' },\r\n { name: 'Eritrea', code: 'ER' },\r\n { name: 'Estonia', code: 'EE' },\r\n { name: 'Ethiopia', code: 'ET' },\r\n { name: 'Falkland Islands (Malvinas)', code: 'FK' },\r\n { name: 'Faroe Islands', code: 'FO' },\r\n { name: 'Fiji', code: 'FJ' },\r\n { name: 'Finland', code: 'FI' },\r\n { name: 'France', code: 'FR' },\r\n { name: 'French Guiana', code: 'GF' },\r\n { name: 'French Polynesia', code: 'PF' },\r\n { name: 'French Southern Territories', code: 'TF' },\r\n { name: 'Gabon', code: 'GA' },\r\n { name: 'Gambia', code: 'GM' },\r\n { name: 'Georgia', code: 'GE' },\r\n { name: 'Germany', code: 'DE' },\r\n { name: 'Ghana', code: 'GH' },\r\n { name: 'Gibraltar', code: 'GI' },\r\n { name: 'Greece', code: 'GR' },\r\n { name: 'Greenland', code: 'GL' },\r\n { name: 'Grenada', code: 'GD' },\r\n { name: 'Guadeloupe', code: 'GP' },\r\n { name: 'Guam', code: 'GU' },\r\n { name: 'Guatemala', code: 'GT' },\r\n { name: 'Guernsey', code: 'GG' },\r\n { name: 'Guinea', code: 'GN' },\r\n { name: 'Guinea-Bissau', code: 'GW' },\r\n { name: 'Guyana', code: 'GY' },\r\n { name: 'Haiti', code: 'HT' },\r\n { name: 'Heard Island and Mcdonald Islands', code: 'HM' },\r\n { name: 'Holy See (Vatican City State)', code: 'VA' },\r\n { name: 'Honduras', code: 'HN' },\r\n { name: 'Hong Kong', code: 'HK' },\r\n { name: 'Hungary', code: 'HU' },\r\n { name: 'Iceland', code: 'IS' },\r\n { name: 'India', code: 'IN' },\r\n { name: 'Indonesia', code: 'ID' },\r\n { name: 'Iran, Islamic Republic Of', code: 'IR' },\r\n { name: 'Iraq', code: 'IQ' },\r\n { name: 'Ireland', code: 'IE' },\r\n { name: 'Isle of Man', code: 'IM' },\r\n { name: 'Israel', code: 'IL' },\r\n { name: 'Italy', code: 'IT' },\r\n { name: 'Jamaica', code: 'JM' },\r\n { name: 'Japan', code: 'JP' },\r\n { name: 'Jersey', code: 'JE' },\r\n { name: 'Jordan', code: 'JO' },\r\n { name: 'Kazakhstan', code: 'KZ' },\r\n { name: 'Kenya', code: 'KE' },\r\n { name: 'Kiribati', code: 'KI' },\r\n { name: \"Korea, Democratic People'S Republic of\", code: 'KP' },\r\n { name: 'Korea, Republic of', code: 'KR' },\r\n { name: 'Kuwait', code: 'KW' },\r\n { name: 'Kyrgyzstan', code: 'KG' },\r\n { name: \"Lao People'S Democratic Republic\", code: 'LA' },\r\n { name: 'Latvia', code: 'LV' },\r\n { name: 'Lebanon', code: 'LB' },\r\n { name: 'Lesotho', code: 'LS' },\r\n { name: 'Liberia', code: 'LR' },\r\n { name: 'Libyan Arab Jamahiriya', code: 'LY' },\r\n { name: 'Liechtenstein', code: 'LI' },\r\n { name: 'Lithuania', code: 'LT' },\r\n { name: 'Luxembourg', code: 'LU' },\r\n { name: 'Macao', code: 'MO' },\r\n { name: 'Macedonia, The Former Yugoslav Republic of', code: 'MK' },\r\n { name: 'Madagascar', code: 'MG' },\r\n { name: 'Malawi', code: 'MW' },\r\n { name: 'Malaysia', code: 'MY' },\r\n { name: 'Maldives', code: 'MV' },\r\n { name: 'Mali', code: 'ML' },\r\n { name: 'Malta', code: 'MT' },\r\n { name: 'Marshall Islands', code: 'MH' },\r\n { name: 'Martinique', code: 'MQ' },\r\n { name: 'Mauritania', code: 'MR' },\r\n { name: 'Mauritius', code: 'MU' },\r\n { name: 'Mayotte', code: 'YT' },\r\n { name: 'Mexico', code: 'MX' },\r\n { name: 'Micronesia, Federated States of', code: 'FM' },\r\n { name: 'Moldova, Republic of', code: 'MD' },\r\n { name: 'Monaco', code: 'MC' },\r\n { name: 'Mongolia', code: 'MN' },\r\n { name: 'Montserrat', code: 'MS' },\r\n { name: 'Morocco', code: 'MA' },\r\n { name: 'Mozambique', code: 'MZ' },\r\n { name: 'Myanmar', code: 'MM' },\r\n { name: 'Namibia', code: 'NA' },\r\n { name: 'Nauru', code: 'NR' },\r\n { name: 'Nepal', code: 'NP' },\r\n { name: 'Netherlands', code: 'NL' },\r\n { name: 'Netherlands Antilles', code: 'AN' },\r\n { name: 'New Caledonia', code: 'NC' },\r\n { name: 'New Zealand', code: 'NZ' },\r\n { name: 'Nicaragua', code: 'NI' },\r\n { name: 'Niger', code: 'NE' },\r\n { name: 'Nigeria', code: 'NG' },\r\n { name: 'Niue', code: 'NU' },\r\n { name: 'Norfolk Island', code: 'NF' },\r\n { name: 'Northern Mariana Islands', code: 'MP' },\r\n { name: 'Norway', code: 'NO' },\r\n { name: 'Oman', code: 'OM' },\r\n { name: 'Pakistan', code: 'PK' },\r\n { name: 'Palau', code: 'PW' },\r\n { name: 'Palestinian Territory, Occupied', code: 'PS' },\r\n { name: 'Panama', code: 'PA' },\r\n { name: 'Papua New Guinea', code: 'PG' },\r\n { name: 'Paraguay', code: 'PY' },\r\n { name: 'Peru', code: 'PE' },\r\n { name: 'Philippines', code: 'PH' },\r\n { name: 'Pitcairn', code: 'PN' },\r\n { name: 'Poland', code: 'PL' },\r\n { name: 'Portugal', code: 'PT' },\r\n { name: 'Puerto Rico', code: 'PR' },\r\n { name: 'Qatar', code: 'QA' },\r\n { name: 'Reunion', code: 'RE' },\r\n { name: 'Romania', code: 'RO' },\r\n { name: 'Russian Federation', code: 'RU' },\r\n { name: 'RWANDA', code: 'RW' },\r\n { name: 'Saint Helena', code: 'SH' },\r\n { name: 'Saint Kitts and Nevis', code: 'KN' },\r\n { name: 'Saint Lucia', code: 'LC' },\r\n { name: 'Saint Pierre and Miquelon', code: 'PM' },\r\n { name: 'Saint Vincent and the Grenadines', code: 'VC' },\r\n { name: 'Samoa', code: 'WS' },\r\n { name: 'San Marino', code: 'SM' },\r\n { name: 'Sao Tome and Principe', code: 'ST' },\r\n { name: 'Saudi Arabia', code: 'SA' },\r\n { name: 'Senegal', code: 'SN' },\r\n { name: 'Serbia and Montenegro', code: 'CS' },\r\n { name: 'Seychelles', code: 'SC' },\r\n { name: 'Sierra Leone', code: 'SL' },\r\n { name: 'Singapore', code: 'SG' },\r\n { name: 'Slovakia', code: 'SK' },\r\n { name: 'Slovenia', code: 'SI' },\r\n { name: 'Solomon Islands', code: 'SB' },\r\n { name: 'Somalia', code: 'SO' },\r\n { name: 'South Africa', code: 'ZA' },\r\n { name: 'South Georgia and the South Sandwich Islands', code: 'GS' },\r\n { name: 'Spain', code: 'ES' },\r\n { name: 'Sri Lanka', code: 'LK' },\r\n { name: 'Sudan', code: 'SD' },\r\n { name: 'Suriname', code: 'SR' },\r\n { name: 'Svalbard and Jan Mayen', code: 'SJ' },\r\n { name: 'Swaziland', code: 'SZ' },\r\n { name: 'Sweden', code: 'SE' },\r\n { name: 'Switzerland', code: 'CH' },\r\n { name: 'Syrian Arab Republic', code: 'SY' },\r\n { name: 'Taiwan, Province of China', code: 'TW' },\r\n { name: 'Tajikistan', code: 'TJ' },\r\n { name: 'Tanzania, United Republic of', code: 'TZ' },\r\n { name: 'Thailand', code: 'TH' },\r\n { name: 'Timor-Leste', code: 'TL' },\r\n { name: 'Togo', code: 'TG' },\r\n { name: 'Tokelau', code: 'TK' },\r\n { name: 'Tonga', code: 'TO' },\r\n { name: 'Trinidad and Tobago', code: 'TT' },\r\n { name: 'Tunisia', code: 'TN' },\r\n { name: 'Turkey', code: 'TR' },\r\n { name: 'Turkmenistan', code: 'TM' },\r\n { name: 'Turks and Caicos Islands', code: 'TC' },\r\n { name: 'Tuvalu', code: 'TV' },\r\n { name: 'Uganda', code: 'UG' },\r\n { name: 'Ukraine', code: 'UA' },\r\n { name: 'United Arab Emirates', code: 'AE' },\r\n { name: 'United Kingdom', code: 'GB' },\r\n { name: 'United States', code: 'US' },\r\n { name: 'United States Minor Outlying Islands', code: 'UM' },\r\n { name: 'Uruguay', code: 'UY' },\r\n { name: 'Uzbekistan', code: 'UZ' },\r\n { name: 'Vanuatu', code: 'VU' },\r\n { name: 'Venezuela', code: 'VE' },\r\n { name: 'Viet Nam', code: 'VN' },\r\n { name: 'Virgin Islands, British', code: 'VG' },\r\n { name: 'Virgin Islands, U.S.', code: 'VI' },\r\n { name: 'Wallis and Futuna', code: 'WF' },\r\n { name: 'Western Sahara', code: 'EH' },\r\n { name: 'Yemen', code: 'YE' },\r\n { name: 'Zambia', code: 'ZM' },\r\n { name: 'Zimbabwe', code: 'ZW' }\r\n];\r\n\r\nexport default countries;\r\n","import styled, { css } from 'styled-components';\r\nimport { themeGet } from 'styled-system';\r\nimport { Box, Flex } from '../../ui-kit/index';\r\nimport theme from '../../ui-kit/themes/theme';\r\n\r\nexport const PackageBox = styled(Box)`\r\n background: ${themeGet('colors.pureWhite.0')};\r\n`;\r\n\r\nexport const Wrapper = styled(Box)`\r\n ${props =>\r\n props.applyBorder\r\n ? css`\r\n border-radius: ${theme.radii[5]}px;\r\n box-shadow: ${theme.boxShadows[21]}\r\n border: ${theme.borders[4]}\r\n background-image: linear-gradient(\r\n to right,\r\n ${themeGet('colors.pureWhite.0')} -11%,\r\n ${themeGet('colors.snowMountainGrey.20')} 138%\r\n )`\r\n : css`\r\n border-radius: ${theme.radii[1]}px;\r\n border-bottom: ${theme.borders[4]};\r\n `}\r\n`;\r\n\r\nexport const PriceDivider = styled(Box)`\r\n opacity: 0.4;\r\n border-top: ${props => (props.dashed ? 'dashed' : 'solid')} 1px ${themeGet('colors.kiddiePoolBlue.50')};\r\n`;\r\n\r\nexport const SustainabilityTooltip = styled.span`\r\n color: ${theme.colors.deepLakeBlue[100]};\r\n background: ${theme.colors.pureWhite[0]};\r\n font-size: ${`${theme.fontSizes[0]}px`};\r\n font-weight: ${theme.fontWeights.semibold};\r\n cursor: pointer;\r\n`;\r\n\r\nexport const SustainabilityContainer = styled(Flex)`\r\n min-height: 22px;\r\n`;\r\n\r\nexport const DayPassContainer = styled(Flex)`\r\n position: relative;\r\n border-bottom: 1px solid ${theme.colors.deepLakeBlue[20]};\r\n\r\n ${Flex} {\r\n &:not(:last-child) {\r\n border-right: 1px solid ${theme.colors.deepLakeBlue[20]};\r\n }\r\n }\r\n`;\r\n","// This component is deprecated, please use src/components/ui-kit/NewSelect\r\n/* eslint-disable react-hooks/exhaustive-deps */\r\nimport PropTypes from 'prop-types';\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport styled, { css } from 'styled-components';\r\nimport { themeGet } from 'styled-system';\r\nimport { fontWeights } from '../../ui-kit/themes/theme';\r\nimport Box from '../Box';\r\nimport Flex from '../Flex';\r\nimport Label from '../Label';\r\nimport Relative from '../Relative';\r\nimport Text from '../Text';\r\nimport ArrowDownThinIcon from '../icons/ArrowDownThin';\r\n\r\nconst borderColor = ({ invalid, valid }) => {\r\n if (valid) {\r\n return css`\r\n border-color: ${themeGet('colors.successGreen')};\r\n `;\r\n }\r\n if (invalid) {\r\n return css`\r\n border-color: ${themeGet('colors.digitalBrightRed.100')};\r\n `;\r\n }\r\n\r\n return css`\r\n border-color: ${themeGet('colors.preciousStoneBlue.20')};\r\n `;\r\n};\r\n\r\nconst StyledSelect = styled.select`\r\n margin: 0px;\r\n cursor: pointer;\r\n appearance: none;\r\n padding-top: ${({ placeholder, paddingTop }) => (paddingTop ? paddingTop : !!placeholder ? `22px` : `15px`)};\r\n padding-bottom: ${({ placeholder, paddingBottom }) =>\r\n paddingBottom ? paddingBottom : !!placeholder ? `10px` : `14px`};\r\n padding-left: 16px;\r\n padding-right: 30px;\r\n border-radius: ${({ borderRadius }) => (borderRadius ? borderRadius : '10px')};\r\n background-color: ${({ backgroundColor }) =>\r\n backgroundColor ? themeGet('colors.' + backgroundColor) : themeGet('colors.snowMountainGrey.20')};\r\n width: 100%;\r\n border-width: ${({ borderWidth }) => (borderWidth ? borderWidth : '1px')};\r\n border-style: solid;\r\n font-size: ${({ fontSize }) => (fontSize ? themeGet('fontSizes.' + fontSize) : themeGet('fontSizes.1'))}px;\r\n color: ${({ color }) => (color ? themeGet('colors.' + color) : themeGet('colors.deepLakeBlue.100'))};\r\n font-family: ${themeGet('fonts.secondary')};\r\n font-weight: ${({ fontWeight }) => (fontWeight ? fontWeight : themeGet('fontWeights.regular'))};\r\n line-height: 1.2;\r\n height: ${({ height }) => (height ? height : `50px`)};\r\n\r\n &:focus {\r\n outline: unset;\r\n border: none;\r\n box-shadow: 0 0 0 2px ${themeGet('colors.focusBlue')};\r\n }\r\n\r\n & + svg {\r\n ${({ isNewWidgetStyleActive }) =>\r\n isNewWidgetStyleActive &&\r\n css`\r\n fill: ${themeGet('colors.deepLakeBlue.100')};\r\n top: 35px;\r\n right: 13px;\r\n stroke-width: 2;\r\n path {\r\n stroke: black;\r\n stroke-width: 2;\r\n }\r\n `}\r\n }\r\n\r\n ${borderColor}\r\n`;\r\n\r\nconst StyledChevronDownIcon = styled(ArrowDownThinIcon)`\r\n pointer-events: none;\r\n display: flex;\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n right: 10px;\r\n fill: ${themeGet('colors.preciousStoneBlue.100')};\r\n`;\r\n\r\nconst StyledPlaceHolder = styled(Label)`\r\n top: 25px;\r\n transform: ${({ active }) => (active ? `translateY(-15px) scale(.57)` : `translateY(-50%)`)};\r\n left: ${themeGet('space.3')}px;\r\n color: ${props => (props.active ? themeGet('colors.preciousStoneBlue.100') : themeGet('colors.deepLakeBlue.100'))};\r\n opacity: ${props => (props.active ? 1 : 0.6)};\r\n transition: all 0.1s ease-in-out 0s;\r\n font-size: ${themeGet('fontSizes.1')}px;\r\n`;\r\n\r\nconst propTypes = {\r\n /**\r\n Use the invalid state to indicate there was an error validating this field.\r\n */\r\n invalid: PropTypes.bool,\r\n /**\r\n Use the valid prop to indicate if the select was successfully validated\r\n filled; this will take precedence over the invalid prop.\r\n */\r\n valid: PropTypes.bool,\r\n /**\r\n * Shows an error message, it will only display if invalid is `true`.\r\n */\r\n errorMessage: PropTypes.string,\r\n /**\r\n * Floating label text.\r\n */\r\n placeholder: PropTypes.string,\r\n /**\r\n * Execute function when the component gets focus, this will be executed\r\n * after moving the floating label.\r\n */\r\n onFocus: PropTypes.func,\r\n /**\r\n * Execute function when the `Select` component losses focus, this will be\r\n * executed after moving the floating label.\r\n */\r\n onBlur: PropTypes.func,\r\n /**\r\n * Value to select if the `Select`component is used as a controlled input.\r\n */\r\n value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\r\n /**\r\n * Value to be used when the `Select`component is not used as a controlled\r\n * input.\r\n */\r\n defaultValue: PropTypes.string\r\n};\r\n\r\nconst defaultProps = {\r\n invalid: false,\r\n valid: false,\r\n onFocus: () => {},\r\n onBlur: () => {}\r\n};\r\n\r\n/**\r\n * Use the `Select` component to give the user multiple selections with and\r\n * enhanced design but, preserving native select UI.\r\n *\r\n * Aside from the props listed below, this component accepts all the normal\r\n * props from a select HTML tag, they will be streamed to the select tag.\r\n */\r\nconst Select = ({\r\n children,\r\n errorMessage,\r\n placeholder,\r\n onFocus,\r\n onBlur,\r\n value,\r\n id,\r\n defaultValue,\r\n invalid,\r\n ...props\r\n}) => {\r\n const [isFocusedOrFilled, setIsFocusedOrFilled] = useState((!!value && value !== 'placeholder') || defaultValue);\r\n\r\n useEffect(() => {\r\n setIsFocusedOrFilled((!!value && value !== 'placeholder') || defaultValue);\r\n }, [value]);\r\n\r\n const selectRef = useRef(null);\r\n\r\n const focusHandler = e => {\r\n if (!isFocusedOrFilled) {\r\n setIsFocusedOrFilled(true);\r\n }\r\n\r\n onFocus(e);\r\n };\r\n\r\n const blurHandler = e => {\r\n const {\r\n current: { value: selectValue }\r\n } = selectRef;\r\n setIsFocusedOrFilled(!!selectValue && selectValue !== 'placeholder');\r\n onBlur(e);\r\n };\r\n\r\n const getDefaultValue = () => {\r\n if (defaultValue) {\r\n return {\r\n defaultValue\r\n };\r\n }\r\n\r\n if (placeholder && !value) {\r\n return {\r\n defaultValue: 'placeholder'\r\n };\r\n }\r\n\r\n return {};\r\n };\r\n\r\n const getValue = () => {\r\n if (isFocusedOrFilled) {\r\n return { value };\r\n }\r\n\r\n return {};\r\n };\r\n\r\n return (\r\n \r\n \r\n \r\n {placeholder && }\r\n {children}\r\n \r\n {placeholder && (\r\n \r\n {placeholder}\r\n \r\n )}\r\n \r\n \r\n {errorMessage && invalid && (\r\n \r\n \r\n {errorMessage}\r\n \r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\nSelect.propTypes = propTypes;\r\nSelect.defaultProps = defaultProps;\r\n\r\nexport default Select;\r\n","import Select from './Select';\r\n\r\nexport default Select;\r\n","import React from 'react';\r\nimport Select from '../ui-kit/Select';\r\nimport {\r\n getDropdownDataForPackage,\r\n shouldShowQuantitySelect\r\n} from '../../utilities/packagesUtils';\r\n\r\nconst SelectPackageQuantity = ({\r\n quantitySelected,\r\n checkinDateSelection,\r\n checkoutDateSelection,\r\n packageItem,\r\n handleUpdatePackageQuantity,\r\n numberOfGuests,\r\n isNiagaraProperty,\r\n ...props\r\n}) => {\r\n // Some package information comes in a different shape,\r\n // we need to map with the information and object properties we need to consume\r\n const pkgItem = { ...packageItem };\r\n pkgItem.packageCode = packageItem.packageCode || packageItem.id;\r\n pkgItem.quantity = packageItem.quantity || packageItem.quantityAdded;\r\n\r\n const isCabana = packageItem.isCabana || false;\r\n\r\n const shouldShowSelect = shouldShowQuantitySelect(pkgItem) && !isCabana;\r\n\r\n if (\r\n (pkgItem.showQuantitySelect === undefined ||\r\n pkgItem.showQuantitySelect === true) &&\r\n shouldShowSelect\r\n ) {\r\n const { quantity, options } = getDropdownDataForPackage(\r\n pkgItem,\r\n checkinDateSelection,\r\n checkoutDateSelection,\r\n numberOfGuests,\r\n isNiagaraProperty\r\n );\r\n\r\n return (\r\n \r\n );\r\n } else {\r\n return null;\r\n }\r\n};\r\n\r\nexport default SelectPackageQuantity;\r\n","import { ASSETS_LOCATIONS, getAssetsUrl } from '../../../utilities/constants';\r\n\r\nexport const OFFERS_IMAGES = {\r\n OFFERS_GWL_VOYAGERS_CLUB: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'gwl-voyagers-club.svg'),\r\n OFFERS_V_GREEN_ICON: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'v-green.svg'),\r\n OFFERS_V_BLUE_ICON: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'v-blue.svg'),\r\n OFFERS_V_GRAY_ICON: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'v-gray.svg')\r\n};\r\n","// Canada provinces\r\nconst provinces = [\r\n {\r\n name: 'Alberta',\r\n abbreviation: 'AB'\r\n },\r\n {\r\n name: 'British Columbia',\r\n abbreviation: 'BC'\r\n },\r\n {\r\n name: 'Manitoba',\r\n abbreviation: 'MB'\r\n },\r\n {\r\n name: 'New Brunswick',\r\n abbreviation: 'NB'\r\n },\r\n {\r\n name: 'Newfoundland and Labrador',\r\n abbreviation: 'NL'\r\n },\r\n {\r\n name: 'Nova Scotia',\r\n abbreviation: 'NS'\r\n },\r\n {\r\n name: 'Northwest Territories',\r\n abbreviation: 'NT'\r\n },\r\n {\r\n name: 'Nunavut',\r\n abbreviation: 'NU'\r\n },\r\n {\r\n name: 'Ontario',\r\n abbreviation: 'ON'\r\n },\r\n {\r\n name: 'Prince Edward Island',\r\n abbreviation: 'PE'\r\n },\r\n {\r\n name: 'Québec',\r\n abbreviation: 'QC'\r\n },\r\n {\r\n name: 'Saskatchewan',\r\n abbreviation: 'SK'\r\n },\r\n {\r\n name: 'Yukon',\r\n abbreviation: 'YT'\r\n }\r\n];\r\n\r\nexport default provinces;\r\n","const states = [\r\n {\r\n name: 'Alabama',\r\n abbreviation: 'AL'\r\n },\r\n {\r\n name: 'Alaska',\r\n abbreviation: 'AK'\r\n },\r\n {\r\n name: 'American Samoa',\r\n abbreviation: 'AS'\r\n },\r\n {\r\n name: 'Arizona',\r\n abbreviation: 'AZ'\r\n },\r\n {\r\n name: 'Arkansas',\r\n abbreviation: 'AR'\r\n },\r\n {\r\n name: 'California',\r\n abbreviation: 'CA'\r\n },\r\n {\r\n name: 'Colorado',\r\n abbreviation: 'CO'\r\n },\r\n {\r\n name: 'Connecticut',\r\n abbreviation: 'CT'\r\n },\r\n {\r\n name: 'Delaware',\r\n abbreviation: 'DE'\r\n },\r\n {\r\n name: 'District Of Columbia',\r\n abbreviation: 'DC'\r\n },\r\n {\r\n name: 'Federated States Of Micronesia',\r\n abbreviation: 'FM'\r\n },\r\n {\r\n name: 'Florida',\r\n abbreviation: 'FL'\r\n },\r\n {\r\n name: 'Georgia',\r\n abbreviation: 'GA'\r\n },\r\n {\r\n name: 'Guam',\r\n abbreviation: 'GU'\r\n },\r\n {\r\n name: 'Hawaii',\r\n abbreviation: 'HI'\r\n },\r\n {\r\n name: 'Idaho',\r\n abbreviation: 'ID'\r\n },\r\n {\r\n name: 'Illinois',\r\n abbreviation: 'IL'\r\n },\r\n {\r\n name: 'Indiana',\r\n abbreviation: 'IN'\r\n },\r\n {\r\n name: 'Iowa',\r\n abbreviation: 'IA'\r\n },\r\n {\r\n name: 'Kansas',\r\n abbreviation: 'KS'\r\n },\r\n {\r\n name: 'Kentucky',\r\n abbreviation: 'KY'\r\n },\r\n {\r\n name: 'Louisiana',\r\n abbreviation: 'LA'\r\n },\r\n {\r\n name: 'Maine',\r\n abbreviation: 'ME'\r\n },\r\n {\r\n name: 'Marshall Islands',\r\n abbreviation: 'MH'\r\n },\r\n {\r\n name: 'Maryland',\r\n abbreviation: 'MD'\r\n },\r\n {\r\n name: 'Massachusetts',\r\n abbreviation: 'MA'\r\n },\r\n {\r\n name: 'Michigan',\r\n abbreviation: 'MI'\r\n },\r\n {\r\n name: 'Minnesota',\r\n abbreviation: 'MN'\r\n },\r\n {\r\n name: 'Mississippi',\r\n abbreviation: 'MS'\r\n },\r\n {\r\n name: 'Missouri',\r\n abbreviation: 'MO'\r\n },\r\n {\r\n name: 'Montana',\r\n abbreviation: 'MT'\r\n },\r\n {\r\n name: 'Nebraska',\r\n abbreviation: 'NE'\r\n },\r\n {\r\n name: 'Nevada',\r\n abbreviation: 'NV'\r\n },\r\n {\r\n name: 'New Hampshire',\r\n abbreviation: 'NH'\r\n },\r\n {\r\n name: 'New Jersey',\r\n abbreviation: 'NJ'\r\n },\r\n {\r\n name: 'New Mexico',\r\n abbreviation: 'NM'\r\n },\r\n {\r\n name: 'New York',\r\n abbreviation: 'NY'\r\n },\r\n {\r\n name: 'North Carolina',\r\n abbreviation: 'NC'\r\n },\r\n {\r\n name: 'North Dakota',\r\n abbreviation: 'ND'\r\n },\r\n {\r\n name: 'Northern Mariana Islands',\r\n abbreviation: 'MP'\r\n },\r\n {\r\n name: 'Ohio',\r\n abbreviation: 'OH'\r\n },\r\n {\r\n name: 'Oklahoma',\r\n abbreviation: 'OK'\r\n },\r\n {\r\n name: 'Oregon',\r\n abbreviation: 'OR'\r\n },\r\n {\r\n name: 'Palau',\r\n abbreviation: 'PW'\r\n },\r\n {\r\n name: 'Pennsylvania',\r\n abbreviation: 'PA'\r\n },\r\n {\r\n name: 'Puerto Rico',\r\n abbreviation: 'PR'\r\n },\r\n {\r\n name: 'Rhode Island',\r\n abbreviation: 'RI'\r\n },\r\n {\r\n name: 'South Carolina',\r\n abbreviation: 'SC'\r\n },\r\n {\r\n name: 'South Dakota',\r\n abbreviation: 'SD'\r\n },\r\n {\r\n name: 'Tennessee',\r\n abbreviation: 'TN'\r\n },\r\n {\r\n name: 'Texas',\r\n abbreviation: 'TX'\r\n },\r\n {\r\n name: 'Utah',\r\n abbreviation: 'UT'\r\n },\r\n {\r\n name: 'Vermont',\r\n abbreviation: 'VT'\r\n },\r\n {\r\n name: 'Virgin Islands',\r\n abbreviation: 'VI'\r\n },\r\n {\r\n name: 'Virginia',\r\n abbreviation: 'VA'\r\n },\r\n {\r\n name: 'Washington',\r\n abbreviation: 'WA'\r\n },\r\n {\r\n name: 'West Virginia',\r\n abbreviation: 'WV'\r\n },\r\n {\r\n name: 'Wisconsin',\r\n abbreviation: 'WI'\r\n },\r\n {\r\n name: 'Wyoming',\r\n abbreviation: 'WY'\r\n }\r\n];\r\n\r\nexport default states;\r\n","import Text from './Text';\r\nimport theme from './themes/theme';\r\n\r\nconst Heading = Text.withComponent('h3');\r\n\r\nHeading.defaultProps = {\r\n fontWeight: 'bold',\r\n fontSize: 4,\r\n theme: theme,\r\n fontFamily: theme.fontPrimary\r\n};\r\n\r\nHeading.displayName = 'Heading';\r\n\r\nHeading.H1 = Heading.withComponent('h1');\r\nHeading.H1.defaultProps = {\r\n fontSize: 6,\r\n fontWeight: 'bold',\r\n theme: theme,\r\n fontFamily: theme.fontPrimary\r\n};\r\n\r\nHeading.H2 = Heading.withComponent('h2');\r\nHeading.H2.defaultProps = {\r\n fontSize: 5,\r\n fontWeight: 'bold',\r\n theme: theme,\r\n fontFamily: theme.fontPrimary\r\n};\r\n\r\nHeading.H3 = Heading.withComponent('h3');\r\nHeading.H3.defaultProps = {\r\n fontSize: 8,\r\n fontWeight: 'bold',\r\n theme: theme,\r\n fontFamily: theme.fontMontBold\r\n};\r\n\r\nHeading.H4 = Heading.withComponent('h4');\r\nHeading.H4.defaultProps = {\r\n fontSize: 1,\r\n theme: theme,\r\n fontFamily: theme.fontMontBlack\r\n};\r\n\r\nHeading.H5 = Heading.withComponent('h5');\r\nHeading.H5.defaultProps = {\r\n fontSize: 7,\r\n fontWeight: 'bold',\r\n theme: theme,\r\n fontFamily: theme.fontOswaldBold\r\n};\r\n\r\nHeading.H6 = Heading.withComponent('h6');\r\nHeading.H6.defaultProps = {\r\n fontSize: 0,\r\n fontWeight: 'bold',\r\n theme: theme,\r\n fontFamily: theme.fontPrimary\r\n};\r\n\r\nexport default Heading;\r\n","// LeadGen action types\r\n\r\nconst leadGenActionTypes = {\r\n IS_LEADGEN_PROCESSING_TYPE: 'IS_LEADGEN_PROCESSING_TYPE',\r\n SET_LEADGEN_IS_ALREADY_SHOWN: 'SET_LEADGEN_IS_ALREADY_SHOWN',\r\n RESET_LEADGEN_STATUS: 'RESET_LEADGEN_STATUS'\r\n};\r\n\r\nexport default leadGenActionTypes;\r\n","import styled, { css } from 'styled-components';\r\nimport theme from '../ui-kit/themes/theme';\r\nimport ModalAdapter from './ModalAdapter';\r\n\r\nconst StyledModal = styled(ModalAdapter).attrs({\r\n overlayClassName: 'Overlay',\r\n modalClassName: 'Modal',\r\n closeTimeoutMS: 250\r\n})`\r\n .Overlay {\r\n position: fixed;\r\n top: ${props => (props.fullSizeContent && props.fullSizeContentTop ? `${props.fullSizeContentTop}px` : 0)};\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: ${props =>\r\n props.fullSizeContent && props.fullSizeBackgroundColor\r\n ? props.fullSizeBackgroundColor\r\n : `${theme.colors.deepLakeBlue[100]}80`};\r\n transition: opacity 0.25s ease-in-out;\r\n z-index: ${props => (props.zIndex ? props.zIndex : theme.zIndex.loader)};\r\n opacity: 0;\r\n }\r\n\r\n .ReactModal__Overlay--after-open {\r\n opacity: 1;\r\n }\r\n\r\n .ReactModal__Overlay--before-close {\r\n opacity: 0;\r\n }\r\n\r\n .Modal {\r\n ${props => props.width && `width : ${props.width};`}\r\n ${props => props.height && `height : ${props.height};`}\r\n ${props => props.maxWidth && `max-width : ${props.maxWidth};`}\r\n ${props => props.marginTop && `margin-top : ${props.marginTop};`}\r\n outline: none;\r\n max-height: 100%;\r\n\r\n ${({ fullSizeContent }) => {\r\n if (fullSizeContent) {\r\n return css`\r\n width: 100%;\r\n height: 100%;\r\n background: ${props =>\r\n props.fullSizeBackgroundColor ? props.fullSizeBackgroundColor : props.theme.colors.nightSkyBlack[100]};\r\n `;\r\n }\r\n\r\n return css`\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n position: absolute;\r\n background: ${props => props.theme.colors.pureWhite[0]};\r\n overflow: auto;\r\n -webkit-overflow-scrolling: touch;\r\n padding: ${props => (props.padding ? props.padding : 0)};\r\n box-shadow: ${props => props.theme.boxShadows[3]};\r\n border-radius: ${props => (props.borderRadius ? props.borderRadius : '8px')};\r\n `;\r\n }}\r\n }\r\n`;\r\n\r\nStyledModal.displayName = 'StyledModal';\r\n\r\nStyledModal.defaultProps = {\r\n theme: theme,\r\n padding: '30px'\r\n};\r\n\r\nexport default StyledModal;\r\n","import React from 'react';\r\nimport Modal from 'react-modal';\r\n\r\nconst ModalAdapter = ({ className, modalClassName, ...props }) => {\r\n return (\r\n \r\n );\r\n};\r\n\r\nexport default ModalAdapter;\r\n","export const isPayPalEnabled = (enabledAt, property) => {\r\n if (enabledAt) {\r\n var list = enabledAt.split(',');\r\n return list.includes(property);\r\n }\r\n};\r\n","// Booking Engine Alert action types\r\n\r\nconst bookingEngineAlertActionTypes = {\r\n SET_BOOK_ENGINE_ALERT_IS_SUCCESSFUL: 'SET_BOOK_ENGINE_ALERT_IS_SUCCESSFUL',\r\n SET_BOOK_ENGINE_ALERT_IS_LOADING: 'SET_BOOK_ENGINE_ALERT_IS_LOADING',\r\n SET_BOOK_ENGINE_ALERT_GOT_ERROR: 'SET_BOOK_ENGINE_ALERT_GOT_ERROR'\r\n};\r\n\r\nexport default bookingEngineAlertActionTypes;\r\n","// Current Lodge action types\r\n\r\nconst currentLodgeActionTypes = {\r\n UPDATE_CURRENT_LODGE: 'UPDATE_CURRENT_LODGE'\r\n};\r\n\r\nexport default currentLodgeActionTypes;\r\n","const flowActionTypes = {\r\n FETCH_FLOW_STEPS_REQUEST: 'FETCH_FLOW_STEPS_REQUEST',\r\n FETCH_FLOW_STEPS_SUCCESS: 'FETCH_FLOW_STEPS_SUCCESS',\r\n FETCH_FLOW_STEPS_FAILURE: 'FETCH_FLOW_STEPS_FAILURE'\r\n};\r\n\r\nexport default flowActionTypes;\r\n","// Guests action types\r\n\r\nconst guestsModalActionTypes = {\r\n SET_GUESTS_ADULTS_COUNT: 'SET_GUESTS_ADULTS_COUNT',\r\n SET_GUESTS_KIDS_COUNT: 'SET_GUESTS_KIDS_COUNT',\r\n SET_GUESTS_KIDS_AGES: 'SET_GUESTS_KIDS_AGES'\r\n};\r\n\r\nexport default guestsModalActionTypes;\r\n","// IEModal action types\r\n\r\nconst ieModalActionTypes = {\r\n SET_IEMODAL_IS_ALREADY_SHOWN: 'SET_IEMODAL_IS_ALREADY_SHOWN'\r\n};\r\n\r\nexport default ieModalActionTypes;\r\n","// Offer reducer\r\n\r\nimport AuthClient from '../../../api/auth/AuthClient';\r\n\r\nimport {\r\n OFFERS_ACTIONS,\r\n offerEventBuilder\r\n} from '../../../infrastructure/middleware/analytics/analyticsObjectBuilders';\r\nimport { pushEvent } from '../../../utilities/dataLayerUtils';\r\nimport { initializeState } from '../../../utilities/storageUtils';\r\nimport offerActionTypes from './offer.types';\r\n\r\nconst authClient = new AuthClient();\r\n\r\nexport const getDefaultOfferCode = (fallbackValue = '') => {\r\n const isUserLoggedIn = authClient.isLoggedIn();\r\n const promoCodeList = window.promoCodeList ? JSON.parse(window.promoCodeList) : [];\r\n const relatedOfferCode = promoCodeList.find(item => item.promoCode === window.dealPromoCode);\r\n const isGatedOffer = relatedOfferCode && JSON.parse(relatedOfferCode.isExclusive);\r\n\r\n if (isGatedOffer && !isUserLoggedIn) {\r\n return fallbackValue;\r\n }\r\n\r\n return window.dealPromoCode || fallbackValue;\r\n};\r\n\r\nconst INITIAL_STATE = {\r\n code: getDefaultOfferCode(),\r\n description: '',\r\n validOffer: false,\r\n errorMessage: '',\r\n activeOffers: [],\r\n emailOffers: []\r\n};\r\n\r\nconst offerReducer = (state, action) => {\r\n state = initializeState(state, INITIAL_STATE);\r\n\r\n switch (action.type) {\r\n case offerActionTypes.ADD_OFFER_CODE:\r\n return { ...state, code: action.code };\r\n case offerActionTypes.SET_OFFER_CODE_DESCRIPTION:\r\n return {\r\n ...state,\r\n description: action.description,\r\n validOffer: action.description ? true : false,\r\n errorMessage: ''\r\n };\r\n case offerActionTypes.REMOVE_OFFER_CODE:\r\n return {\r\n ...state,\r\n code: ''\r\n };\r\n case offerActionTypes.CREATE_OFFER_ERROR:\r\n return {\r\n ...state,\r\n validOffer: false,\r\n errorMessage: action.errorMessage,\r\n description: ''\r\n };\r\n case offerActionTypes.ADD_OFFER_ACTIVE_TYPE: {\r\n const eventObject = offerEventBuilder(OFFERS_ACTIONS.ADD, {\r\n resortLocation: action.offerData.resortLocation,\r\n name: action.offerData.title,\r\n value: -action.offerData.dollarValue\r\n });\r\n pushEvent(eventObject);\r\n const activeOffers = [...state.activeOffers];\r\n if (!activeOffers.includes(action.offerData.id)) {\r\n activeOffers.push(action.offerData.id);\r\n return { ...state, activeOffers: activeOffers };\r\n }\r\n return state;\r\n }\r\n case offerActionTypes.ADD_OFFER_EMAIL_ACTIVE_TYPE: {\r\n const emailOffers = [...state.emailOffers];\r\n if (!emailOffers.includes(action.offerData.id)) {\r\n emailOffers.push(action.offerData.id);\r\n return { ...state, emailOffers: emailOffers };\r\n }\r\n return state;\r\n }\r\n case offerActionTypes.REMOVE_OFFER_ACTIVE_TYPE: {\r\n const eventObject = offerEventBuilder(OFFERS_ACTIONS.REMOVE, {\r\n resortLocation: action.offerData.resortLocation,\r\n name: action.offerData.title,\r\n value: -action.offerData.dollarValue\r\n });\r\n pushEvent(eventObject);\r\n const activeOffers = state.activeOffers.filter(offer => offer !== action.offerData.id);\r\n const activeEmailOffers = state.emailOffers.filter(offer => offer !== action.offerData.id);\r\n return { ...state, activeOffers: activeOffers, emailOffers: activeEmailOffers };\r\n }\r\n case offerActionTypes.REMOVE_OFFERS_ALL_ACTIVE_TYPE: {\r\n return { ...state, activeOffers: [], emailOffers: [] };\r\n }\r\n case offerActionTypes.VERIFY_ACTIVE_OFFERS: {\r\n const activeOffers = [...state.activeOffers];\r\n const currentUserOffers = action.offerData;\r\n const verifiedActiveOffer = activeOffers.filter(offerId =>\r\n currentUserOffers.some(offerObj => offerObj.id === offerId)\r\n );\r\n\r\n return { ...state, activeOffers: verifiedActiveOffer };\r\n }\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport default offerReducer;\r\n","// Current Lodge Actions\r\n\r\nimport { getResortLocationUrl } from '../../../utilities/resortLocation';\r\nimport currentLodgeActionTypes from './currentLodge.types';\r\n\r\nexport const updateCurrentLodge = lodges => dispatch => {\r\n const resortLocationUrl = getResortLocationUrl();\r\n\r\n const locationFromUrl = resortLocationUrl.replace(/\\//g, '');\r\n\r\n const currentLocationData = Object.values(lodges).find(location => location.url === locationFromUrl);\r\n\r\n if (currentLocationData) {\r\n dispatch({\r\n type: currentLodgeActionTypes.UPDATE_CURRENT_LODGE,\r\n resortData: currentLocationData,\r\n resortLocationUrl: resortLocationUrl\r\n });\r\n }\r\n};\r\n","import { ASSETS_LOCATIONS, getAssetsUrl } from '../../../utilities/constants';\r\n\r\nexport const DINING_CREDIT = {\r\n 50: getAssetsUrl(ASSETS_LOCATIONS.SVG, '50.svg'),\r\n 100: getAssetsUrl(ASSETS_LOCATIONS.SVG, '100.svg'),\r\n 150: getAssetsUrl(ASSETS_LOCATIONS.SVG, '150.svg'),\r\n 300: getAssetsUrl(ASSETS_LOCATIONS.SVG, '300.svg'),\r\n star: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'star.svg'),\r\n rArrow: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'core-icons-arrows-caret-right.svg'),\r\n greyDiningImage: getAssetsUrl(ASSETS_LOCATIONS.WEBP, 'dining-illustrations@3x.webp'),\r\n yellowDiningImage: getAssetsUrl(ASSETS_LOCATIONS.WEBP, 'dining-illustrations-2@3x.webp'),\r\n big50: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'FlatIllustrations.svg'),\r\n big100: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'FlatIllustrations2.svg'),\r\n big150: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'FlatIllustrations3.svg'),\r\n big300: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'FlatIllustrations3.svg')\r\n};\r\n\r\nexport const DINING_CREDIT_COINS = [50, 100, 150, 300];\r\n\r\nexport const MODAL_CREDIT_CARDS_IMAGE = getAssetsUrl(ASSETS_LOCATIONS.SVG, 'icon-dining-type.svg');\r\n\r\nexport const MODAL_RESTAURANTS_CARDS_IMAGE = getAssetsUrl(ASSETS_LOCATIONS.SVG, 'icon-dining-restaurant.svg');\r\n\r\nexport const MODAL_CREDIT_CARDS_IMAGE_MOBILE = getAssetsUrl(ASSETS_LOCATIONS.SVG, 'icon-dining-type-mobile.svg');\r\n\r\nexport const MODAL_RESTAURANTS_CARDS_IMAGE_MOBILE = getAssetsUrl(\r\n ASSETS_LOCATIONS.SVG,\r\n 'icon-dining-restaurant-mobile.svg'\r\n);\r\n","import colors from '../ui-kit/themes/colors';\r\n\r\n// ineligibilityReason\r\nexport const INELIGIBILITY_REASONS = {\r\n TOO_EARLY: 'TOO_EARLY', // The reservation isnt due the next 24h.\r\n PRE_CHECKED_IN: 'PRE_CHECKED_IN', // User has already done online check-in.\r\n OTHER: 'OTHER' // Nor1 Api hasn't synced..\r\n};\r\n\r\nexport const CHECK_IN_MESSAGES = {\r\n available: {\r\n description: 'Mobile pre check-in is available now!',\r\n color: colors.nightSkyBlack[80]\r\n },\r\n unavailable: {\r\n description: 'Mobile pre check-in will be available 48 hours prior to your reservation.',\r\n color: colors.nightSkyBlack[80]\r\n },\r\n successful: {\r\n title: 'Mobile pre check-in successful!',\r\n description: 'Check your email to see more information',\r\n color: colors.deepForestGreen[100]\r\n },\r\n invalid: {\r\n title: 'Your reservation is not valid for mobile pre check-in',\r\n description: 'Please check-in at the lodge when you arrive',\r\n color: colors.errorOrange\r\n },\r\n mobile: {\r\n description: 'Mobile pre check-in will be available 48 hours before you arrive via email and SMS',\r\n color: colors.nightSkyBlack[80]\r\n }\r\n};\r\n\r\nexport const ICON_STYLES = {\r\n size: '21px',\r\n color: colors.preciousStoneBlue[100]\r\n};\r\n","import React from 'react';\r\nimport Text from './Text';\r\nimport styled from 'styled-components';\r\nimport theme from './themes/theme';\r\nimport ArrowDownThinIcon from './icons/ArrowDownThin';\r\nimport { Flex } from '.';\r\n// PlusMinus :before psuedoElement is purposely not found here\r\n// It is instead defined in App.js createGlobalStyle since it is the only way to hook into 'aria-...'\r\nconst StyledTitleText = styled(Text)`\r\n font-size: ${props => (props.fontSize && props.fontSize) || '12px'};\r\n line-height: 1.8;\r\n font-weight: bold;\r\n display: inline-block;\r\n font-family: ${theme.fontSecondary};\r\n cursor: pointer;\r\n color: ${props => props.color || theme.colors.digitalBrightRed[100]};\r\n`;\r\n\r\nconst StyledContent = styled(Text)`\r\n font-size: ${props => (props.fontSize && props.fontSize) || '12px'};\r\n font-family: ${theme.fontSecondary};\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n align-content: center;\r\n margin: ${theme.space[2]}px;\r\n`;\r\n\r\nexport const DescriptionIcon = styled(ArrowDownThinIcon)`\r\n transition-duration: 0.4s;\r\n transition-property: transform;\r\n transform: rotate(${props => props.rotate || '0deg'});\r\n height: 12px;\r\n width: 36px;\r\n align-self: center;\r\n padding-left: ${theme.space[1]}px;\r\n padding-right: ${theme.space[1]}px;\r\n`;\r\n\r\nexport const AccordionTitleTextRetro = props => {\r\n const { children, expanded, ...rest } = props;\r\n return (\r\n \r\n \r\n {children}\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const AccordionContentRetro = props => {\r\n const { children, ...rest } = props;\r\n return {children};\r\n};\r\n\r\nAccordionTitleTextRetro.defaultProps = {\r\n color: theme.colors.digitalBrightRed[100]\r\n};\r\n","import StringMask from 'string-mask';\r\nimport { MASK, PHONE_MASK_REGEX } from '../utilities/constants';\r\nimport unmaskValue from '../components/utilities/unmaskValue';\r\n\r\nexport const maskPhone = str => {\r\n const unmaskedValue = unmaskValue(str, PHONE_MASK_REGEX);\r\n const formatted = StringMask.process(unmaskedValue, MASK);\r\n return formatted.result;\r\n};\r\n","/**\r\n * Method to create a delay of @param delay milliseconds.\r\n * @param {number} delay Amount of milliseconds to wait for.\r\n * @returns A promise that is self-resolved within the specified delay.\r\n */\r\nexport const waitFor = delay => new Promise(resolve => setTimeout(resolve, delay));\r\n","export { default as Modal, MODAL_VARIATIONS } from './Modal';\r\nexport { default as ModalSpinner } from './ModalSpinner';\r\nexport { default as ModalAdapter } from './ModalAdapter';\r\nexport { default as styles } from './styles';\r\nexport * from './MediaGalleryModal';\r\n","import { Link as ReactRouterLink } from 'react-router-dom';\r\nimport styled, { css } from 'styled-components';\r\nimport { space, themeGet } from 'styled-system';\r\nimport { Absolute, Box, Button, Card, Flex, Relative, Text } from '../../components/ui-kit';\r\nimport { FlexCard } from '../../components/ui-kit/Card';\r\nimport CloseCircleIcon from '../../components/ui-kit/icons/CloseCircle';\r\nimport theme, { colors, fontWeights, mediaQueries } from '../../components/ui-kit/themes/theme';\r\nimport { IMAGES } from './constants';\r\n\r\nexport const WaveWrapper = styled(Relative)`\r\n margin-left: 0;\r\n padding-top: 80px;\r\n padding-bottom: 40px;\r\n left: auto;\r\n width: 100%;\r\n\r\n background-image: url(${IMAGES.waveSVG}),\r\n linear-gradient(\r\n to bottom,\r\n ${themeGet('colors.preciousStoneBlue.100')} -55%,\r\n ${themeGet('colors.deepLakeBlue.100')} 97%\r\n );\r\n background-repeat: repeat-x;\r\n background-position: -90px top;\r\n background-size: 430px, 100%;\r\n\r\n ${themeGet('mediaQueries.lg')} {\r\n background-position: -170px top;\r\n padding-top: 96px;\r\n }\r\n\r\n ${themeGet('mediaQueries.xl')} {\r\n background-size: 375px, 100%;\r\n background-position: -100px top;\r\n padding-top: 70px;\r\n padding-bottom: 45px;\r\n margin-top: 32px;\r\n }\r\n`;\r\n\r\nexport const MobileAppDevice = styled.img`\r\n width: 100%;\r\n`;\r\n\r\nexport const AppFeaturesWrapper = styled.ul`\r\n padding-left: 0;\r\n font-family: ${theme.fontSecondary};\r\n font-size: ${theme.fontSizes[1]}px;\r\n font-weight: ${fontWeights.medium};\r\n line-height: 2;\r\n color: ${theme.colors.deepLakeBlue[100]};\r\n list-style: none;\r\n\r\n li::before {\r\n content: '• ';\r\n color: ${theme.colors.digitalBrightRed[100]};\r\n font-weight: ${fontWeights.extraBold};\r\n font-size: ${theme.fontSizes[3]}px;\r\n }\r\n`;\r\n\r\nexport const AppStoreButtonWrapper = styled.a`\r\n display: block;\r\n\r\n img {\r\n display: block;\r\n max-height: 40px;\r\n }\r\n`;\r\n\r\nexport const StyledCloseCircleIcon = styled(CloseCircleIcon)`\r\n ${space}\r\n`;\r\n\r\nexport const Link = styled(ReactRouterLink)`\r\n text-decoration: none;\r\n color: ${colors.woodpeckerRed[100]};\r\n`;\r\n\r\nexport const CloseButton = styled.button`\r\n cursor: pointer;\r\n border: none;\r\n background: transparent;\r\n position: absolute;\r\n right: 5px;\r\n top: 6px;\r\n`;\r\n\r\nexport const PackageCard = styled(Flex).attrs({\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n justifyContent: 'start'\r\n})`\r\n padding-bottom: 20px;\r\n border-bottom: 1px solid ${themeGet('colors.snowMountainGrey.100')};\r\n padding-left: ${themeGet('space.3')}px;\r\n padding-right: ${themeGet('space.3')}px;\r\n width: 100%;\r\n\r\n :not(:last-child) {\r\n margin-bottom: 20px;\r\n }\r\n\r\n .slider-list {\r\n min-height: 145px;\r\n }\r\n\r\n ${theme.mediaQueries.xl} {\r\n width: 284px;\r\n margin-bottom: 20px;\r\n border: none;\r\n padding-left: 24px;\r\n padding-right: 24px;\r\n padding-bottom: 0;\r\n }\r\n\r\n ${theme.mediaQueries.xxl} {\r\n width: 284px;\r\n margin-bottom: 0;\r\n\r\n :not(:last-child) {\r\n margin-bottom: 0;\r\n }\r\n }\r\n`;\r\n\r\nPackageCard.displayName = 'PackageCard';\r\n\r\nexport const PackageCardItem = styled(Flex).attrs({\r\n flexDirection: 'column',\r\n alignItems: 'flex-start',\r\n justifyContent: 'space-between'\r\n})`\r\n margin-top: 10px;\r\n overflow: hidden;\r\n`;\r\n\r\nexport const InfoCardAddOnsWrapper = styled(Card)`\r\n display: block;\r\n position: relative;\r\n border-radius: 15px;\r\n border: none;\r\n background-color: rgba(255, 255, 255, 0.18);\r\n width: ${({ carouselWidth }) => {\r\n return carouselWidth ? `${carouselWidth}px` : 'clamp(164px, 100%, 277px)';\r\n }};\r\n &:before {\r\n content: '';\r\n background-image: url(\"data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='15' ry='15' stroke='white' stroke-width='2' stroke-dasharray='5%2c 8' stroke-dashoffset='3' stroke-linecap='square'/%3e%3c/svg%3e\");\r\n background-size: cover;\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n opacity: 0.3;\r\n }\r\n > a {\r\n position: absolute;\r\n width: 100%;\r\n height: 100%;\r\n top: 0;\r\n left: 0;\r\n display: block;\r\n\r\n cursor: pointer;\r\n transition: 0.2s background ease-in-out;\r\n :hover {\r\n background: ${themeGet('colors.deepLakeBlue.100')};\r\n ${Text} {\r\n transition: 0.2s color ease-in-out;\r\n color: ${themeGet('colors.pureWhite.0')};\r\n }\r\n\r\n svg {\r\n transition: 0.2s fill ease-in-out;\r\n fill: ${themeGet('colors.pureWhite.0')};\r\n }\r\n }\r\n }\r\n`;\r\n\r\nexport const InfoCardBody = styled(Absolute)`\r\n top: 50%;\r\n width: 100%;\r\n transform: translateY(-50%);\r\n`;\r\n\r\nexport const TitleField = styled(Text)`\r\n font-weight: bold;\r\n text-align: center;\r\n font-size: ${theme.fontSizes[9]}px;\r\n line-height: ${theme.fontSizes[1]}px;\r\n padding-top: 0px;\r\n color: ${theme.colors.deepLakeBlue[100]};\r\n padding-bottom: 1px;\r\n\r\n ${mediaQueries.lg} {\r\n padding-top: 2px;\r\n font-size: ${theme.fontSizes[1]}px;\r\n line-height: ${theme.fontSizes[7]}px;\r\n }\r\n`;\r\n\r\nexport const SeeAllCTA = styled(Text)`\r\n cursor: pointer;\r\n text-decoration: underline;\r\n color: ${theme.colors.preciousStoneBlue[100]};\r\n font-size: ${theme.fontSizes[0]}px;\r\n line-height: ${theme.fontSizes[2]}px;\r\n\r\n ${mediaQueries.lg} {\r\n font-size: ${theme.fontSizes[1]}px;\r\n line-height: ${theme.fontSizes[7]}px;\r\n }\r\n`;\r\n\r\nexport const DescriptionText = styled(Text)`\r\n display: -webkit-box;\r\n -webkit-line-clamp: 4;\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n p {\r\n margin: 8px 0;\r\n }\r\n`;\r\n\r\nexport const FlexCardPackage = styled(FlexCard)`\r\n overflow-y: auto;\r\n padding: ${themeGet('space.3')}px 0 0 0;\r\n\r\n ${mediaQueries.lg} {\r\n padding: ${themeGet('space.3')}px ${themeGet('space.2')}px;\r\n }\r\n ${mediaQueries.xl} {\r\n padding: ${themeGet('space.3')}px ${themeGet('space.3')}px;\r\n }\r\n`;\r\n\r\nexport const CloseModalButton = styled.button`\r\n background: none;\r\n cursor: pointer;\r\n color: ${colors.preciousStoneBlue[100]};\r\n position: absolute;\r\n right: 0;\r\n top: 22px;\r\n z-index: 10;\r\n padding: 10px 32px;\r\n border: none;\r\n :hover {\r\n border: none;\r\n color: ${colors.blue};\r\n }\r\n\r\n @media (max-width: 390px) {\r\n top: 14px;\r\n }\r\n`;\r\n\r\nexport const CloseModalButtonText = styled(Text)`\r\n height: 16px;\r\n width: 16px;\r\n font-size: 16px;\r\n`;\r\n\r\nexport const PackageInfo = styled(FlexCard)`\r\n overflow-y: auto;\r\n`;\r\n\r\nexport const PackageDetailsContainerModal = styled(Box)`\r\n overflow: auto;\r\n width: 100%;\r\n\r\n ul {\r\n width: auto;\r\n padding: 0;\r\n list-style-type: none;\r\n\r\n > li {\r\n font-family: Montserrat;\r\n font-size: ${themeGet('fontSizes.1')}px;\r\n font-weight: ${themeGet('fontWeights.medium')};\r\n line-height: 1.71;\r\n color: ${themeGet('colors.deepLakeBlue.100')};\r\n position: relative;\r\n padding-left: ${themeGet('space.3')}px;\r\n margin-bottom: ${themeGet('space.1')}px;\r\n\r\n &:before {\r\n content: '';\r\n position: absolute;\r\n display: inline;\r\n left: 0;\r\n top: 8px;\r\n border-radius: 50%;\r\n width: 6px;\r\n height: 6px;\r\n background-color: ${themeGet('colors.successGreen')};\r\n }\r\n }\r\n }\r\n`;\r\n\r\nexport const PackageCardText = styled(Text)`\r\n width: 100%;\r\n`;\r\n\r\nexport const ChargeTypeText = styled(Text)`\r\n width: 100%;\r\n font-size: ${themeGet('fontSizes.0')}px;\r\n font-weight: ${themeGet('fontWeights.bold')};\r\n color: ${themeGet('colors.deepLakeBlue.100')};\r\n margin-bottom: 12px;\r\n`;\r\n\r\nexport const PackageCardDescription = styled(Text)`\r\n width: 100%;\r\n padding-left: 0px;\r\n overflow: hidden;\r\n font-size: ${themeGet('fontSizes.1')}px;\r\n line-height: 1.71;\r\n`;\r\n\r\nexport const PackageCardDescriptionCollapsible = styled(Text)`\r\n width: 100%;\r\n padding-left: 8px;\r\n overflow: hidden;\r\n font-size: ${themeGet('fontSizes.1')}px;\r\n line-height: 1.71;\r\n`;\r\n\r\nexport const CabanaDetailsCardDescription = styled(Text)`\r\n margin: 0;\r\n min-height: 50px;\r\n max-height: 100px;\r\n width: 100%;\r\n line-height: 1.67;\r\n\r\n & > p {\r\n margin: 0;\r\n }\r\n`;\r\n\r\nexport const PackageCardButtonContainer = styled(Flex)`\r\n border-top-style: outset;\r\n border-top-color: ${themeGet('colors.snowMountainGrey.100')};\r\n border-top-width: 1px;\r\n margin-top: auto;\r\n padding-top: 12px;\r\n flex-direction: column;\r\n`;\r\n\r\nexport const CabanaCardButtonContainer = styled(Box)`\r\n padding: ${themeGet('space.3')}px;\r\n padding-bottom: 0;\r\n border-top: 1px solid ${themeGet('colors.snowMountainGrey.100')};\r\n opacity: ${props => (props.isAvailable ? 'initial' : '0.7')};\r\n pointer-events: ${props => (props.isAvailable ? 'initial' : 'none')};\r\n`;\r\n\r\nexport const DetailsButtonContainer = styled(Box)`\r\n background-color: ${themeGet('colors.kiddiePoolBlue.10')};\r\n padding: ${themeGet('space.7')}px ${themeGet('space.4')}px;\r\n position: absolute;\r\n bottom: 0;\r\n ${props => {\r\n if (props.alignLeft) {\r\n return `\r\n width: 330px;\r\n left: 0;\r\n `;\r\n } else {\r\n return `\r\n width: 50%;\r\n right: 0;\r\n `;\r\n }\r\n }}\r\n`;\r\n\r\nexport const CabanaCard = styled(FlexCard)`\r\n border-radius: 0;\r\n box-shadow: ${themeGet('elevation.3')};\r\n margin-bottom: 32px;\r\n\r\n ${mediaQueries.lg} {\r\n max-width: 50%;\r\n border-radius: 15px;\r\n box-shadow: ${themeGet('elevation.3')};\r\n margin: ${themeGet('space.2')}px;\r\n flex: 27%;\r\n max-width: calc(33.3% - 16px);\r\n min-width: calc(33.3% - 16px);\r\n }\r\n`;\r\n\r\nexport const PackageContainer = styled(FlexCard)`\r\n position: relative;\r\n overflow: visible;\r\n min-height: 400px;\r\n`;\r\n\r\nexport const PackageContainerMobile = styled(FlexCard)`\r\n position: relative;\r\n overflow: visible;\r\n @media (max-width: 375px) {\r\n height: 150px;\r\n }\r\n`;\r\n\r\nexport const QuantityButton = styled(FlexCard)`\r\n background-color: ${themeGet('colors.preciousStoneBlue.100')};\r\n cursor: pointer;\r\n`;\r\n\r\nexport const PassDetailsNavigatorMobile = styled(FlexCard)`\r\n background: ${props => props.themeColor};\r\n border-radius: 0 10px 10px 0;\r\n`;\r\n\r\nexport const PassCardHeaderMobile = styled(Text)`\r\n line-height: 1.2;\r\n font-size: ${themeGet('fontSizes.3')}px;\r\n font-family: 'Montserrat', 'Helvetica Neue', Helvetica, Arial, sans-serif;\r\n font-weight: bold;\r\n @media (max-width: 375px) {\r\n font-size: ${themeGet('fontSizes.2')}px;\r\n }\r\n`;\r\n\r\nexport const PassDetailsImageContainer = styled(FlexCard)`\r\n background-color: ${themeGet('colors.snowMountainGrey.20')};\r\n`;\r\n\r\nexport const PackageDetailsContainerMobile = styled(Box)`\r\n ul {\r\n padding-left: 18px;\r\n }\r\n p {\r\n padding-left: 18px;\r\n }\r\n`;\r\n\r\nexport const CMPInfoBoxesWrapper = styled(Box)`\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: ${theme.space[3]}px;\r\n row-gap: 30px;\r\n\r\n ${theme.mediaScreens.tablet`\r\n row-gap: 36px;\r\n `}\r\n ${theme.mediaScreens.desktop`\r\n gap: 30px;\r\n grid-template-columns: repeat(4, 1fr);\r\n `}\r\n`;\r\n\r\nexport const CMPInfoBox = styled(Box)`\r\n position: relative;\r\n`;\r\n\r\nexport const AddCabanaButton = styled(Button)`\r\n opacity: ${props => (props.isDateSelected ? 'initial' : '0.5')};\r\n pointer-events: ${props => (props.isDateSelected ? '' : 'none')};\r\n white-space: nowrap;\r\n padding: 10px 40px;\r\n ${mediaQueries.sm} {\r\n padding: 10px 40px;\r\n }\r\n ${mediaQueries.lg} {\r\n padding: 10px 10px;\r\n }\r\n ${mediaQueries.xl} {\r\n padding: 10px 30px;\r\n }\r\n`;\r\n\r\nexport const HeaderInfoContainer = styled(Flex)`\r\n justify-content: 'flex-start';\r\n width: 100%;\r\n\r\n ${mediaQueries.xl} {\r\n width: 688px;\r\n justify-content: flex-end;\r\n }\r\n\r\n ${mediaQueries.xxl} {\r\n }\r\n`;\r\n\r\nHeaderInfoContainer.displayName = 'HeaderInfoContainer';\r\n\r\nexport const StyledImage = styled.img`\r\n width: 64px;\r\n height: 64px;\r\n\r\n ${mediaQueries.lg} {\r\n width: 80px;\r\n height: 80px;\r\n }\r\n`;\r\n\r\nexport const PackageDetailsImage = styled.img`\r\n object-fit: cover;\r\n width: 100%;\r\n top: 0;\r\n height: auto;\r\n z-index: -1;\r\n ${mediaQueries.xl} {\r\n height: 100%;\r\n width: auto !important;\r\n position: absolute;\r\n }\r\n`;\r\n\r\nexport const MobileCardText = styled(Text.P)`\r\n @media (max-width: 375px) {\r\n font-size: ${themeGet('fontSizes.0')}px;\r\n margin: 4px 0;\r\n & > p {\r\n font-size: ${themeGet('fontSizes.0')}px;\r\n }\r\n }\r\n & > p {\r\n margin: 0;\r\n }\r\n`;\r\n\r\nexport const CapitalizeTextModal = styled(Text)`\r\n text-transform: capitalize;\r\n line-height: 20px;\r\n`;\r\n\r\nexport const Headline = styled(Text)`\r\n display: flex;\r\n justify-content: flex-start;\r\n font-size: ${themeGet('fontSizes.3')}px;\r\n margin-bottom: 35px;\r\n font-weight: ${themeGet('fontWeights.bold')};\r\n color: ${themeGet('colors.preciousStoneBlue.100')};\r\n line-height: 24px;\r\n ${mediaQueries.sm} {\r\n justify-content: center;\r\n font-size: ${themeGet('fontSizes.4')}px;\r\n margin-bottom: 60px;\r\n line-height: 32px;\r\n }\r\n`;\r\n\r\nexport const HowToRedeemText = styled(Text)`\r\n font-weight: 500;\r\n font-size: ${themeGet('fontSizes.1')}px;\r\n color: ${themeGet('colors.nightSkyBlack.100')};\r\n width: 50%;\r\n line-height: 20px;\r\n`;\r\n\r\nexport const IconImage = styled.img`\r\n width: 64px;\r\n\r\n ${mediaQueries.xl} {\r\n width: 80px;\r\n }\r\n`;\r\n\r\nexport const Divider = styled.div`\r\n width: 100%;\r\n border-top: 1px solid ${theme.colors.snowMountainGrey[100]};\r\n margin: ${({ margin }) => (margin ? margin : '12px 0px')};\r\n`;\r\nexport const DividerVertical = styled.div`\r\n width: 4%;\r\n border-left: 1px solid ${theme.colors.snowMountainGrey[100]};\r\n height: 64px;\r\n margin-left: 24px;\r\n`;\r\n\r\nexport const DataIcon = styled.img`\r\n width: ${({ isMobile }) => (isMobile ? 30 : 45)}px;\r\n height: ${({ isMobile, imgException }) => (imgException ? imgException : isMobile ? 30 : 45)}px;\r\n margin-right: 25px;\r\n`;\r\n\r\nexport const InfoIcon = styled.img`\r\n width: 16px;\r\n height: 16px;\r\n margin-right: ${props => (props.smallerMargin ? 8 : 16)}px;\r\n`;\r\n\r\nexport const ModalTitle = styled(Text)`\r\n font-size: ${({ isMobile }) => (isMobile ? theme.fontSizes[7] : theme.fontSizes[4])}px;\r\n font-weight: ${theme.fontWeights.bold};\r\n color: ${theme.colors.deepLakeBlue[100]};\r\n line-height: ${({ isMobile }) => (isMobile ? theme.fontSizes[8] : theme.fontSizes[5])}px;\r\n margin-bottom: 33px;\r\n`;\r\nexport const DataTitle = styled(Text)`\r\n font-weight: ${theme.fontWeights.bold};\r\n color: ${({ showPackagesInAddGuestsModal }) =>\r\n showPackagesInAddGuestsModal ? theme.colors.nightSkyBlack[80] : theme.colors.deepLakeBlue[100]};\r\n font-size: ${theme.fontSizes[1]}px;\r\n line-height: 18px;\r\n\r\n ${mediaQueries.sm} {\r\n font-size: ${theme.fontSizes[7]}px;\r\n line-height: 24px;\r\n }\r\n`;\r\nexport const DataDescription = styled(Text)`\r\n font-size: ${theme.fontSizes[0]}px;\r\n font-weight: ${theme.fontWeights.medium};\r\n color: ${theme.colors.nightSkyBlack[80]};\r\n line-height: 18px;\r\n`;\r\n\r\nexport const RoomInclusionsSection = styled(Flex)`\r\n background-color: ${theme.colors.kiddiePoolBlue[10]};\r\n flex-direction: column;\r\n padding: 16px 36px;\r\n margin: 24px -36px;\r\n`;\r\n\r\nexport const CounterLabel = styled(Text)`\r\n font-size: ${({ isMobile }) => (isMobile ? theme.fontSizes[3] : theme.fontSizes[7])}px;\r\n font-weight: ${theme.fontWeights.bold};\r\n color: ${theme.colors.nightSkyBlack[80]};\r\n line-height: 24px;\r\n`;\r\n\r\nexport const CounterLabelDescription = styled(Text)`\r\n font-size: ${({ isMobile }) => (isMobile ? theme.fontSizes[9] : theme.fontSizes[0])}px;\r\n font-weight: ${theme.fontWeights.medium};\r\n color: ${theme.colors.deepLakeBlue[100]};\r\n line-height: ${({ isMobile }) => (isMobile ? theme.fontSizes[2] : theme.fontSizes[7])}px;\r\n`;\r\nexport const SelectDescription = styled(Text)`\r\n font-size: ${theme.fontSizes[1]}px;\r\n font-weight: ${theme.fontWeights.medium};\r\n color: ${theme.colors.nightSkyBlack[80]};\r\n line-height: 20px;\r\n`;\r\n\r\nexport const InfoAlertWrapper = styled(Flex)`\r\n align-items: flex-start;\r\n background-color: ${theme.colors.sandstoneBuff[20]};\r\n border: 1px solid ${theme.colors.digitalYellowOrange[100]};\r\n border-radius: 10px;\r\n padding: 12px 16px;\r\n margin: 25px 0;\r\n`;\r\n\r\nexport const NewGuestsBadgeContainer = styled.div`\r\n width: 40px;\r\n position: absolute;\r\n text-align: center;\r\n z-index: 100;\r\n margin-top: -10px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n ${mediaQueries.sm} {\r\n width: 45px;\r\n position: absolute;\r\n text-align: center;\r\n z-index: 100;\r\n margin-top: -10px;\r\n }\r\n`;\r\n\r\nexport const AddGuestsCTAButton = styled(Button)`\r\n padding: 8px 40px;\r\n ${mediaQueries.sm} {\r\n width: ${({ customWidth }) => customWidth}px;\r\n }\r\n width: calc(100% - 40px);\r\n margin-left: auto;\r\n margin-right: auto;\r\n`;\r\n\r\nexport const Total = styled(Text)`\r\n font-size: ${({ showPackagesInAddGuestsModal }) =>\r\n showPackagesInAddGuestsModal ? theme.fontSizes[1] : theme.fontSizes[7]}px;\r\n line-height: 18px;\r\n ${mediaQueries.sm} {\r\n font-size: ${theme.fontSizes[7]}px;\r\n line-height: 24px;\r\n }\r\n font-weight: ${theme.fontWeights.bold};\r\n color: ${({ showPackagesInAddGuestsModal }) =>\r\n showPackagesInAddGuestsModal ? theme.colors.nightSkyBlack[80] : theme.colors.deepLakeBlue[100]};\r\n`;\r\n\r\nexport const InclusionsTitle = styled(Text)`\r\n font-size: ${({ isMobile }) => (isMobile ? theme.fontSizes[0] : theme.fontSizes[1])}px;\r\n font-weight: ${theme.fontWeights.bold};\r\n color: ${theme.colors.nightSkyBlack[80]};\r\n line-height: ${({ isMobile }) => (isMobile ? '16px' : '20px')};\r\n`;\r\n\r\n// Info Cards\r\nexport const Image = styled.img`\r\n width: 64px;\r\n height: 64px;\r\n margin-bottom: 8px;\r\n ${mediaQueries.sm} {\r\n width: 80px;\r\n height: 80px;\r\n margin-bottom: 12px;\r\n }\r\n`;\r\n\r\nexport const AddCardsButtonContainer = styled(Box)`\r\n width: clamp(148px, 100%, 245px);\r\n max-width: calc(100% - 16px);\r\n margin: 0 auto;\r\n ${mediaQueries.md} {\r\n max-width: calc(100% - 32px);\r\n }\r\n`;\r\n\r\nexport const PlusInfoImgs = styled.img`\r\n width: 24px;\r\n height: 24px;\r\n ${mediaQueries.md} {\r\n width: 32px;\r\n height: 32px;\r\n }\r\n\r\n @media (max-width: 1024px) and (min-width: 768px) {\r\n width: 24px;\r\n height: 24px;\r\n }\r\n`;\r\n\r\nexport const LcoHeaderImageSection = styled(Box)`\r\n height: 210px;\r\n width: 100%;\r\n img {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n }\r\n ${theme.mediaQueries.md} {\r\n height: 250px;\r\n }\r\n`;\r\n\r\nexport const LcoContentSection = styled(Box)`\r\n padding: 24px 24px 0px;\r\n`;\r\n\r\nexport const LcoButtonsSection = styled(Flex)`\r\n align-items: center;\r\n flex-direction: row;\r\n justify-content: space-between;\r\n height: 82px;\r\n padding: 24px;\r\n\r\n ${theme.mediaQueries.md} {\r\n padding: 18px 24px;\r\n width: 100%;\r\n margin: 0;\r\n }\r\n`;\r\n\r\nexport const AddBundleButton = styled(Button)`\r\n width: 207px;\r\n ${theme.mediaQueries.lg} {\r\n width: 221px;\r\n }\r\n`;\r\n\r\nexport const LcoHoursContainer = styled(Flex)`\r\n border-radius: 8px;\r\n background-color: ${theme.colors.snowMountainGrey[50]};\r\n padding: 8px 0px;\r\n justify-content: center;\r\n & > div {\r\n flex: 1;\r\n &:first-child {\r\n border-right: 1px solid ${theme.colors.nightSkyBlack[60]};\r\n }\r\n }\r\n ${theme.mediaQueries.lg} {\r\n width: 327px;\r\n }\r\n`;\r\n\r\nexport const BundleImageContainer = styled(Box)`\r\n width: 172px;\r\n height: 64px;\r\n overflow: hidden;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin: 0 auto;\r\n`;\r\n\r\nexport const BundleImage = styled.img`\r\n width: 72px;\r\n height: 72px;\r\n ${theme.mediaQueries.md} {\r\n width: 56px;\r\n height: 56px;\r\n }\r\n`;\r\n\r\nexport const MobileAddOnsContainer = styled(Box)`\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: ${theme.space[3]}px;\r\n row-gap: 30px;\r\n ${({ isBundleAvailable }) => {\r\n if (isBundleAvailable) {\r\n return css`\r\n > div {\r\n &:first-child {\r\n grid-column: 1 / -1;\r\n margin-bottom: 10px;\r\n margin-right: 0px;\r\n\r\n > .info-card-addons-bundle {\r\n height: 302px;\r\n width: 100%;\r\n padding-top: initial;\r\n }\r\n }\r\n }\r\n `;\r\n }\r\n }}\r\n`;\r\n\r\nexport const BundleInfoCardWrapper = styled(Flex)`\r\n column-gap: 24px;\r\n ${theme.mediaQueries.md} {\r\n column-gap: 4px;\r\n }\r\n`;\r\n\r\nexport const AddonsCarouselContainer = styled(Box)`\r\n > div {\r\n padding: 0;\r\n }\r\n`;\r\n\r\nexport const AddGuestPolicyCont = styled(Flex)`\r\n width: 80px;\r\n position: relative;\r\n left: -30px;\r\n width: calc(100% + 60px);\r\n padding: 30px;\r\n background-color: ${theme.colors.snowMountainGrey[20]};\r\n margin: 20px 0;\r\n\r\n ${mediaQueries.sm} {\r\n padding: 20px;\r\n width: 100%;\r\n left: 0;\r\n }\r\n\r\n flex-direction: column;\r\n`;\r\n\r\nexport const NewReservationDetailsHeader = styled(Flex)`\r\n width: 100%;\r\n min-height: 20px;\r\n border: 1px solid ${theme.colors.snowMountainGrey[100]};\r\n border-radius: 16px;\r\n padding: 20px 20px 5px 20px;\r\n\r\n ${mediaQueries.sm} {\r\n padding: 20px 20px 10px 20px;\r\n }\r\n margin-bottom: 20px;\r\n flex-wrap: wrap;\r\n`;\r\n\r\nexport const LineDetailsHeader = styled(Flex)`\r\n width: 100%;\r\n min-height: 20px;\r\n margin-bottom: 15px;\r\n\r\n ${mediaQueries.sm} {\r\n width: 50%;\r\n margin-bottom: 10px;\r\n }\r\n\r\n img {\r\n position: relative;\r\n top: -2px;\r\n }\r\n`;\r\n","import { API_URLS, getApiUrl } from '../Utils/apiURLConfiguration';\r\nimport GWRApiClient from './GWRApiClient';\r\n\r\n/**\r\n * Concrete implementation for the Payment endpoints\r\n *\r\n * @class PaymentApiClient\r\n * @extends {GWRApiClient}\r\n */\r\nexport default class PaymentApiClient extends GWRApiClient {\r\n /**\r\n * @constructor\r\n * Calls parent constructor.\r\n * If there isn't any url provided, then we use the default from the environment variable\r\n * fills the url and token information\r\n * @param {string} url\r\n * The url where the service endpoints are\r\n * @param {string} token\r\n * The token of the logged user\r\n */\r\n constructor(version = '', token = '') {\r\n let apiVersion = version !== '' ? version : `v2`;\r\n\r\n const urlAux = getApiUrl(API_URLS.REACT_APP_PAYMENT_SERVICE_ENDPOINT, apiVersion);\r\n\r\n super(urlAux, token);\r\n }\r\n\r\n /**\r\n * Sends a GET request with accessBlock in order to get the wallet(s) config\r\n * @param accessBlock\r\n * @param i4GoServerUrl\r\n * @returns {Promise|*>}\r\n */\r\n async getShift4WalletConfig(accessBlock, i4GoServerUrl) {\r\n const walletConfigUrl = `${i4GoServerUrl}?fuseaction=get.get3dsInfo&i4go_accessBlock=${accessBlock}`;\r\n\r\n return await super.getApiCall(walletConfigUrl, {}, false);\r\n }\r\n\r\n /**\r\n * Sends a GET request with accessBlock in order to get the wallet(s) config\r\n * @param accessBlock\r\n * @param applePayToken\r\n * @param googlePayToken\r\n * @param i4GoServerUrl\r\n * @returns {Promise|*>}\r\n */\r\n async approveShift4WalletTransaction(accessBlock, applePayToken, googlePayToken, i4GoServerUrl) {\r\n const form_data = new FormData();\r\n const formDataValues = {\r\n i4go_accessBlock: accessBlock,\r\n i4go_successURL: '',\r\n i4go_failureURL: '',\r\n i4go_cardNumber: '',\r\n i4go_cvv2Code: '',\r\n i4go_p2peBlock: '',\r\n i4go_trackInformation: '',\r\n i4go_applePayToken: applePayToken,\r\n i4go_googlePayToken: googlePayToken,\r\n i4go_cardinalInfo: '',\r\n i4go_referrer: window.location,\r\n i4go_cardholderName: '',\r\n cardNumber: '',\r\n cvv2Code: '',\r\n i4go_streetAddress: '',\r\n i4go_postalCode: ''\r\n };\r\n\r\n if (applePayToken) {\r\n delete formDataValues.i4go_googlePayToken;\r\n } else {\r\n delete formDataValues.i4go_applePayToken;\r\n }\r\n\r\n for (let key in formDataValues) {\r\n form_data.append(key, formDataValues[key]);\r\n }\r\n const walletConfigUrl = `${i4GoServerUrl}?fuseaction=api.jsonPostCardEntry`;\r\n\r\n return await super.postApiCall(walletConfigUrl, form_data, false);\r\n }\r\n}\r\n","import GWRApiClient from './GWRApiClient';\r\n\r\n/**\r\n * Concrete implementation for the Upgrade room endpoints\r\n *\r\n * @class Shift4i4GoApiClient\r\n * @extends {GWRApiClient}\r\n */\r\n\r\nexport default class Shift4i4GoApiClient extends GWRApiClient {\r\n /**\r\n * @constructor\r\n * Calls parent constructor.\r\n * If there isn't any url provided, then we use the default from the environment variable\r\n * fills the url and token information\r\n * @param {string} url\r\n * The url where the service endpoints are\r\n * @param {string} token\r\n * The token of the logged user\r\n */\r\n\r\n constructor(url = '', token = '') {\r\n super(url, token);\r\n }\r\n\r\n /**\r\n * function to get vaulted card token\r\n * @function\r\n * @param {Object} data - form data to send card details get token\r\n * @param {string} url - shifti4Go server url\r\n */\r\n async getVaultedCardDetails(urlReq, data) {\r\n const urlRequest = `${urlReq}?fuseaction=api.jsonPostCardEntry`;\r\n var formData = new FormData();\r\n Object.keys(data).forEach((value, index) => {\r\n formData.append(value, data[value]);\r\n });\r\n let response = await super.postApiCall(urlRequest, formData, false);\r\n return response;\r\n }\r\n}\r\n","import * as Yup from 'yup';\r\nimport { SUPPORTED_COUNTRIES, VALID_COUNTRIES } from '../../utilities/constants';\r\nimport countries from '../utilities/countries';\r\nimport provinces from '../utilities/provinces';\r\nimport states from '../utilities/states';\r\nimport { onlyDigitsValidation, strLenIsBetweenRange } from '../utilities/validation/ValidationHelperMethods';\r\nimport { specialRequestOptions } from './AdditionalRequests/selectOptions';\r\nimport { errors, paymentFieldsLengths } from './ValidationMessages';\r\n\r\nconst createReservationSchema = (cidNumberIsRequired = true) => {\r\n let creditCardValues = {\r\n number: Yup.string().required(),\r\n cardCode: Yup.string().required(),\r\n holder: Yup.string().required(),\r\n expiration: Yup.date().required()\r\n };\r\n\r\n if (cidNumberIsRequired) {\r\n creditCardValues.cidNumber = Yup.string()\r\n .required()\r\n .test('is-number', errors.CVV_ONLY_NUMBERS, val => onlyDigitsValidation(val))\r\n .test('len', errors.CVV_LENGTH, val =>\r\n strLenIsBetweenRange(val, paymentFieldsLengths.CVV_MIN - 1, paymentFieldsLengths.CVV_MAX + 1)\r\n );\r\n }\r\n\r\n return Yup.object().shape({\r\n userId: Yup.string()\r\n .default(null)\r\n .notRequired()\r\n .nullable(),\r\n payment: Yup.object().shape({\r\n type: Yup.number()\r\n .positive()\r\n .integer()\r\n .required(),\r\n creditCard: Yup.object().when('type', {\r\n is: 1,\r\n then: Yup.object().shape(creditCardValues),\r\n otherwise: Yup.object().notRequired()\r\n }),\r\n affirm: Yup.object().when('type', {\r\n is: 3,\r\n then: Yup.object().shape({\r\n checkoutToken: Yup.string().required(),\r\n property: Yup.string().required(),\r\n amount: Yup.number().required(),\r\n resvId: Yup.string().nullable()\r\n }),\r\n otherwise: Yup.object().notRequired()\r\n })\r\n }),\r\n address: Yup.object().shape({\r\n street1: Yup.string().required(),\r\n city: Yup.string().required(),\r\n state: Yup.string()\r\n .when('country', {\r\n is: SUPPORTED_COUNTRIES.UnitedStates,\r\n then: Yup.string()\r\n .oneOf(states.map(state => state.abbreviation))\r\n .required()\r\n })\r\n .when('country', {\r\n is: SUPPORTED_COUNTRIES.Canada,\r\n then: Yup.string()\r\n .oneOf(provinces.map(province => province.abbreviation))\r\n .required()\r\n })\r\n .when('country', {\r\n is: val => !VALID_COUNTRIES.includes(val),\r\n then: Yup.string().notRequired()\r\n }),\r\n country: Yup.string()\r\n .oneOf(countries.map(country => country.code))\r\n .required(),\r\n postalCode: Yup.string()\r\n .when('country', {\r\n is: val => val === SUPPORTED_COUNTRIES.UnitedStates,\r\n then: Yup.string().length(5)\r\n })\r\n .required(),\r\n email: Yup.string()\r\n .email()\r\n .required()\r\n }),\r\n details: Yup.object().shape({\r\n comments: Yup.array()\r\n .of(Yup.string())\r\n .default(() => [])\r\n .notRequired()\r\n .nullable(),\r\n specialRequests: Yup.array()\r\n .of(\r\n Yup.object().shape({\r\n requestId: Yup.number().default(0),\r\n code: Yup.string().oneOf(specialRequestOptions.map(item => item.value))\r\n })\r\n )\r\n .notRequired(),\r\n sourceCode: Yup.string()\r\n .default('NA')\r\n .notRequired(),\r\n selection: Yup.object().shape({\r\n property: Yup.string()\r\n .uppercase()\r\n .required(),\r\n arrival: Yup.string().required(),\r\n departure: Yup.string().required(),\r\n roomCode: Yup.string().required(),\r\n adults: Yup.number()\r\n .integer()\r\n .required(),\r\n children: Yup.array()\r\n .of(Yup.number().integer())\r\n .default([]),\r\n offerCode: Yup.string()\r\n .uppercase()\r\n .notRequired(),\r\n rateCode: Yup.string()\r\n .uppercase()\r\n .notRequired(),\r\n site: Yup.string()\r\n .uppercase()\r\n .required(),\r\n suiteDescription: Yup.string().notRequired(),\r\n suiteTitle: Yup.string().notRequired(),\r\n checkoutTime: Yup.date().notRequired(),\r\n isDueBalanceBb: Yup.boolean()\r\n .default(true)\r\n .notRequired(),\r\n grandTotalDue: Yup.number().notRequired()\r\n }),\r\n items: Yup.array()\r\n .of(\r\n Yup.object().shape({\r\n quantity: Yup.number()\r\n .positive()\r\n .integer(),\r\n date: Yup.date().notRequired(),\r\n itemCode: Yup.string().notRequired(),\r\n rateCode: Yup.string()\r\n .uppercase()\r\n .notRequired(),\r\n total: Yup.number()\r\n .positive()\r\n .integer()\r\n .notRequired()\r\n })\r\n )\r\n .default([])\r\n .notRequired(),\r\n alerts: Yup.array()\r\n .of(\r\n Yup.object().shape({\r\n alert_code: Yup.string().notRequired(),\r\n alert_description: Yup.string().notRequired()\r\n })\r\n )\r\n .default([])\r\n .notRequired(),\r\n packages: Yup.array()\r\n .of(\r\n Yup.object().shape({\r\n description: Yup.string().notRequired(),\r\n shortDescription: Yup.string().notRequired(),\r\n packageCode: Yup.string().notRequired(),\r\n quantity: Yup.number()\r\n .positive()\r\n .integer()\r\n .notRequired(),\r\n tax: Yup.number().notRequired(),\r\n totalAmount: Yup.number().notRequired(),\r\n unitAmount: Yup.number().notRequired(),\r\n packageAmount: Yup.number().notRequired()\r\n })\r\n )\r\n .default([])\r\n .notRequired()\r\n }),\r\n qualifyingId: Yup.string().notRequired(),\r\n isCabana: Yup.boolean()\r\n .default(false)\r\n .notRequired(),\r\n cabanaSource: Yup.string().notRequired(),\r\n profileId: Yup.string()\r\n .notRequired()\r\n .nullable(),\r\n cabanaItem: Yup.object()\r\n .shape({\r\n quantity: Yup.number()\r\n .positive()\r\n .integer()\r\n .notRequired(),\r\n date: Yup.date().notRequired(),\r\n itemCode: Yup.string().notRequired(),\r\n rateCode: Yup.string()\r\n .uppercase()\r\n .notRequired(),\r\n total: Yup.number()\r\n .positive()\r\n .integer()\r\n .notRequired()\r\n })\r\n .default(null)\r\n .nullable()\r\n .notRequired(),\r\n customer: Yup.object().shape({\r\n gender: Yup.number()\r\n .oneOf([1, 2])\r\n .required(),\r\n firstName: Yup.string().required(),\r\n lastName: Yup.string().required(),\r\n isCASLMarked: Yup.boolean().default(false)\r\n })\r\n });\r\n};\r\n\r\nexport default createReservationSchema;\r\n","import * as Yup from 'yup';\r\nimport { SUPPORTED_COUNTRIES, VALID_COUNTRIES } from '../../../utilities/constants';\r\nimport countries from '../../utilities/countries';\r\nimport provinces from '../../utilities/provinces';\r\nimport states from '../../utilities/states';\r\nimport { onlyDigitsValidation, strLenIsBetweenRange } from '../../utilities/validation/ValidationHelperMethods';\r\nimport { errors, paymentFieldsLengths } from '../ValidationMessages';\r\n\r\nconst partyReservationSchema = Yup.object().shape({\r\n userId: Yup.string()\r\n .default(null)\r\n .notRequired()\r\n .nullable(),\r\n payment: Yup.object().shape({\r\n type: Yup.number()\r\n .positive()\r\n .integer()\r\n .required(),\r\n creditCard: Yup.object().when('type', {\r\n is: 1,\r\n then: Yup.object().shape({\r\n number: Yup.string().required(),\r\n holder: Yup.string().required(),\r\n expiration: Yup.date().required(),\r\n cardCode: Yup.string().required(),\r\n cidNumber: Yup.string()\r\n .required()\r\n .test('is-number', errors.CVV_ONLY_NUMBERS, val => onlyDigitsValidation(val))\r\n .test('len', errors.CVV_LENGTH, val =>\r\n strLenIsBetweenRange(val, paymentFieldsLengths.CVV_MIN - 1, paymentFieldsLengths.CVV_MAX + 1)\r\n )\r\n }),\r\n otherwise: Yup.object().notRequired()\r\n }),\r\n affirm: Yup.object().when('type', {\r\n is: 3,\r\n then: Yup.object().shape({\r\n checkoutToken: Yup.string().required(),\r\n property: Yup.string().required(),\r\n amount: Yup.number().required(),\r\n resvId: Yup.string().nullable()\r\n }),\r\n otherwise: Yup.object().notRequired()\r\n })\r\n }),\r\n address: Yup.object().shape({\r\n street1: Yup.string().required(),\r\n city: Yup.string().required(),\r\n state: Yup.string()\r\n .when('country', {\r\n is: SUPPORTED_COUNTRIES.UnitedStates,\r\n then: Yup.string()\r\n .oneOf(states.map(state => state.abbreviation))\r\n .required()\r\n })\r\n .when('country', {\r\n is: SUPPORTED_COUNTRIES.Canada,\r\n then: Yup.string()\r\n .oneOf(provinces.map(province => province.abbreviation))\r\n .required()\r\n })\r\n .when('country', {\r\n is: val => !VALID_COUNTRIES.includes(val),\r\n then: Yup.string().notRequired()\r\n }),\r\n country: Yup.string()\r\n .oneOf(countries.map(country => country.code))\r\n .required(),\r\n postalCode: Yup.string()\r\n .when('country', {\r\n is: val => val === SUPPORTED_COUNTRIES.UnitedStates,\r\n then: Yup.string().length(5)\r\n })\r\n .required(),\r\n email: Yup.string()\r\n .email()\r\n .required()\r\n }),\r\n profileId: Yup.string()\r\n .notRequired()\r\n .nullable(),\r\n customer: Yup.object().shape({\r\n gender: Yup.number()\r\n .oneOf([1, 2])\r\n .required(),\r\n firstName: Yup.string().required(),\r\n lastName: Yup.string().required(),\r\n isCASLMarked: Yup.boolean().default(false)\r\n }),\r\n party: Yup.object().shape({\r\n guestsOfHonor: Yup.array().required(),\r\n partyDate: Yup.string().required(),\r\n partyType: Yup.string().required(),\r\n partySize: Yup.object().shape({\r\n adults: Yup.number().required(),\r\n kids: Yup.number().required(),\r\n infants: Yup.number().required(),\r\n spectators: Yup.number().required()\r\n }),\r\n partyTime: Yup.object().shape({\r\n name: Yup.string().required(),\r\n startTime: Yup.string().required(),\r\n endTime: Yup.string().required()\r\n })\r\n })\r\n});\r\n\r\nexport default partyReservationSchema;\r\n","import { creditCardType } from 'card-validator';\r\nimport get from 'lodash-es/get';\r\nimport PaymentApiClient from '../../api/clients/PaymentApiClient';\r\nimport RoomBookingApiClient from '../../api/clients/RoomBookingApiClient';\r\nimport Shift4i4GoApiClient from '../../api/clients/Shift4i4GoApiClient';\r\nimport { isLocationAvailableWithAffirm } from '../../api/Utils/affirmUtils';\r\nimport { isPayPalEnabled } from '../../api/Utils/paypalUtils';\r\nimport { editCopyByReplaceString } from '../../components/utilities/copyFunctions';\r\nimport { store } from '../../store/configureStore';\r\nimport { getNormalizedCode } from '../../utilities/availabilityUtils';\r\nimport {\r\n ASSETS_LOCATIONS,\r\n DATE_FORMATS,\r\n LATE_CHECKOUT_PREFIXES,\r\n SITE_NIAGON,\r\n SUPPORTED_COUNTRIES,\r\n getAssetsUrl\r\n} from '../../utilities/constants';\r\nimport { isDevEnvironment } from '../../utilities/env';\r\nimport { maskPhone } from '../../utilities/maskUtils';\r\nimport { checkObjectProperties } from '../../utilities/objectKeysManagementUtils';\r\nimport { GwDatesWrapper } from '../_internal_date_/gwDatesWrapper';\r\nimport unmaskValue from '../utilities/unmaskValue';\r\nimport createReservationSchema from './createReservationSchema';\r\n\r\nimport { FLOW_NAMES } from '../../flows/DynamicFlow/utilities/constants';\r\nimport { PAYMENT_FORM_IMAGES } from './assets/images';\r\nimport * as COPY from './utilities/copy';\r\nimport partyReservationSchema from './utilities/createPartyReservationSchema';\r\nimport { paymentMethodsTypes } from './utilities/helpers';\r\n\r\nconst DAY_PASS_PAGE_TYPE = 'daypass';\r\n/**\r\n * Type of payment methods\r\n * @enum {string}\r\n */\r\nexport const paymentMethods = {\r\n CREDIT_CARD: 1,\r\n AFFIRM: 3,\r\n PAYPAL: 4,\r\n SHIFT4: 5,\r\n APPLE_PAY: 5,\r\n GOOGLE_PAY: 5\r\n};\r\n\r\nexport const flowOrigins = {\r\n ROOM_BOOKING: 0,\r\n DAY_PASS: 1\r\n};\r\n\r\nconst paymentFormLogos = {\r\n creditCard: getAssetsUrl(ASSETS_LOCATIONS.ROOT, PAYMENT_FORM_IMAGES.UI_ICON_CREDITCARD),\r\n affirm: getAssetsUrl(ASSETS_LOCATIONS.CONTENT, PAYMENT_FORM_IMAGES.AFFIRM_LOGO),\r\n paypal: 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/PP_logo_h_100x26.png',\r\n applePay: getAssetsUrl(ASSETS_LOCATIONS.CONTENT, PAYMENT_FORM_IMAGES.APPLE_PAY_LOGO),\r\n googlePay: getAssetsUrl(ASSETS_LOCATIONS.CONTENT, PAYMENT_FORM_IMAGES.GOOGLE_PAY_LOGO),\r\n shift4: 'https://www.shift4.com/wp-content/uploads/2019/05/shift4-logo.png'\r\n};\r\n\r\n/**\r\n * Payment methods configuration objects to be used to return the payment type\r\n * on the paload.\r\n * @enum {Object}\r\n */\r\nconst paymentMethododsConf = {\r\n 'credit-card': {\r\n type: paymentMethods.CREDIT_CARD,\r\n label: 'creditCard'\r\n },\r\n affirm: {\r\n type: paymentMethods.AFFIRM,\r\n label: 'affirm'\r\n },\r\n applePayEnabled: {\r\n type: paymentMethods.APPLE_PAY,\r\n label: 'digitalWallet'\r\n },\r\n googlePayEnabled: {\r\n type: paymentMethods.GOOGLE_PAY,\r\n label: 'digitalWallet'\r\n },\r\n paypal: {\r\n type: paymentMethods.PAYPAL,\r\n label: 'paypal'\r\n },\r\n shift4: {\r\n type: paymentMethods.SHIFT4,\r\n label: 'ALTERNATIVE'\r\n }\r\n};\r\n\r\n/**\r\n * Type of credit cards\r\n * @enum {string}\r\n */\r\nconst creditCardTypes = {\r\n visa: 'VS',\r\n mastercard: 'MC',\r\n 'american-express': 'AX',\r\n discover: 'DS',\r\n default: 'any'\r\n};\r\n\r\nconst CREDIT_CARD_TEST_NUMBER = '4444333322221111';\r\nconst DEFAULT_OFFER_CODE = 'BBAR';\r\nconst SOURCE_CODE = 'WEBN';\r\nconst OCCASION = 'BDAY';\r\nconst NEXT_GEN_QA = 'NextGenQA';\r\nconst APPLE_PAY_TYPE = 'applePay';\r\nconst GOOGLE_PAY_TYPE = 'googlePay';\r\nexport const DEFAULT_RATE_CODE = 'AMTCERT';\r\n\r\n/**\r\n * Formik initial values\r\n */\r\nconst getInitialValues = selectedPaymentMethod => ({\r\n contactInfo: {\r\n phone: '',\r\n firstName: '',\r\n lastName: '',\r\n email: '',\r\n textAgreement: false\r\n },\r\n billingInfo: {\r\n billingAddress: '',\r\n postalCode: '',\r\n city: '',\r\n state: 'AL',\r\n country: SUPPORTED_COUNTRIES.UnitedStates\r\n },\r\n paymentOptions: {\r\n selected: selectedPaymentMethod ?? 'credit-card',\r\n ccNameOnCard: '',\r\n ccMonth: '',\r\n ccYear: '',\r\n ccCvv: '',\r\n ccCardNumber: '',\r\n paypal: {\r\n nonce: '',\r\n firstName: '',\r\n lastName: '',\r\n email: '',\r\n deviceId: ''\r\n },\r\n googlePay: {\r\n tokenizationData: {},\r\n type: '',\r\n info: {},\r\n description: ''\r\n },\r\n applePay: {\r\n paymentData: {},\r\n paymentMethod: {},\r\n transactionIdentifier: ''\r\n }\r\n },\r\n specialRequests: [],\r\n specialRequestsOther: '',\r\n specialOccasion: [],\r\n specialOccasionOther: '',\r\n specialOccasionBirthday: '',\r\n isCASLMarked: false\r\n});\r\n\r\n/**\r\n * Based on a credit card type, return the correspondant code. On dev\r\n * environment pass the test code \"1111222233334444\" as a visa card.\r\n * @param {number} cardNumber Credit card number.\r\n * @return {string} Credit card code.\r\n */\r\nexport const getCardCode = cardNumber => {\r\n if (cardNumber === CREDIT_CARD_TEST_NUMBER) {\r\n return creditCardTypes.visa;\r\n }\r\n\r\n const cardType = creditCardType(cardNumber);\r\n const [bestCardMatch] = cardType;\r\n\r\n if (!bestCardMatch) return creditCardTypes.default;\r\n\r\n const { type: bestCardType } = bestCardMatch;\r\n return creditCardTypes[bestCardType] || creditCardTypes.default;\r\n};\r\n\r\n/**\r\n *\r\n * @param {*} formData\r\n * @param {*} stateData\r\n */\r\nconst getAffirmCheckoutPayload = (formData, stateData) => {\r\n const { contactInfo, billingInfo } = formData;\r\n const {\r\n selectedSuite,\r\n checkinDateSelection,\r\n checkoutDateSelection,\r\n resortLocation,\r\n selectedPackages,\r\n summaryTotal,\r\n summaryTaxes\r\n } = stateData;\r\n const displayName = `${COPY.GREAT_WOLF_LODGE} ${resortLocation} ; ${resortLocation}, ${COPY.US}; ${checkinDateSelection}-${checkoutDateSelection}; ${selectedSuite.title}`;\r\n\r\n const billingInformation = {\r\n name: {\r\n first: contactInfo.firstName,\r\n last: contactInfo.lastName\r\n },\r\n address: {\r\n line1: billingInfo.billingAddress,\r\n line2: billingInfo.addressLineTwo || '',\r\n city: billingInfo.city,\r\n state: billingInfo.state,\r\n zipcode: billingInfo.postalCode,\r\n country: billingInfo.country\r\n },\r\n email: contactInfo.email\r\n };\r\n\r\n const filteredSelectedPackages = selectedPackages.filter(\r\n filteredPackage => filteredPackage.isAdjustment === undefined\r\n );\r\n\r\n return {\r\n metadata: {\r\n mode: 'modal',\r\n entity_name: resortLocation\r\n },\r\n merchant: {\r\n user_confirmation_url: `${window.location.origin}/plan/payment`,\r\n user_cancel_url: `${window.location.origin}/plan/payment`,\r\n user_confirmation_url_action: 'GET',\r\n name: 'Great Wolf Lodge'\r\n },\r\n billing: billingInformation,\r\n shipping: {\r\n ...billingInformation,\r\n phone_number: unmaskValue(contactInfo.phone)\r\n },\r\n items: [\r\n {\r\n display_name: displayName,\r\n sku: selectedSuite.suiteCode,\r\n unit_price: selectedSuite?.totalRate * 100,\r\n qty: 1,\r\n // Item image and item url are rendering a relative path but I think\r\n // should render an absolute path to those urls for affirm\r\n item_image_url: selectedSuite.mainImage,\r\n item_url: selectedSuite.anchorPath\r\n },\r\n ...filteredSelectedPackages.map(selectedPackage => {\r\n return {\r\n display_name: selectedPackage.packageName || get(selectedPackage, 'shortDescription', ''),\r\n sku: selectedPackage.packageCode,\r\n unit_price: Math.abs(selectedPackage.total.toFixed(2) * 100),\r\n qty: selectedPackage.quantity,\r\n item_image_url: '',\r\n item_url: ''\r\n };\r\n })\r\n ],\r\n shipping_amount: 0,\r\n tax_amount: parseInt(Math.round(summaryTaxes * 100)),\r\n total: parseInt(Math.round(summaryTotal * 100))\r\n };\r\n};\r\n\r\n/**\r\n * Returns and transform all payment details based on the type of payment\r\n * selected.\r\n * @param {Object} paymentData Data coming from the payment form\r\n * @param {Object} stateData Redux state data\r\n */\r\nconst getPaymentDetails = (paymentData, stateData, flowName) => {\r\n const {\r\n ccYear,\r\n ccMonth,\r\n ccCardNumber,\r\n ccNameOnCard,\r\n ccCvv,\r\n selected,\r\n cardCode,\r\n vaultedCardId,\r\n isI4IframeFlow,\r\n security\r\n } = paymentData;\r\n const {\r\n resortLocation,\r\n summaryTotal,\r\n checkoutToken,\r\n paypal,\r\n optimizelyChargePackagesAtCheckout,\r\n googlePay,\r\n applePay,\r\n profile,\r\n offer,\r\n suiteRates,\r\n showLoyalty\r\n } = stateData;\r\n const expiration = ccYear && ccMonth ? GwDatesWrapper.format(`${ccYear}-${ccMonth}-05`) : null;\r\n let paymentObject = {};\r\n if (selected === 'credit-card') {\r\n paymentObject = {\r\n number: ccCardNumber,\r\n holder: ccNameOnCard,\r\n ...(expiration && { expiration }),\r\n ...(vaultedCardId && { vaultedCardId }),\r\n securityCode: 0,\r\n cardCode: cardCode ?? getCardCode(ccCardNumber),\r\n cidNumber: ccCvv,\r\n ccYear: ccYear,\r\n ccMonth: ccMonth\r\n };\r\n\r\n if (isI4IframeFlow) {\r\n paymentObject = {\r\n ...paymentObject,\r\n cardNumber: ccCardNumber,\r\n lastFourDigits: ccCardNumber.slice(-4),\r\n ...(security && { security })\r\n };\r\n }\r\n } else if (selected === 'affirm') {\r\n paymentObject = {\r\n checkoutToken: checkoutToken,\r\n property: resortLocation,\r\n amount: summaryTotal,\r\n reservationId: null\r\n };\r\n } else if (selected === 'paypal') {\r\n paymentObject = {\r\n nonce: paypal.nonce,\r\n firstName: paypal.firstName,\r\n lastName: paypal.lastName,\r\n email: paypal.email,\r\n deviceId: paypal.deviceId\r\n };\r\n } else if (selected === 'googlePayEnabled') {\r\n paymentObject = {\r\n cardCode: googlePay.i4go_cardtype,\r\n extendedCardData: googlePay.i4go_extendedcarddata,\r\n holder: googlePay.i4go_cardholdername,\r\n expirationMonth: googlePay.i4go_expirationmonth,\r\n expirationYear: googlePay.i4go_expirationyear,\r\n token: googlePay.i4go_uniqueid,\r\n lastFourDigits: googlePay.otn.cardnumber.slice(12)\r\n };\r\n } else if (selected === 'applePayEnabled') {\r\n const billingContactData = JSON.parse(applePay.i4go_applepaytoken);\r\n paymentObject = {\r\n cardCode: applePay.i4go_cardtype,\r\n extendedCardData: applePay.i4go_extendedcarddata,\r\n holder:\r\n applePay?.i4go_cardholdername ??\r\n `${billingContactData.billingContact.givenName} ${billingContactData.billingContact.familyName}`,\r\n expirationMonth: applePay.i4go_expirationmonth,\r\n expirationYear: applePay.i4go_expirationyear,\r\n token: applePay.i4go_uniqueid,\r\n lastFourDigits: applePay.otn.cardnumber.slice(12)\r\n };\r\n }\r\n\r\n const handlePoints = () => {\r\n if (showLoyalty && profile && profile.user && profile.user.pointsBalance) {\r\n if (profile.user.pointsBalance <= suiteRates[0].totalNightlyRate) {\r\n return profile.user.pointsBalance.toFixed();\r\n } else if (profile.user.pointsBalance > suiteRates[0].totalNightlyRate) {\r\n return suiteRates[0].totalNightlyRate.toFixed();\r\n }\r\n } else {\r\n return 0;\r\n }\r\n };\r\n\r\n return {\r\n type: paymentMethododsConf[selected].type,\r\n [paymentMethododsConf[selected].label]: paymentObject,\r\n shouldChargePackagesUpfront: optimizelyChargePackagesAtCheckout,\r\n points: flowName !== FLOW_NAMES.BIRTHDAY ? Number(handlePoints()) ?? 0 : 0,\r\n offers: flowName !== FLOW_NAMES.BIRTHDAY && offer && offer.activeOffers ? offer.activeOffers : [],\r\n isI4IframeFlow\r\n };\r\n};\r\n\r\n/**\r\n * Returns a formed object containning address details.\r\n * @param {Object} billingData Payment form billing data\r\n * @param {Object} contactData Payment form contact data\r\n */\r\nconst getAddressDetails = (billingData, contactData) => {\r\n const { billingAddress, addressLineTwo, city, state, country, postalCode } = billingData;\r\n const { email } = contactData;\r\n return {\r\n street1: billingAddress,\r\n street2: addressLineTwo || '',\r\n city: city,\r\n state: state,\r\n country: country,\r\n postalCode: postalCode,\r\n email: email\r\n };\r\n};\r\n\r\n/**\r\n * Returns a formed object containing all the order details.\r\n * @param {Object} formData Payment form data\r\n * @param {Object} stateData Redux state data\r\n */\r\nconst getOrderDetails = (formData, stateData) => {\r\n const {\r\n specialRequests,\r\n specialRequestsOther,\r\n specialOccasion,\r\n specialOccasionBirthday,\r\n specialOccasionOther\r\n } = formData;\r\n const {\r\n selectedSuite,\r\n checkinDateSelection,\r\n checkoutDateSelection,\r\n adultsCount,\r\n kidsAges,\r\n selectedPackages,\r\n dayPasses,\r\n pageType,\r\n validOfferCode,\r\n qualifyingID,\r\n resortLocation\r\n } = stateData;\r\n\r\n const getOfferCode = () => {\r\n if (pageType === DAY_PASS_PAGE_TYPE) return '';\r\n if (isDevEnvironment) return DEFAULT_RATE_CODE;\r\n\r\n if (selectedSuite?.offerType === DEFAULT_OFFER_CODE) {\r\n return DEFAULT_OFFER_CODE;\r\n }\r\n\r\n return validOfferCode ? getNormalizedCode(validOfferCode) : getNormalizedCode(selectedSuite?.rateCode);\r\n };\r\n\r\n const getRateCode = () => {\r\n if (pageType === DAY_PASS_PAGE_TYPE) return dayPasses.selectedRateCode;\r\n\r\n return getNormalizedCode(selectedSuite?.rateCode);\r\n };\r\n const commentsList = [specialRequestsOther];\r\n\r\n if (pageType === DAY_PASS_PAGE_TYPE && dayPasses.qualifyingId) {\r\n commentsList.push(editCopyByReplaceString(COPY.QUALIFYING_ID, dayPasses.qualifyingId, ''));\r\n } else if (qualifyingID) {\r\n commentsList.push(editCopyByReplaceString(COPY.QUALIFYING_ID, qualifyingID, ''));\r\n }\r\n\r\n return {\r\n comments: commentsList,\r\n specialRequests: specialRequests.map(request => ({\r\n requestId: 0,\r\n code: request\r\n })),\r\n // what is source code?\r\n sourceCode: SOURCE_CODE,\r\n selection: {\r\n property: resortLocation,\r\n arrival:\r\n pageType === DAY_PASS_PAGE_TYPE\r\n ? GwDatesWrapper.format(dayPasses.arrivalDate, DATE_FORMATS.default)\r\n : GwDatesWrapper.format(checkinDateSelection, DATE_FORMATS.default),\r\n departure:\r\n pageType === DAY_PASS_PAGE_TYPE\r\n ? GwDatesWrapper.add(dayPasses.arrivalDate, 1, 'days')\r\n : GwDatesWrapper.format(checkoutDateSelection, DATE_FORMATS.default),\r\n roomCode: pageType === DAY_PASS_PAGE_TYPE ? dayPasses.selectedItemCode : selectedSuite.suiteCode,\r\n suiteDescription: pageType === DAY_PASS_PAGE_TYPE ? dayPasses.item.description : selectedSuite.title,\r\n adults: pageType === DAY_PASS_PAGE_TYPE ? dayPasses.numberOfGuests : adultsCount,\r\n children: pageType === DAY_PASS_PAGE_TYPE ? [] : kidsAges,\r\n offerCode: pageType === DAY_PASS_PAGE_TYPE ? getNormalizedCode(dayPasses.promoCode) : getOfferCode(),\r\n rateCode: getRateCode(),\r\n site: resortLocation,\r\n availabilityKey: selectedSuite?.availabilityKey,\r\n suiteContent: {\r\n maxOccupancy: selectedSuite?.maxOccupancy,\r\n suiteCategory: selectedSuite?.suiteCategory\r\n }\r\n },\r\n alerts: specialOccasion.map(occasion => ({\r\n alert_code: occasion,\r\n alert_description:\r\n occasion === OCCASION\r\n ? editCopyByReplaceString(COPY.WISH_HAPPY_BIRTH_DAY, specialOccasionBirthday, '')\r\n : specialOccasionOther\r\n })),\r\n packages:\r\n pageType === DAY_PASS_PAGE_TYPE\r\n ? selectedPackages.map(selectedPackage => {\r\n const { packageCode, isAdjustment, startDate, endDate, packageType, isDiningByPackage } = selectedPackage;\r\n return {\r\n packageCode,\r\n isAdjustment,\r\n quantity: 1,\r\n packageType: packageType && packageType.length > 0 ? packageType[0] : '',\r\n isDiningByPackage,\r\n startDate: GwDatesWrapper.format(startDate, DATE_FORMATS.default),\r\n endDate: GwDatesWrapper.format(endDate, DATE_FORMATS.default)\r\n };\r\n })\r\n : selectedPackages.map(selectedPackage => {\r\n const {\r\n packageCode,\r\n isAdjustment,\r\n quantity,\r\n startDate,\r\n endDate,\r\n packageType,\r\n isDiningByPackage,\r\n availabilityKey\r\n } = selectedPackage;\r\n\r\n return {\r\n availabilityKey,\r\n packageCode,\r\n isAdjustment,\r\n quantity,\r\n packageType: packageType && packageType.length > 0 ? packageType[0] : '',\r\n isDiningByPackage,\r\n startDate: GwDatesWrapper.format(startDate, DATE_FORMATS.default),\r\n endDate: GwDatesWrapper.format(endDate, DATE_FORMATS.default)\r\n };\r\n }),\r\n items:\r\n pageType === DAY_PASS_PAGE_TYPE\r\n ? // Create an \"array\" of items containing the day passes information\r\n [\r\n {\r\n Quantity: dayPasses.numberOfGuests,\r\n Date: GwDatesWrapper.format(dayPasses.arrivalDate, DATE_FORMATS.default),\r\n ItemCode: dayPasses.selectedItemCode,\r\n RateCode: getRateCode()\r\n }\r\n ]\r\n : // if the page type is a reservation, we should send the\r\n // late checkout packages as an item so the backend can discount\r\n // the item quantity\r\n selectedPackages\r\n .filter(selectedPackage => selectedPackage.packageCode.includes(LATE_CHECKOUT_PREFIXES.code))\r\n .map(selectedPackage => {\r\n const { quantity, total, packageCode } = selectedPackage;\r\n return {\r\n Quantity: quantity,\r\n Date: GwDatesWrapper.format(checkoutDateSelection, DATE_FORMATS.default), // should be applied for the stay checkout date\r\n Total: total,\r\n ItemCode: packageCode,\r\n RateCode: getRateCode()\r\n };\r\n })\r\n };\r\n};\r\n\r\n/**\r\n * Return customer details\r\n * @param {Object} contactInfo User data\r\n */\r\nconst getCustomerDetails = contactInfo => {\r\n return {\r\n // where to pull gender?\r\n gender: 1,\r\n firstName: contactInfo.firstName,\r\n lastName: isDevEnvironment ? NEXT_GEN_QA : contactInfo.lastName,\r\n phoneNumber: maskPhone(contactInfo.phone),\r\n canContactBySms: contactInfo.textAgreement,\r\n isCASLMarked: contactInfo.isCASLMarked,\r\n isPhoneUpdated: contactInfo?.isPhoneUpdated ?? false\r\n };\r\n};\r\n\r\n/**\r\n * Returns the payment info returned by Paypal checkout\r\n * @param {Object} paypal Paypal success object\r\n */\r\nconst getPaypalPaymentInfo = paypal => {\r\n return {\r\n nonce: paypal.nonce,\r\n firstName: paypal.details.firstName,\r\n lastName: paypal.details.lastName,\r\n email: paypal.details.email,\r\n deviceId: paypal.deviceId\r\n };\r\n};\r\n\r\n/**\r\n * Returns the billing info selected on Paypal site\r\n * @param {Object} paypal Paypal success object\r\n */\r\nconst getPaypalBillingInfo = paypal => {\r\n return {\r\n billingAddress: paypal.details.billingAddress.line1 || '',\r\n postalCode: paypal.details.billingAddress.postalCode || '',\r\n city: paypal.details.billingAddress.city || '',\r\n state: paypal.details.billingAddress.state || '',\r\n country: paypal.details.billingAddress.countryCode || ''\r\n };\r\n};\r\n\r\n/**\r\n * Returns the payment info returned by Google Pay checkout\r\n * @param gPay\r\n * @returns {{country: (*|string), city: (string|string), postalCode: (*|string), billingAddress: (string|string), state: (string|string)}}\r\n */\r\nconst getGooglePayBillingInfo = gPay => {\r\n return {\r\n billingAddress: gPay?.info?.billingAddress.address1 || '',\r\n postalCode: gPay?.info?.billingAddress.postalCode || '',\r\n city: gPay?.info?.billingAddress.locality || '',\r\n state: gPay?.info?.billingAddress.administrativeArea || '',\r\n country: gPay?.info?.billingAddress.countryCode || ''\r\n };\r\n};\r\n\r\n/**\r\n * Returns the payment info returned by Apple Pay checkout\r\n * @param applePayBillingContact\r\n * @returns {{country: (*|string), city: (string|string), postalCode: (*|string), billingAddress: (string|string), state: (string|string)}}\r\n */\r\nconst getApplePayBillingInfo = applePayBillingContact => {\r\n return {\r\n billingAddress: applePayBillingContact?.addressLines[0] || '',\r\n postalCode: applePayBillingContact?.postalCode || '',\r\n city: applePayBillingContact?.locality || '',\r\n state: applePayBillingContact?.administrativeArea || '',\r\n country: applePayBillingContact?.countryCode || ''\r\n };\r\n};\r\n\r\n/**\r\n * Returns a contact and billing info based on user logged in for formik.\r\n * @param {Object} profile Payment form data\r\n */\r\nconst setContactandBillingAddressInfo = (profile, selectedPaymentMethod) => {\r\n const { currentLodge } = store.getState();\r\n let contactAndBillingAddressInfo = { ...getInitialValues(selectedPaymentMethod) };\r\n if (profile) {\r\n contactAndBillingAddressInfo.contactInfo = {\r\n phone: maskPhone(profile.phoneNumber) || '',\r\n firstName: profile.firstName || '',\r\n lastName: profile.lastName || '',\r\n email: profile.email || '',\r\n textAgreement: currentLodge.resortLocation !== SITE_NIAGON ? true : false\r\n };\r\n contactAndBillingAddressInfo.billingInfo = {\r\n billingAddress: profile.streetLine1 || '',\r\n addressLineTwo: profile.streetLine2 || '',\r\n postalCode: profile.zip || '',\r\n city: profile.city || '',\r\n state: profile.stateProvince || '',\r\n country: profile.country || SUPPORTED_COUNTRIES.UnitedStates\r\n };\r\n }\r\n return contactAndBillingAddressInfo;\r\n};\r\n\r\nconst getPartyOrder = state => {\r\n const {\r\n partyDate,\r\n partyAdults,\r\n partyKids,\r\n partyInfants,\r\n partySpectators,\r\n partyTime,\r\n bdaySelectedParty,\r\n guestsOfHonor,\r\n selectedPackages\r\n } = state;\r\n const timeDate = bdaySelectedParty.priceDetails.times.find(timeData => timeData.name === partyTime);\r\n const BIRTHDAY_PAYMENT_INDEX = {\r\n 0: 'pizzaPackages',\r\n 1: 'drinksPackages',\r\n 2: 'cakePackages',\r\n 3: 'addOnPackages'\r\n };\r\n\r\n function createArrayBirthdayPackages(selectedPackages) {\r\n let packages = {};\r\n\r\n const groupedPackages = {};\r\n selectedPackages.forEach(pkg => {\r\n const summarySectionType = pkg.summarySectionType;\r\n if (groupedPackages[summarySectionType]) {\r\n groupedPackages[summarySectionType].push(pkg);\r\n } else {\r\n groupedPackages[summarySectionType] = [pkg];\r\n }\r\n });\r\n\r\n Object.keys(groupedPackages).forEach(gKey => {\r\n // packageCodes\r\n const packageCodes = [];\r\n const groupedPackages = Object.groupBy(selectedPackages, ({ summarySectionType }) => summarySectionType);\r\n const sortedPackage = groupedPackages[gKey]?.sort((a, b) => {\r\n // If packageCode is the same, compare isExtra (false comes before true)\r\n return a.isExtra - b.isExtra;\r\n });\r\n\r\n if (+gKey === 3) {\r\n sortedPackage?.forEach(pkg => {\r\n packageCodes.push({\r\n code: pkg.packageCode,\r\n quantity: pkg.quantity\r\n });\r\n });\r\n } else {\r\n sortedPackage.forEach(pkg => {\r\n const qty = pkg.quantity;\r\n const code = pkg.packageCode;\r\n for (let i = 0; i < qty; i++) {\r\n packageCodes.push(code);\r\n }\r\n });\r\n }\r\n\r\n packages[BIRTHDAY_PAYMENT_INDEX[gKey]] = packageCodes;\r\n });\r\n\r\n return packages;\r\n }\r\n\r\n return {\r\n party: {\r\n guestsOfHonor: guestsOfHonor,\r\n partyDate: partyDate,\r\n partySize: {\r\n adults: partyAdults,\r\n kids: partyKids,\r\n infants: partyInfants,\r\n spectators: partySpectators\r\n },\r\n partyTime: {\r\n name: timeDate.name,\r\n startTime: timeDate.startTime,\r\n endTime: timeDate.endTime\r\n },\r\n partyType: bdaySelectedParty.partyType,\r\n depositAmount: bdaySelectedParty.priceDetails?.depositAmount,\r\n remainingBalance: bdaySelectedParty.priceDetails?.remainingBalance,\r\n ...createArrayBirthdayPackages(selectedPackages)\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * Returns a well formed payload to be used by createReservation.\r\n * @param {Object} formValues Payment form data\r\n * @param {Object} stateValues Redux state data\r\n */\r\nconst getPayload = async (flowName, formValues, stateValues, callBack = () => {}) => {\r\n const {\r\n paymentOptions,\r\n billingInfo,\r\n contactInfo,\r\n specialRequests,\r\n specialRequestsOther,\r\n specialOccasion\r\n } = formValues;\r\n const { profile, suiteRates } = stateValues;\r\n\r\n const defaultPayload = {\r\n profileId: profile.user ? profile.user.id : null,\r\n address: getAddressDetails(billingInfo, contactInfo),\r\n payment: getPaymentDetails(paymentOptions, stateValues, flowName),\r\n customer: getCustomerDetails(contactInfo)\r\n };\r\n\r\n let payload = {};\r\n\r\n if (flowName === FLOW_NAMES.BOOKING || flowName === FLOW_NAMES.DAYPASS) {\r\n const suiteDaypassPayload = {\r\n details: getOrderDetails(\r\n {\r\n specialRequests,\r\n specialRequestsOther,\r\n specialOccasion\r\n },\r\n stateValues\r\n ),\r\n\r\n expectedRates: suiteRates\r\n };\r\n payload = { ...defaultPayload, ...suiteDaypassPayload };\r\n\r\n try {\r\n const cidNumberIsRequired = !paymentOptions.isI4IframeFlow;\r\n return await createReservationSchema(cidNumberIsRequired).validate(payload);\r\n } catch (error) {\r\n callBack(error?.errors[0] ?? 'Something Went Wrong');\r\n console.error(error);\r\n // null catch statement to prevent error from breaking the app\r\n }\r\n }\r\n\r\n if (flowName === FLOW_NAMES.BIRTHDAY) {\r\n const birthdayPayload = getPartyOrder(stateValues);\r\n payload = { ...defaultPayload, ...birthdayPayload };\r\n try {\r\n return await partyReservationSchema.validate(payload);\r\n } catch (error) {\r\n callBack(error?.errors[0] ?? 'Something Went Wrong');\r\n console.error(error);\r\n // null catch statement to prevent error from breaking the app\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * @function\r\n * Check if the all contact and billing information is complete before we\r\n * render the info text component\r\n * @param {Object} contactInfo Formik data with the contactInfo\r\n * @param {Object} billingInfo Formik data with the billingInfo\r\n * @Return {Boolean} If contactInfo and billingInfo haven't any null or empty properties then the result will be true\r\n */\r\nconst allFieldsProvided = contactInfo => {\r\n if (!contactInfo) return false;\r\n\r\n return checkObjectProperties(contactInfo);\r\n};\r\n\r\n/**\r\n * @function\r\n * Returns requited data to render payment tabs depending on calculated values\r\n * @param {Boolean} isPlanPage\r\n * @returns\r\n */\r\nconst getPaymentMethods = (isPlanPage, resortLocation) => {\r\n const { CREDIT_CARD, AFFIRM, PAYPAL, SHIFT4, APPLE_PAY, GOOGLE_PAY } = paymentMethodsTypes;\r\n\r\n const methods = {\r\n [CREDIT_CARD]: {\r\n isEnabled: true,\r\n isEnabledOutsidePlanPage: true,\r\n order: 1\r\n },\r\n [AFFIRM]: {\r\n isEnabled: isLocationAvailableWithAffirm(resortLocation),\r\n isEnabledOutsidePlanPage: false,\r\n order: 4\r\n },\r\n [PAYPAL]: {\r\n isEnabled: isPayPalEnabled(process.env.REACT_APP_PAYPAL_ENABLED_AT, resortLocation),\r\n isEnabledOutsidePlanPage: true,\r\n order: 5\r\n },\r\n [SHIFT4]: {\r\n isEnabled: process.env.REACT_APP_ENABLE_SHIFT4 === 'true',\r\n isEnabledOutsidePlanPage: true,\r\n order: 6\r\n },\r\n [APPLE_PAY]: {\r\n isEnabled: true,\r\n isEnabledOutsidePlanPage: true,\r\n order: 7\r\n },\r\n [GOOGLE_PAY]: {\r\n isEnabled: true,\r\n isEnabledOutsidePlanPage: true,\r\n order: 8\r\n }\r\n };\r\n\r\n const availablePaymentMethods = Object.values(paymentMethodsTypes).filter(method => {\r\n return isPlanPage\r\n ? methods[method]?.isEnabled\r\n : methods[method]?.isEnabled && methods[method]?.isEnabledOutsidePlanPage;\r\n });\r\n\r\n let availableSpace = 100;\r\n\r\n return availablePaymentMethods\r\n .map((method, idx) => {\r\n const { length } = availablePaymentMethods;\r\n if (availableSpace % length === 0 || idx !== 0) {\r\n return { name: method, width: `${availableSpace / length}%` };\r\n }\r\n\r\n const firstTabSize = Math.ceil(availableSpace / length / 10) * 10;\r\n availableSpace -= firstTabSize;\r\n return { name: method, width: `${firstTabSize}%` };\r\n })\r\n .sort((a, b) => a.order < b.order);\r\n};\r\n\r\nconst fetchShift4WalletConfig = async (accessBlock, i4GoServerUrl) => {\r\n try {\r\n const payApiClient = new PaymentApiClient();\r\n const { data } = await payApiClient.getShift4WalletConfig(accessBlock, i4GoServerUrl);\r\n return data;\r\n } catch (e) {\r\n console.log(e);\r\n }\r\n};\r\n\r\nconst approveShift4WalletTransaction = async (accessBlock, token, paymentType, i4GoServerUrl) => {\r\n try {\r\n const applePayToken = paymentType === APPLE_PAY_TYPE ? token : '';\r\n const googlePayToken = paymentType === GOOGLE_PAY_TYPE ? token : '';\r\n const payApiClient = new PaymentApiClient();\r\n const { data } = await payApiClient.approveShift4WalletTransaction(\r\n accessBlock,\r\n applePayToken,\r\n googlePayToken,\r\n i4GoServerUrl\r\n );\r\n return data;\r\n } catch (e) {\r\n console.log(e);\r\n }\r\n};\r\n\r\nexport const fetchTiogaTokenAccessBlock = async (resortLocation, paymentType, totalToCharge, origin = null) => {\r\n try {\r\n const payApiClient = new RoomBookingApiClient();\r\n return await payApiClient.getShift4i4AccessBlockTioga(resortLocation, paymentType, totalToCharge, origin);\r\n } catch (e) {\r\n console.error(e);\r\n }\r\n};\r\n\r\n/**\r\n * Create shift4i4Go vaulted card details\r\n *\r\n * @function\r\n * @param {number, ccMonth, ccYear, cidNumber, holder} creditCardData credt Card data to be tokenized\r\n * @param {postalCode, street1} billingAddressData billing address data to be tokenized\r\n */\r\nconst fillVaultedCardDetails = async (creditCardData, billingAddressData, resortLocation) => {\r\n const { number: ccNumber, ccMonth, ccYear, cidNumber: cvv2Code, holder: ccHolder } = creditCardData;\r\n const { postalCode, street1 } = billingAddressData;\r\n const cardTokenAccessBlockData = await fetchTiogaTokenAccessBlock(resortLocation, 1, 0);\r\n const ccStreetAddress = street1.replace(/(^\\d+)(.+$)/i, '$1');\r\n const data = {\r\n i4go_accessblock: cardTokenAccessBlockData.data.token,\r\n i4go_cardnumber: ccNumber,\r\n i4go_expirationmonth: ccMonth,\r\n i4go_expirationyear: ccYear,\r\n i4go_cvv2code: cvv2Code,\r\n i4go_cardholdername: ccHolder,\r\n i4go_postalcode: postalCode,\r\n i4go_streetaddress: ccStreetAddress\r\n };\r\n const vaultedCardDetails = (\r\n await new Shift4i4GoApiClient().getVaultedCardDetails(cardTokenAccessBlockData.data.url, data)\r\n ).data;\r\n\r\n return {\r\n vaultedCardId: vaultedCardDetails.i4go_uniqueid,\r\n lastFourDigits: vaultedCardDetails.otn.cardnumber.replaceAll('X', '').trim(),\r\n cardnumber: vaultedCardDetails.otn.cardnumber,\r\n cidNumber: '',\r\n number: vaultedCardDetails.otn.cardnumber\r\n };\r\n};\r\n\r\nexport const transformPaymentDataToOptions = (paymentMethodsComponents, optionsVariation) =>\r\n optionsVariation.reduce((paymentMethods, currentOption) => {\r\n if (!paymentMethodsComponents[currentOption].show || !paymentMethodsComponents[currentOption].allowedOnLocation)\r\n return paymentMethods;\r\n\r\n return [\r\n ...paymentMethods,\r\n {\r\n paymentMethod: {\r\n uuid: currentOption,\r\n ...paymentMethodsComponents[currentOption]\r\n }\r\n }\r\n ];\r\n }, []);\r\n\r\nexport const getSelectedPaymentMethod = (\r\n appleGooglePayMethodsFirst,\r\n isGooglePaymentActive,\r\n availablePaymentMethods\r\n) => {\r\n if (!appleGooglePayMethodsFirst) return paymentMethodsTypes.CREDIT_CARD;\r\n if (window.ApplePaySession && availablePaymentMethods.includes(paymentMethodsTypes.APPLE_PAY))\r\n return paymentMethodsTypes.APPLE_PAY;\r\n if (isGooglePaymentActive && availablePaymentMethods.includes(paymentMethodsTypes.GOOGLE_PAY))\r\n return paymentMethodsTypes.GOOGLE_PAY;\r\n return paymentMethodsTypes.CREDIT_CARD;\r\n};\r\n\r\nexport const setBasicBillingInfo = (values, addressInfo) => {\r\n values.billingInfo.city = addressInfo.locality;\r\n values.billingInfo.postalCode = addressInfo.postalCode;\r\n values.billingInfo.country = addressInfo.countryCode;\r\n values.billingInfo.state = addressInfo.administrativeArea;\r\n};\r\n\r\nexport {\r\n allFieldsProvided,\r\n approveShift4WalletTransaction,\r\n fetchShift4WalletConfig,\r\n fillVaultedCardDetails,\r\n getAffirmCheckoutPayload,\r\n getApplePayBillingInfo,\r\n getGooglePayBillingInfo,\r\n getPayload,\r\n getPaymentMethods,\r\n getPaypalBillingInfo,\r\n getPaypalPaymentInfo,\r\n paymentFormLogos,\r\n setContactandBillingAddressInfo\r\n};\r\n","import styled from 'styled-components';\r\nimport theme from './themes/theme';\r\nimport Box from './Box';\r\n\r\nconst floatLabel = (active, type, error) => {\r\n if (active) {\r\n if (type === 'textarea') {\r\n return {\r\n transform: 'translateY(-8px) scale(0.57)',\r\n color: `${theme.colors.preciousStoneBlue[100]}`\r\n };\r\n } else {\r\n return {\r\n fontSize: '8px',\r\n transform: `translateY(${error ? '15px' : '-15px'})`,\r\n color: `${theme.colors.preciousStoneBlue[100]}`\r\n };\r\n }\r\n }\r\n};\r\n\r\nconst positionLabel = (type, error) => {\r\n if (type === 'textarea') {\r\n return {\r\n top: '15px'\r\n };\r\n } else if (type === 'select') {\r\n return {\r\n top: 'calc(100% - 31px)'\r\n };\r\n } else {\r\n if (error) {\r\n return {\r\n top: 0,\r\n overflow: 'hidden',\r\n minHeight: '15px',\r\n left: 0,\r\n margin: '8px 0'\r\n };\r\n }\r\n\r\n return {\r\n top: '25px',\r\n transform: 'translateY(-50%)',\r\n overflow: 'visible',\r\n minHeight: 'auto'\r\n };\r\n }\r\n};\r\n\r\nconst errorFieldProps = props => {\r\n if (props.error) {\r\n return {\r\n position: 'relative',\r\n transition: 'none'\r\n };\r\n }\r\n};\r\n\r\nconst Label = styled(Box).attrs(props => ({\r\n as: 'label'\r\n}))`\r\n font-size: ${props => (props.error ? '10px' : `${theme.fontSizes[1]}px`)};\r\n position: absolute;\r\n transform-origin: top left;\r\n color: ${props => (props.error ? theme.colors.digitalBrightRed[100] : props.color || theme.colors.nightSkyBlack[60])};\r\n left: 16px;\r\n font-family: ${theme.fontSecondary};\r\n font-weight: ${theme.fontWeights.medium};\r\n margin: 0;\r\n transition: all 0.1s ease-in-out;\r\n pointer-events: ${props => (props.clickable ? 'unset' : 'none')};\r\n padding-bottom: 0;\r\n display: inline-block;\r\n line-height: normal;\r\n ${props => positionLabel(props.type, props.error)};\r\n ${props => floatLabel(props.active, props.type, props.error)};\r\n ${errorFieldProps};\r\n`;\r\n\r\nLabel.displayName = 'Label';\r\n\r\nLabel.defaultProps = {\r\n theme: theme,\r\n active: false\r\n};\r\n\r\nexport default Label;\r\n","// Lodge Locations Selectors\r\n\r\nexport const getLocationList = state => state.locationList;\r\n\r\nexport const getLocation = (state, locationCode) => state?.locationList[locationCode] || {};\r\n\r\nexport const getLocationPhone = (state, locationCode) => getLocation(state, locationCode).phone;\r\n\r\nexport const getLocationURL = (state, locationCode) => getLocation(state, locationCode).url;\r\n\r\nexport const getLocationDisplayName = (state, shorthandOrCode) => getLocation(state, shorthandOrCode).display;\r\n\r\n/**\r\n * Check if the user has a location already selected\r\n * @param {array} locationSelectedValues Locations selected by the user\r\n * @param {string} locationCode Property code to check if the user has selected\r\n * @returns bool whether the user has a location already selected\r\n */\r\nexport const containsLocation = (locationSelectedValues, locationCode) => {\r\n return locationSelectedValues.includes(locationCode);\r\n};\r\n\r\n/**\r\n * Get locations/properties by region in a dictionary\r\n * @returns dict\r\n */\r\nexport const getPropertiesByRegion = state => {\r\n let regions = Object.entries(state.locationList).map(([key, value]) => {\r\n return value.region;\r\n });\r\n regions = [...new Set(regions)];\r\n\r\n const locations = Object.entries(state.locationList).map(([key, value]) => {\r\n return {\r\n display: value.display,\r\n region: value.region,\r\n operaCode: value.operaCode\r\n };\r\n });\r\n\r\n let propertiesByRegion = {};\r\n\r\n regions.forEach(region => {\r\n propertiesByRegion[region] = locations.filter(location => location.region === region);\r\n });\r\n\r\n return propertiesByRegion;\r\n};\r\n\r\n/**\r\n * Get regions selected by the user\r\n * @param {array} locationSelectedValues Locations selected by the user\r\n * @returns array containing the names of the regions where the user is subscribed\r\n */\r\nexport const regionsSelected = (state, locationSelectedValues) => {\r\n const propsByRegion = getPropertiesByRegion(state);\r\n const filtered = Object.keys(propsByRegion).filter(key =>\r\n propsByRegion[key].some(location => containsLocation(locationSelectedValues, location.operaCode))\r\n );\r\n\r\n return filtered;\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\n\r\nimport { Text } from '..';\r\nimport { deleteState } from '../../../infrastructure/middleware/storage/reduxLocalStorage';\r\nimport theme from '../themes/theme';\r\nimport { TextLikeLink } from './styles';\r\n\r\nconst propTypes = {\r\n /** Changes the hover color for text and icons */\r\n hoverColor: PropTypes.string,\r\n /** Changes the default color for text and icons */\r\n color: PropTypes.string,\r\n /** Changes the text font weight */\r\n fontWeight: PropTypes.number,\r\n /** Use this prop to clear redux local storage on redirects */\r\n clearStateOnRedirect: PropTypes.bool,\r\n /** An string indicating if the component should render an element that is different from the normal anchor element. */\r\n as: PropTypes.string,\r\n /** Icon to display */\r\n icon: PropTypes.func,\r\n /** Size of the icon */\r\n size: PropTypes.string,\r\n /** Position for the icon */\r\n iconPosition: PropTypes.oneOf(['left', 'right']),\r\n /** Prop to add the underline to the component */\r\n underline: PropTypes.bool,\r\n /** Props to be passed to the icon component */\r\n iconProps: PropTypes.object\r\n};\r\n\r\nconst defaultProps = {\r\n color: theme.colors.preciousStoneBlue[100],\r\n fontWeight: theme.fontWeights.bold,\r\n clearStateOnRedirect: false,\r\n as: 'a',\r\n iconPosition: 'right',\r\n size: '14px',\r\n underline: true,\r\n iconProps: null,\r\n lineHeight: null\r\n};\r\n\r\n/** Use the `TextLink` component to indicate a clickable text */\r\nconst TextLink = ({\r\n clearStateOnRedirect,\r\n onClick,\r\n children,\r\n icon: Icon,\r\n size,\r\n fontSize,\r\n iconPosition,\r\n iconProps,\r\n lineHeight,\r\n ...restProps\r\n}) => {\r\n const handleClick = () => {\r\n if (clearStateOnRedirect) {\r\n deleteState();\r\n }\r\n\r\n onClick && onClick();\r\n };\r\n\r\n return (\r\n \r\n {Icon && iconPosition === 'left' && }\r\n \r\n {children}\r\n \r\n {Icon && iconPosition === 'right' && }\r\n \r\n );\r\n};\r\n\r\nTextLink.defaultProps = defaultProps;\r\nTextLink.propTypes = propTypes;\r\n\r\nexport default TextLink;\r\n","import TextLink from './TextLink';\r\n\r\nexport default TextLink;\r\n","import { API_URLS, getApiUrl } from '../Utils/apiURLConfiguration';\r\nimport GWRApiClient from './GWRApiClient';\r\n\r\n/**\r\n * Concrete implementation for the Reservation endpoints\r\n *\r\n * @class ReservationsApiClient\r\n * @extends {GWRApiClient}\r\n */\r\nexport default class ReservationsApiClient extends GWRApiClient {\r\n /**\r\n * @constructor\r\n * Calls parent constructor.\r\n * If there isn't any url provided, then we use the default from the environment variable\r\n * fills the url and token information\r\n * @param {string} url\r\n * The url where the service endpoints are\r\n * @param {string} token\r\n * The token of the logged user\r\n */\r\n constructor(version = '', token = '') {\r\n let apiVersion = version !== '' ? version : `v2`;\r\n\r\n const urlAux = getApiUrl(API_URLS.REACT_APP_RESERVATION_SERVICE_ENDPOINT, apiVersion);\r\n\r\n super(urlAux, token);\r\n }\r\n\r\n /**\r\n * @function\r\n * Get a reservation by its Id\r\n * @param {int} reservationId\r\n */\r\n async getReservationsById(reservationId) {\r\n const urlRequest = `${this.url}/${reservationId}`;\r\n\r\n let request = await super.getApiCallAuth(urlRequest);\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * @function\r\n * Get's an object that specifies wether or not the reservetation is elligible for virtual check-in,\r\n * it's worth noticing that reservation is elligible for virtual checking if it's due to 24h, there\r\n * maybe some cases when the Nor1 API isn't synced so it may respond with a non elligible flag.\r\n * @param {number} reservationId Reservation number.\r\n */\r\n async getReservationCheckIn(reservationId) {\r\n const urlRequest = `${this.url}/${reservationId}/check-in`;\r\n\r\n const request = await super.getApiCallAuth(urlRequest);\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * @deprecated This function and the components where it's used should be removed in a future release.\r\n * Get all reservations by Phone number and last four numbers of the Credit Card\r\n * @param {string} phone\r\n * @param {int} creditCard\r\n */\r\n async getAllReservationsByPhoneAndCc(phone, creditCard) {\r\n const urlRequest = `${this.url}/phone`;\r\n\r\n let queryParams = {\r\n PhoneNumber: phone,\r\n LastFourCc: creditCard\r\n };\r\n\r\n let request = await super.getApiCallAuth(urlRequest, queryParams);\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * @function\r\n * Get all reservations by Email and last four numbers of the Credit Card\r\n * @param {string} email\r\n * @param {int} creditCard\r\n */\r\n async getAllReservationsByEmailAndCc(email, creditCard) {\r\n const urlRequest = `${this.url}/email`;\r\n\r\n let queryParams = {\r\n Email: email,\r\n LastFourCc: creditCard\r\n };\r\n\r\n let request = await super.getApiCallAuth(urlRequest, queryParams);\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * @function\r\n * Get all reservations by Reservation Id and Last Name\r\n * @param {int} reservationId\r\n * @param {string} lastName\r\n */\r\n async getReservationsByIdAndLastName(reservationId, lastName) {\r\n const urlRequest = `${this.url}/last-name`;\r\n\r\n let queryParams = {\r\n ReservationId: reservationId,\r\n LastName: lastName\r\n };\r\n\r\n let request = await super.getApiCall(urlRequest, queryParams);\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * @function\r\n * Get reservations by Reservation Id and Reservation Key\r\n * @param {number} reservationId\r\n * @param {string} reservationKey\r\n */\r\n async getReservationsByIdAndReservationKey(reservationId, reservationKey) {\r\n const urlRequest = `${this.url}/fetch`;\r\n\r\n const queryParams = {\r\n ReservationId: reservationId,\r\n ReservationKey: reservationKey\r\n };\r\n\r\n const request = await super.getApiCall(urlRequest, queryParams);\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * @function\r\n * Send a PUT request to cancel the reservation by Id.\r\n * @param {number} reservationId\r\n */\r\n async cancelReservationById(reservationId) {\r\n const actionUrl = `${reservationId}/cancel`;\r\n\r\n const urlRequest = `${this.url}/${actionUrl}`;\r\n\r\n let request = await super.putApiCallAuth(urlRequest, {});\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * @function\r\n * Send a PUT request to modify a reservation.\r\n * @param {Object} reservation Reservation payload.\r\n * The reservation modified fields\r\n */\r\n async modifyReservation(reservation) {\r\n const urlRequest = `${this.url}/modify`;\r\n\r\n let request = await super.putApiCall(urlRequest, reservation);\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * @function\r\n * Create a new reservation for the current user\r\n * @param {object} reservation\r\n */\r\n async createSuiteReservation(reservation) {\r\n const urlRequest = this.url;\r\n\r\n const shouldUseAuthCall = super.shouldUseAuthenticatedCalls();\r\n\r\n let request = null;\r\n\r\n // This to allow backend to update the User Profile\r\n if (shouldUseAuthCall) {\r\n request = await super.postApiCallAuth(urlRequest, reservation);\r\n } else {\r\n request = await super.postApiCall(urlRequest, reservation);\r\n }\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * Create a new daypass for the current user.\r\n * @param {Object} reservation payload object\r\n * @returns\r\n * @see {@link https://gwrdev-azure.greatwolf.com/reservation/index.html?urls.primaryName=V2} for information on model object.\r\n */\r\n async createDayPassReservation(reservation) {\r\n const urlRequest = `${this.url}/daypass`;\r\n\r\n return super.postApiCall(urlRequest, reservation);\r\n }\r\n\r\n /**\r\n * Add a cabana for your reservation\r\n * @param {Object} Cabanas payload object\r\n */\r\n async addCabana(cabanasRequest) {\r\n const urlRequest = `${this.url}/cabana`;\r\n return super.postApiCall(urlRequest, cabanasRequest);\r\n }\r\n\r\n async addCabanaV3(reservationId, cabanasRequest, lastName) {\r\n const urlRequest = `${this.url}/${reservationId}/packages/cabana?last-name=${lastName}`;\r\n return super.postApiCall(urlRequest, cabanasRequest);\r\n }\r\n\r\n async getCabanaDeposit(request) {\r\n const urlRequest = `${this.url}/${request.id}/packages/availability/cabana/${request.cabanaRoomCode}/${request.cabanaRateCode}?${request.extraParams}`;\r\n\r\n let result = await super.getApiCall(urlRequest, request.queryParams);\r\n\r\n return result;\r\n }\r\n\r\n async fetchCabanasV3(resId) {\r\n const urlRequest = `${this.url}/${resId}/packages/availability/cabana`;\r\n\r\n let result = await super.getApiCall(urlRequest);\r\n\r\n return result;\r\n }\r\n\r\n async getDynamicTilesV3(request) {\r\n const urlRequest = `${this.url}/${request.resId}/dynamic-tile`;\r\n\r\n let result = await super.getApiCallAuth(urlRequest, request.queryParams);\r\n\r\n return result;\r\n }\r\n\r\n async fakeGetDynamicTilesV3(request) {\r\n throw new Error('dynamic-tile disabled temporarily');\r\n }\r\n\r\n async getFolio(request) {\r\n const urlRequest = `${this.url}/${request.resId}/folio`;\r\n\r\n let result = await super.getApiCall(urlRequest, request.queryParams);\r\n\r\n return result;\r\n }\r\n\r\n async getDiningCredits(request) {\r\n const urlRequest = `${this.url}/${request.resId}/dining-credits`;\r\n\r\n let result = await super.getApiCall(urlRequest, request.queryParams);\r\n\r\n return result;\r\n }\r\n}\r\n","/*\r\nAs detailed on this user story: https://dev.azure.com/gwdigital/GW%20Digital%20Project/_workitems/edit/55167/\r\nduring the removal of the 'moment' date library it was chosen to have\r\nthis file be the only place where 'moment' would be allowed to be imported or mentioned.\r\n*/\r\nimport moment from 'moment';\r\nimport {\r\n DateRangePicker,\r\n DayPicker,\r\n DayPickerRangeController,\r\n DayPickerSingleDateController,\r\n SingleDatePicker,\r\n toISODateString\r\n} from 'react-dates';\r\nimport {\r\n ANCHOR_LEFT,\r\n END_DATE,\r\n HORIZONTAL_ORIENTATION,\r\n START_DATE,\r\n VERTICAL_ORIENTATION,\r\n VERTICAL_SCROLLABLE\r\n} from 'react-dates/constants';\r\nimport { GwDatesWrapper } from './gwDatesWrapper';\r\n\r\nexport {\r\n ANCHOR_LEFT as GW_ANCHOR_LEFT,\r\n END_DATE as GW_END_DATE,\r\n HORIZONTAL_ORIENTATION as GW_HORIZONTAL_ORIENTATION, START_DATE as GW_START_DATE, VERTICAL_ORIENTATION as GW_VERTICAL_ORIENTATION,\r\n VERTICAL_SCROLLABLE as GW_VERTICAL_SCROLLABLE\r\n};\r\n\r\n// Check to see if the input provided is 'moment' object\r\nconst isMoment = inputData => {\r\n return inputData instanceof moment;\r\n};\r\n\r\nconst formatStr = GwDatesWrapper.gwDateFromat;\r\n\r\n// Helper to convert 'moment' object values into standard string dates.\r\n// Input can be an object, an array, or a single value. It would recurse\r\n// through all entries to convert the entire input (all indeces of array\r\n// and all properties of an Object)\r\nconst convertMomentToDates = inputData => {\r\n try {\r\n // Return null/undefined if input is null/undefined\r\n if (!inputData) return inputData;\r\n\r\n // Check type of input data\r\n if (isMoment(inputData)) {\r\n // Single moment object\r\n return GwDatesWrapper.format(inputData, formatStr);\r\n } else if (Array.isArray(inputData)) {\r\n // Array of potential moment objects\r\n return inputData.map(val => convertMomentToDates(val));\r\n } else if ({}.constructor === inputData.constructor) {\r\n // JSON with potential moment object properties\r\n return Object.entries(inputData).reduce((acc, [key, val]) => {\r\n acc[key] = convertMomentToDates(val);\r\n return acc;\r\n }, {});\r\n } else return inputData;\r\n } catch (ex) {\r\n console.error('convertMomentToDates', ex);\r\n return inputData;\r\n }\r\n};\r\n\r\n// Helper to convert standard string dates into 'moment' object values.\r\n// Input can be an object, an array, or a single value. It would recurse\r\n// through all entries to convert the entire input (all indeces of array\r\n// and all properties of an Object)\r\nconst convertDatesToMoment = inputData => {\r\n // Check to see if the input provided is a string in standard date format\r\n const isDateStr = inputStr => {\r\n // input needs to be of string type\r\n if (typeof inputStr !== 'string') return false;\r\n // input needs to have the same length as format string\r\n inputStr = inputStr.substring(0, formatStr.length);\r\n // check input against the default/standard date format\r\n const formatPieces = formatStr.split('-');\r\n const inputPieces = inputStr.split('-');\r\n\r\n // check if equal count of pieces based on separator\r\n if (formatPieces.length !== inputPieces.length) return false;\r\n // length of each piece\r\n for (let i = 0; i < formatPieces.length; i++) {\r\n // if any piece is not same, then its not in desired format\r\n if (formatPieces[i].length !== inputPieces[i].length) {\r\n return false;\r\n }\r\n }\r\n // if same count of pieces and all pieces are same length\r\n // means input string is in standard date format\r\n return true;\r\n };\r\n\r\n try {\r\n // Return null/undefined if input is null/undefined\r\n if (!inputData) return inputData;\r\n\r\n // Check type of input data\r\n if (isMoment(inputData)) {\r\n // moment object\r\n return inputData; // Nothing to do - already a moment\r\n } else if (isDateStr(inputData)) {\r\n // Single string representing a date\r\n return moment(inputData);\r\n } else if (Array.isArray(inputData)) {\r\n // Array of dates\r\n return inputData.map(val => convertDatesToMoment(val));\r\n } else if ({}.constructor === inputData.constructor) {\r\n // JSON with date properties\r\n return Object.entries(inputData).reduce((acc, [key, val]) => {\r\n acc[key] = convertDatesToMoment(val);\r\n return acc;\r\n }, {});\r\n } else return inputData;\r\n } catch (ex) {\r\n console.error('convertDatesToMoment', ex);\r\n return inputData;\r\n }\r\n};\r\n\r\n// Change handlers (functions) of given set of props so that outer components can send\r\n// in dates in string format, but downstream 'react-dates' component will\r\n// receive 'moment' objects; also outer component can return dates in string format\r\n// but the converted function from this helper will send 'moment' objects to the\r\n// 'react-dates' component.\r\nconst changeHandlersForMoments = (propsWithHandlers, nameOfHandlersToReplace) => {\r\n const convertedProps = { ...propsWithHandlers };\r\n nameOfHandlersToReplace.forEach(name => {\r\n const origHandler = propsWithHandlers[name]; // Original handler that will return date in string format\r\n if (origHandler) {\r\n const newHandler = (param1, param2, param3, param4, param5) => {\r\n // New handler capable of returning moment\r\n // convert input parameter to dateStr (in case of any moment) and capture output from original handler\r\n const dateStrOutput = origHandler(\r\n convertMomentToDates(param1),\r\n convertMomentToDates(param2),\r\n convertMomentToDates(param3),\r\n convertMomentToDates(param4),\r\n convertMomentToDates(param5)\r\n );\r\n // convert output of original handler (which is expected to be a dateStr) into moment and return that\r\n const convertedOutput = convertDatesToMoment(dateStrOutput);\r\n return convertedOutput;\r\n };\r\n // update props with new hanlder (that receives moment but calls original handler with dateStr)\r\n convertedProps[name] = newHandler;\r\n }\r\n });\r\n return convertedProps;\r\n};\r\n\r\n// ******************************************************************************************\r\n// *** Generic wrapper component that is re-used for creating specific wrapper components ***\r\n// *** in order to provide moment-agnostic versions of 'reac-dates' components ***\r\n// ******************************************************************************************\r\n// Documentation used for names of 'react-dates' library props and handlers in this wrapper component:\r\n// DateRangePicker --> https://github.com/react-dates/react-dates?tab=readme-ov-file#daterangepicker\r\n// GWDayPickerRangeController --> https://github.com/react-dates/react-dates?tab=readme-ov-file#daypickerrangecontroller\r\n// SingleDatePicker --> https://github.com/react-dates/react-dates?tab=readme-ov-file#singledatepicker\r\n// DayPicker --> https://github.com/react-dates/react-dates/blob/master/src/components/DayPicker.jsx\r\n// DayPickerSingleDateController --> https://github.com/react-dates/react-dates/blob/master/src/components/DayPickerSingleDateController.jsx\r\n// ******************************************************************************************\r\n// Additionally, in future, we'll have to find substitutes for these components to remove dependency on\r\n// 'react-dates' library in order to eliminate use of 'moment' from code base. The idea would be to find\r\n// substitutes that can produce current UI/output, using same/similar input (props & hanlders), have no\r\n// reliance on 'moment' library and also provide better run-time chunk size (good support for tree shaking\r\n// and lazy loading).\r\n//\r\n// To get things started, here is an article that talks about a few other date pickers:\r\n// --> https://blog.logrocket.com/top-react-date-pickers/#comparing-date-pickers\r\n// ******************************************************************************************\r\n\r\nconst GWReactDatesWrapper = ({ ComponentToWrap, ...props }) => {\r\n const propsNeedingMoment = ['minDate', 'maxDate', 'startDate', 'endDate', 'date', 'focusedDate'];\r\n const handlersForDateConvert = [\r\n 'onDateChange',\r\n 'onDatesChange',\r\n 'onPrevMonthClick',\r\n 'onNextMonthClick',\r\n 'onClose',\r\n 'isDayBlocked',\r\n 'isOutsideRange',\r\n 'isDayHighlighted',\r\n 'initialVisibleMonth',\r\n 'onFocusChange'\r\n ];\r\n // handlers not included in above 'handlersForDateConvert' list\r\n // --> renderCalendarInfo, onOutsideClick, renderCalendarDay, renderDayContents, renderMonthText, renderMonthElement\r\n\r\n // Change inputs of given set of props so that outer components can send\r\n // in dates in string format, but downstream 'react-dates' compoent will\r\n // receive 'moment' objects.\r\n\r\n propsNeedingMoment.forEach(name => {\r\n if (props[name]) {\r\n props[name] = convertDatesToMoment(props[name]);\r\n }\r\n });\r\n\r\n props = changeHandlersForMoments(props, handlersForDateConvert);\r\n\r\n return ;\r\n};\r\n\r\nexport const GWRDateRangePicker = ({ ...props }) => {\r\n return ;\r\n};\r\n\r\nexport const GWDayPickerRangeController = ({ ...props }) => {\r\n return ;\r\n};\r\n\r\nexport const GWSingleDatePicker = ({ ...props }) => {\r\n return ;\r\n};\r\n\r\nexport const GWDayPicker = ({ ...props }) => {\r\n return ;\r\n};\r\n\r\nexport const GWDayPickerSingleDateController = ({ ...props }) => {\r\n return ;\r\n};\r\n\r\n// Helper functions based on 'react-dates' code from:\r\n\r\n// https://github.com/react-dates/react-dates/blob/be4ef1e52f012a79128021b8f92fdcbcad6cd168/src/utils/isInclusivelyAfterDay.js\r\nexport const gwIsInclusivelyAfterDay = (dt1, dt2) => {\r\n return GwDatesWrapper.isValid(dt1) && GwDatesWrapper.isValid(dt2) && !GwDatesWrapper.isBefore(dt1, dt2);\r\n};\r\n\r\nexport const gwToISODateString = date => {\r\n return toISODateString(date);\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport styled from 'styled-components';\r\nimport Box from './Box';\r\nimport Text from './Text';\r\nimport CheckIcon from './icons/Check';\r\nimport theme from './themes/theme';\r\n\r\nconst Checkbox = props => {\r\n const {\r\n redesignWidth,\r\n redesignHeight,\r\n disabled,\r\n size,\r\n id,\r\n isRedesign,\r\n tabIndex,\r\n checked,\r\n secondary,\r\n valign,\r\n ...inputProps\r\n } = props;\r\n\r\n return (\r\n \r\n {isRedesign ? (\r\n \r\n \r\n \r\n \r\n ) : (\r\n \r\n )}\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst RedesignInput = styled('div')`\r\n display: inline-block;\r\n width: ${({ redesignWidth }) => (redesignWidth ? redesignWidth : '16')}px;\r\n height: ${({ redesignHeight }) => (redesignHeight ? redesignHeight : '16')}px;\r\n border-radius: 2px;\r\n position: relative;\r\n vertical-align: 'top';\r\n border: 1px solid ${theme.colors.deepForestGreen[100]};\r\n background-color: ${({ checked, secondary }) =>\r\n checked\r\n ? secondary\r\n ? theme.colors.preciousStoneBlue[100]\r\n : theme.colors.successGreen\r\n : theme.colors.pureWhite[0]};\r\n\r\n svg {\r\n display: none;\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n pointer-events: none;\r\n }\r\n\r\n input {\r\n opacity: 0;\r\n margin: 0;\r\n width: 100%;\r\n height: 100%;\r\n\r\n &:checked ~ svg {\r\n display: block;\r\n }\r\n }\r\n`;\r\n\r\nconst CheckBoxWrapper = styled(Box)`\r\n width: ${({ redesignWidth }) => (redesignWidth ? redesignWidth : '16')}px;\r\n height: ${({ redesignHeight }) => (redesignHeight ? redesignHeight : '16')}px;\r\n display: inline-block;\r\n position: relative;\r\n vertical-align: ${props => (props.valign ? props.valign : 'top')};\r\n margin-top: ${props => (props.valign ? '0' : '-2px')};\r\n cursor: ${({ disabled }) => (disabled ? null : 'pointer')};\r\n color: ${props => (props.disabled ? props.theme.colors.deepForestGreen[20] : props.theme.colors.deepForestGreen[50])};\r\n svg[data-name='checked'] {\r\n display: none;\r\n }\r\n > input:checked {\r\n & ~ svg[data-name='checked'] {\r\n display: inline-block;\r\n color: ${props =>\r\n props.disabled ? props.theme.colors.deepForestGreen[20] : props.theme.colors.deepForestGreen[50]};\r\n }\r\n & ~ svg[data-name='empty'] {\r\n display: none;\r\n }\r\n }\r\n`;\r\n\r\nCheckBoxWrapper.defaultProps = { theme };\r\n\r\nCheckbox.displayName = 'Checkbox';\r\n\r\nCheckbox.propTypes = {\r\n name: PropTypes.string,\r\n id: PropTypes.string.isRequired,\r\n size: PropTypes.number,\r\n defaultChecked: PropTypes.bool,\r\n disabled: PropTypes.bool,\r\n onChange: PropTypes.func,\r\n theme: PropTypes.object,\r\n redesignHeight: PropTypes.number,\r\n redesignWidth: PropTypes.number\r\n};\r\n\r\nCheckbox.defaultProps = {\r\n size: 20,\r\n disabled: false,\r\n onChange: () => {},\r\n theme: theme\r\n};\r\n\r\nexport default Checkbox;\r\n","// Offer Actions\r\n\r\nimport { getNormalizedCode } from '../../../utilities/availabilityUtils';\r\nimport offerActionTypes from './offer.types';\r\n\r\nexport const addOfferCode = code => ({\r\n type: offerActionTypes.ADD_OFFER_CODE,\r\n code: getNormalizedCode(code)\r\n});\r\n\r\nexport const removeOfferCode = () => ({ type: offerActionTypes.REMOVE_OFFER_CODE });\r\nexport const setOfferCodeDescription = description => dispatch => {\r\n dispatch({\r\n type: offerActionTypes.SET_OFFER_CODE_DESCRIPTION,\r\n description: description\r\n });\r\n};\r\nexport const addActiveOffer = offerData => dispatch => {\r\n dispatch({\r\n type: offerActionTypes.ADD_OFFER_ACTIVE_TYPE,\r\n offerData: offerData\r\n });\r\n};\r\nexport const addEmailActiveOffer = offerData => dispatch => {\r\n dispatch({\r\n type: offerActionTypes.ADD_OFFER_EMAIL_ACTIVE_TYPE,\r\n offerData: offerData\r\n });\r\n};\r\nexport const removeActiveOffer = offerData => dispatch => {\r\n dispatch({\r\n type: offerActionTypes.REMOVE_OFFER_ACTIVE_TYPE,\r\n offerData: offerData\r\n });\r\n};\r\n\r\nexport const verifyActiveOffers = offerData => dispatch => {\r\n dispatch({\r\n type: offerActionTypes.VERIFY_ACTIVE_OFFERS,\r\n offerData: offerData\r\n });\r\n};\r\n","/**\r\n * Pushes current value into the accumulator and returns the accumulator to be\r\n * used in a reduce function.\r\n *\r\n * @param {Array} accumulator Array of items\r\n * @param {number} currentValue Array key\r\n * @returns {Array} Accumulator with new item\r\n */\r\nfunction transformationFn(accumulator, currentValue) {\r\n accumulator.push(currentValue);\r\n return accumulator;\r\n}\r\n\r\n/**\r\n * Generates an array based on the length and transformation passed, if no\r\n * transformastion is passed to the array it will return an array with the\r\n * array length keys as items.\r\n *\r\n * @export\r\n * @param {number} [arrayLength=0]\r\n * @param {function} [transformation=transformationFn]\r\n * @returns {undefined|Array} Undefined if called without arguments otherwise,\r\n * returns an array with the umber of items provided.\r\n */\r\nfunction generateArray(arrayLength = 0, transformation = transformationFn) {\r\n if (!arrayLength) return [];\r\n return [...Array(arrayLength).keys()].reduce(transformation, []);\r\n}\r\n\r\nexport default generateArray;\r\n","import React from 'react'\n\nconst CheckIcon = ({\n size,\n color,\n ...props\n}) => (\n \n)\n\nCheckIcon.displayName = 'CheckIcon'\n\nCheckIcon.defaultProps = {\n size: 24,\n color: 'currentcolor'\n}\n\nexport default CheckIcon","import { DATE_FORMATS } from '../../../utilities/constants';\r\nimport { GwDatesWrapper } from '../../_internal_date_/gwDatesWrapper';\r\n\r\nconst days = (date_1, date_2) => {\r\n let difference = date_1.getTime() - date_2.getTime();\r\n let TotalDays = Math.ceil(difference / (1000 * 3600 * 24));\r\n return TotalDays;\r\n};\r\n\r\nexport const addResortLocationToOffer = (resortLocation, offer) => ({ resortLocation, ...offer });\r\n\r\nexport const formatOffer = (offer, isCheckBoxActive, checkIn, checkOut) => {\r\n // CREATE TEMP FORMAT\r\n const offerObject = {\r\n ...offer\r\n };\r\n // ADD CHECKBOX\r\n offerObject.checkBoxActive = isCheckBoxActive;\r\n\r\n const checkInDate = GwDatesWrapper.format(checkIn, DATE_FORMATS.default);\r\n const checkOutDate = GwDatesWrapper.format(checkOut, DATE_FORMATS.default);\r\n const offerStayStart = GwDatesWrapper.format(offer.stayStartDate, DATE_FORMATS.default);\r\n const offerStayEnd = GwDatesWrapper.format(offer.stayEndDate, DATE_FORMATS.default);\r\n\r\n offerObject.searchIsWithinOfferDates =\r\n GwDatesWrapper.isSameOrAfter(checkInDate, offerStayStart) &&\r\n GwDatesWrapper.isSameOrBefore(checkOutDate, offerStayEnd);\r\n\r\n // ADD EXPIRATION\r\n const todayDate = new Date();\r\n const compareDate = new Date(offer.bookByDate);\r\n const isExpiring = days(compareDate, todayDate);\r\n offerObject.expiringSoon = isExpiring < 14 ? true : false;\r\n\r\n return offerObject;\r\n};\r\n\r\nexport const nonExpiredOrderByDateOffers = (offers, isCheckBoxActive, checkIn, checkOut) => {\r\n const formattedOffers = offers.map(offer => formatOffer(offer, isCheckBoxActive, checkIn, checkOut));\r\n let nonExpiredOffers = [];\r\n let notEligibleOffers = [];\r\n const todayDate = GwDatesWrapper.today();\r\n\r\n formattedOffers.forEach(offer => {\r\n const stayEndDate = GwDatesWrapper.format(offer.stayEndDate, DATE_FORMATS.default);\r\n if (GwDatesWrapper.isSameOrAfter(stayEndDate, todayDate) && offer.searchIsWithinOfferDates) {\r\n nonExpiredOffers.push(offer);\r\n } else notEligibleOffers.push(offer);\r\n });\r\n return nonExpiredOffers\r\n .sort(function(a, b) {\r\n return new Date(a.bookByDate) - new Date(b.bookByDate);\r\n })\r\n .concat(notEligibleOffers);\r\n};\r\n","import { API_URLS, getApiUrl } from '../Utils/apiURLConfiguration';\r\nimport GWRApiClient from './GWRApiClient';\r\n\r\n/**\r\n * Concrete implementation for the User Account endpoints on Tioga\r\n *\r\n * @class UserAccountApiClient\r\n * @extends {GWRApiClient}\r\n */\r\nexport default class UserAccountApiClientTioga extends GWRApiClient {\r\n constructor(version = '', token = '') {\r\n let apiVersion = version !== '' ? version : `v1`;\r\n\r\n const urlAux = getApiUrl(API_URLS.REACT_APP_USERACCOUNT_ENDPOINT_TIOGA, apiVersion);\r\n\r\n super(urlAux, token);\r\n }\r\n\r\n /**\r\n * @function\r\n * Get user informstion based on token\r\n */\r\n async getUserUpdatedPointsAndOffers() {\r\n const urlRequest = `${this.url}/loyalty/balance`;\r\n let request = await super.getApiCallAuth(urlRequest);\r\n return request;\r\n }\r\n\r\n /**\r\n * @function\r\n * Get user point history information based on token and page\r\n * @param {requestObject: {page: number}} requestObject\r\n */\r\n async fetchUserPointsHistory(requestObject) {\r\n const urlRequest = `${this.url}/loyalty/history`;\r\n let request = await super.getApiCallAuth(urlRequest, requestObject?.queryParams);\r\n return request;\r\n }\r\n\r\n /**\r\n * @function\r\n * Update user settings for my profile and my preferences pages\r\n * @param requestObject\r\n */\r\n async updateUserSettings(requestObject) {\r\n const urlRequest = `${this.url}`;\r\n let request = await super.patchApiCallAuth(urlRequest, requestObject);\r\n return request;\r\n }\r\n}\r\n","//DINING CREDIT SECTION TITLE\r\nexport const LEARN_MORE = 'Learn More';\r\nexport const BUY_DINING_CREDITS_NOW =\r\n 'Buy dining credits now to save at all Great Wolf Lodge Restaurants during your stay.';\r\n\r\n//DINING CREDIT LEARN MORE MODAL\r\nexport const INFO_TEXT =\r\n 'Explore the restaurant menus in our app. You can Dine-In at the restaurants or mobile order through our app.';\r\nexport const RESTAURANTS = 'Restaurants Where You Can Use Your Dining Credits:';\r\nexport const INFO_LIST = [\r\n 'Deal is only available for purchase before your stay',\r\n 'Dining credits may be used anytime during your stay',\r\n 'Credit is per room, per stay, and unused credit cannot be rolled over into a future stay'\r\n];\r\nexport const DINING_CREDIT_PACKAGE_TITLE = `$ dining credits for $`;\r\n\r\n//DINING PAGE TITLE\r\nexport const DINING_TITLE = 'Save Later When You Buy Today!';\r\nexport const DINING_STAR_SUBTITLE = 'Only Available Before Your Arrival';\r\nexport const DINING_TITLE_UFF_FLOW = 'Take Advantage Of These Bonus Offers';\r\nexport const DINING_SUBTITLE_UFF_FLOW =\r\n 'Add to your Ultimate Food & Fun Package with additional dining offers and credit deals.';\r\n\r\n//DINING CREDIT CARD\r\nexport const SAVE_TAG_TEXT = 'Save $';\r\n","import React from 'react'\n\nconst CheckedIconIcon = ({\n size,\n color,\n ...props\n}) => (\n \n)\n\nCheckedIconIcon.displayName = 'CheckedIconIcon'\n\nCheckedIconIcon.defaultProps = {\n size: 24,\n color: 'currentcolor'\n}\n\nexport default CheckedIconIcon","import React from 'react';\r\nimport LoadingSpinnerIcon from '../ui-kit/LoadingSpinner';\r\nimport theme from '../ui-kit/themes/theme';\r\nimport Modal from './Modal';\r\n\r\nconst ModalSpinner = props => (\r\n \r\n \r\n \r\n);\r\n\r\nexport default ModalSpinner;\r\n","import uuidv4 from 'uuid/v4';\r\n\r\nexport const getBrowserId = () => {\r\n let browserId = localStorage.getItem('browserId');\r\n if (!browserId) {\r\n const newUuid = uuidv4();\r\n localStorage.setItem('browserId', newUuid);\r\n browserId = newUuid;\r\n }\r\n return browserId;\r\n};\r\n\r\nexport const isInternetExplorer = () => {\r\n return navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0;\r\n};\r\n","// Get cart location\r\nexport const getCartResortLocation = state => state.cartResortLocation;\r\n\r\n// Get expired cart\r\nexport const getExpiredCart = state => state.expiredCart;\r\n\r\n// Get cart last visited step\r\nexport const getCartLastVisitedStep = state => state.cartLastVisitedStep;\r\n","import styled, { css } from 'styled-components';\r\nimport { space } from 'styled-system';\r\n\r\nimport { Box, Flex } from '../../../ui-kit';\r\nimport ArrowDownThinIcon from '../../../ui-kit/icons/ArrowDownThin';\r\nimport theme, { mediaQueries } from '../../../ui-kit/themes/theme';\r\n\r\nexport const Container = styled(Box)`\r\n font-family: ${theme.fontSecondary};\r\n\r\n ${space}\r\n ${mediaQueries.lg} {\r\n margin: 0;\r\n }\r\n`;\r\n\r\nexport const Content = styled(Box)`\r\n ${({ isCartVariation }) => {\r\n if (!isCartVariation) {\r\n return css`\r\n border: none;\r\n padding: 0px ${theme.space[3]}px 0px;\r\n border-radius: 0px 0px 20px 20px;\r\n `;\r\n }\r\n }}\r\n`;\r\n\r\nexport const Header = styled(Box)`\r\n flex: 1;\r\n`;\r\n\r\nexport const HeaderContainer = styled(Flex)`\r\n background-color: ${theme.colors.kiddiePoolBlue[20]};\r\n padding: 16px;\r\n border-radius: 0px;\r\n border: 1px solid ${theme.colors.kiddiePoolBlue[20]};\r\n align-items: center;\r\n color: ${theme.colors.deepLakeBlue[100]};\r\n\r\n ${mediaQueries.lg} {\r\n border-radius: 20px 20px 0px 0px;\r\n }\r\n`;\r\n\r\nexport const SummaryIcon = styled(ArrowDownThinIcon)`\r\n transition-duration: 0.4s;\r\n transition-property: transform;\r\n transform: rotate(${props => props.rotate || '0deg'});\r\n height: 12px;\r\n width: 20px;\r\n\r\n ${mediaQueries.lg} {\r\n height: 7px;\r\n width: 12px;\r\n }\r\n`;\r\n","import React, { createContext, useState, useContext } from 'react';\r\nimport { Container } from './styles';\r\nimport { SummaryAccordionContent } from './SummaryAccordionContent';\r\nimport { SummaryAccordionHeader } from './SummaryAccordionHeader';\r\n\r\nconst AccordionContext = createContext();\r\n\r\nexport const useAccordionContext = () => {\r\n const context = useContext(AccordionContext);\r\n\r\n if (!context) {\r\n throw new Error('Child components of SummaryAccordion cannot be rendered outside the SummaryAccordion Component!');\r\n }\r\n\r\n return context;\r\n};\r\n\r\nexport const SummaryAccordion = ({ shouldStartOpened, children, ...restProps }) => {\r\n const [expanded, setExpanded] = useState(shouldStartOpened);\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nSummaryAccordion.Content = SummaryAccordionContent;\r\n\r\nSummaryAccordion.Header = SummaryAccordionHeader;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\n\r\nimport { Content } from './styles';\r\nimport { useAccordionContext } from './SummaryAccordion';\r\n\r\nexport const SummaryAccordionContent = ({ children, variation, ...restProps }) => {\r\n const { expanded } = useAccordionContext();\r\n return (\r\n \r\n {children({ expanded: expanded })}\r\n \r\n );\r\n};\r\n\r\nSummaryAccordionContent.propTypes = {\r\n children: PropTypes.func.isRequired\r\n};\r\n","import React from 'react';\r\n\r\nimport { Box } from '../../../ui-kit';\r\nimport { Header, HeaderContainer, SummaryIcon } from './styles';\r\nimport { useAccordionContext } from './SummaryAccordion';\r\n\r\nexport const SummaryAccordionHeader = ({ children, ...restProps }) => {\r\n const { expanded, setExpanded } = useAccordionContext();\r\n\r\n return (\r\n \r\n \r\n setExpanded(!expanded)}>\r\n \r\n \r\n \r\n );\r\n};\r\n","import React from 'react';\r\nimport { Flex, Text } from '../../../../../ui-kit';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { StyledWave } from '../styles';\r\n\r\nconst CartHeader = ({ subTotal = 0 }) => {\r\n return (\r\n <>\r\n {/* Content Title and Subtotal */}\r\n \r\n \r\n {COPY.BOOKING_CART_TITLE}\r\n \r\n \r\n \r\n {subtotalCopy(subTotal)}\r\n \r\n \r\n {COPY.BOOKING_CART_SUBTOTAL}\r\n \r\n \r\n \r\n {/* Wave */}\r\n \r\n >\r\n );\r\n};\r\n\r\nexport default CartHeader;\r\n\r\nfunction subtotalCopy(subTotal) {\r\n // Check if subtotal has decimals and decimals are not 0\r\n const subTotalHasDecimals = subTotal % 1 !== 0 && subTotal % 1 !== 0.0;\r\n\r\n // if decimals is true return the subtotal with 2 decimal places\r\n if (subTotalHasDecimals) {\r\n return `$${subTotal}`;\r\n }\r\n // if it has no decimals or decimals are 0 return the subtotal with no decimal places\r\n return `$${Math.floor(subTotal)}`;\r\n}\r\n","import PropTypes from 'prop-types';\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport routes from '../../../../../routes';\r\nimport { emitEventsByName, EVENTS_DICTIONARY } from '../../../../../utilities/customEventsHelpers';\r\nimport { Box, Button } from '../../../../ui-kit';\r\nimport Scrollable from '../../../../ui-kit/Scrollable';\r\nimport theme from '../../../../ui-kit/themes/theme';\r\nimport { editCopyByReplaceString } from '../../../../utilities/copyFunctions';\r\nimport { handleTotal } from '../../../../utilities/utils';\r\nimport * as COPY from '../utilities/copy';\r\nimport CartHeader from './Content/CartHeader';\r\nimport { CartModalButtonsContainer, Overlay, OverlayContainer, ScrollContainer } from './styles';\r\n\r\nconst propTypes = {\r\n toggleOpen: PropTypes.func,\r\n cartHasPackages: PropTypes.bool,\r\n overlayVisible: PropTypes.bool,\r\n variation: PropTypes.string\r\n};\r\n\r\nconst defaultProps = {\r\n toggleOpen: () => {},\r\n cartHasPackages: false,\r\n overlayVisible: false,\r\n variation: null\r\n};\r\n\r\nconst CartOverlay = ({\r\n toggleOpen,\r\n cartHasPackages,\r\n overlayVisible,\r\n isCartVariation,\r\n children,\r\n onPlanPage,\r\n setIsCartOpenClose,\r\n isCartOpenClose,\r\n isCartExpired,\r\n cartLastVisitedStep,\r\n ...otherProps\r\n}) => {\r\n const {\r\n userOffers,\r\n activeOffers,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n currentSelectedPackages,\r\n setExcedent,\r\n isUserAuthenticated,\r\n summaryTotal,\r\n selectedSuite,\r\n pushToLastVisitedStep\r\n } = otherProps;\r\n const hasDiningPackages = currentSelectedPackages?.some(pkg => pkg.packageType?.includes('dining'));\r\n // Dynamic calculation os scroll height\r\n const [contentScrollHeight, setContentScrollHeight] = useState(0);\r\n const [continueButtonText, setContinueButtonText] = useState(\r\n getContinueTextOutsidePlan(cartLastVisitedStep, hasDiningPackages)\r\n );\r\n const cartHeader = useRef(null);\r\n const cartFooter = useRef(null);\r\n const isMobile = useMediaQuery({\r\n query: `(max-width: ${theme.breakpoints.md})`\r\n });\r\n\r\n const navigateToNextStep = () => {\r\n emitEventsByName(EVENTS_DICTIONARY.FLOW_TRIGGER_NEXT_STEP);\r\n };\r\n\r\n const getContinueButtonText = stepTextEvent => {\r\n const stepText = stepTextEvent?.detail?.text ?? null;\r\n if (stepTextEvent) {\r\n setContinueButtonText(editCopyByReplaceString(COPY.CONTINUE_TO_STEP, stepText, ''));\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n overlayVisible && setIsCartOpenClose(true);\r\n }, [setIsCartOpenClose, overlayVisible]);\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (isCartOpenClose && overlayVisible) {\r\n setIsCartOpenClose(false);\r\n }\r\n };\r\n }, [setIsCartOpenClose, isCartOpenClose, overlayVisible]);\r\n\r\n useEffect(() => {\r\n if (cartHeader.current && cartFooter.current) {\r\n const header = document.querySelector('.header-container__inner');\r\n const headerSize = header ? header.clientHeight : isMobile ? 58 : 68;\r\n\r\n setContentScrollHeight(\r\n vhToPixels(100) - cartHeader.current.clientHeight - cartFooter.current.clientHeight - headerSize\r\n );\r\n }\r\n\r\n if (cartHeader.current && !cartFooter.current) {\r\n setContentScrollHeight(vhToPixels(100) - cartHeader.current.clientHeight);\r\n }\r\n }, [isMobile, overlayVisible]);\r\n\r\n useEffect(() => {\r\n window.addEventListener(EVENTS_DICTIONARY.FLOW_NEXT_STEP_TEXT, e => getContinueButtonText(e));\r\n\r\n return () => {\r\n window.removeEventListener(EVENTS_DICTIONARY.FLOW_NEXT_STEP_TEXT, e => getContinueButtonText(e));\r\n };\r\n }, []);\r\n\r\n const subTotal = isUserAuthenticated\r\n ? handleTotal(\r\n userOffers,\r\n activeOffers,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n currentSelectedPackages,\r\n setExcedent\r\n ).toFixed(2)\r\n : summaryTotal?.toFixed(2);\r\n\r\n const continueBooking = () => {\r\n toggleOpen();\r\n if (onPlanPage) {\r\n navigateToNextStep();\r\n } else {\r\n pushToLastVisitedStep();\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n {isCartVariation ? (\r\n \r\n ) : null}\r\n\r\n \r\n {isCartVariation ? (\r\n \r\n \r\n \r\n ) : null}\r\n\r\n \r\n \r\n {children}\r\n \r\n \r\n {(isCartVariation && !onPlanPage && cartHasPackages && !isCartExpired) ||\r\n (isCartVariation && onPlanPage && cartHasPackages) ? (\r\n \r\n \r\n \r\n ) : null}\r\n \r\n >\r\n );\r\n};\r\n\r\nCartOverlay.propTypes = propTypes;\r\nCartOverlay.defaultProps = defaultProps;\r\n\r\nexport default CartOverlay;\r\n\r\nfunction vhToPixels(vh) {\r\n return Math.round(window.innerHeight / (100 / vh));\r\n}\r\n\r\nfunction getContinueTextOutsidePlan(cartLastVisitedStep, hasDiningPackages) {\r\n if (cartLastVisitedStep === routes.plan.dining.replace(/\\/$/, '')) {\r\n if (hasDiningPackages) {\r\n return editCopyByReplaceString(COPY.CONTINUE_TO_STEP, 'Payment', '');\r\n }\r\n return editCopyByReplaceString(COPY.CONTINUE_TO_STEP, 'Dining', '');\r\n }\r\n\r\n if (cartLastVisitedStep === routes.plan.activities.replace(/\\/$/, '')) {\r\n return editCopyByReplaceString(COPY.CONTINUE_TO_STEP, 'Activities', '');\r\n }\r\n\r\n if (cartLastVisitedStep === routes.plan.payment.replace(/\\/$/, '')) {\r\n return editCopyByReplaceString(COPY.CONTINUE_TO_STEP, 'Payment', '');\r\n }\r\n\r\n return COPY.CONTINUE_BOOKING;\r\n}\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\n\r\nimport { TESTS_DICTIONARY, getTestValueAB } from '../../../../../../utilities/ABTesting';\r\nimport { COSTSUMMARY_TOOLTIP, ROOM_RATE_TYPE } from '../../../../../../utilities/constants';\r\nimport { Box } from '../../../../../ui-kit';\r\nimport Tooltip from '../../../../../ui-kit/Tooltip';\r\nimport QuestionIcon from '../../../../../ui-kit/icons/Question';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { handleTaxes } from '../../../../../utilities/utils';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../../utilities/copy';\r\n\r\nconst SummaryTooltip = ({ isDesktop, title, children }) => {\r\n const isTablet = useMediaQuery({\r\n query: `(max-width: ${theme.breakpoints.xl})`\r\n });\r\n return (\r\n {\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n }}\r\n />\r\n );\r\n};\r\n\r\nconst propTypes = {\r\n /** Flag that indicates that the reservation has additional charges */\r\n hasAdditionalCharges: PropTypes.bool.isRequired,\r\n\r\n /** Array with the taxes and fees for reservation*/\r\n taxesAndFees: PropTypes.arrayOf(\r\n PropTypes.shape({\r\n id: PropTypes.string,\r\n name: PropTypes.string,\r\n amount: PropTypes.number,\r\n tooltip: PropTypes.string\r\n })\r\n ),\r\n\r\n /** Size for the tooltip icons */\r\n iconSize: PropTypes.number\r\n};\r\n\r\nexport const AdditionalCharges = ({\r\n hasAdditionalCharges,\r\n taxesAndFees,\r\n iconSize,\r\n roomAdjustmentTax,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n userOffers,\r\n activeOffers,\r\n numberOfNights,\r\n isParkingFeeABCDTestActive,\r\n currentParkingFeeAmount,\r\n isDesktop,\r\n rateType\r\n}) => {\r\n const shouldRenderAdditionalChargers = hasAdditionalCharges && taxesAndFees != null;\r\n\r\n if (!shouldRenderAdditionalChargers) return null;\r\n\r\n /* ABCD TEST FOR PARKING FEE */\r\n\r\n let ABTestTaxesAndFees = [...taxesAndFees];\r\n if (isParkingFeeABCDTestActive) {\r\n const parkingFee = {\r\n id: 'testParkingFee' + Math.floor(Math.random()),\r\n name: 'Parking Fee',\r\n amount: currentParkingFeeAmount * numberOfNights\r\n };\r\n\r\n if (!taxesAndFees.find(i => i.name === 'Parking Fee')) ABTestTaxesAndFees.push(parkingFee);\r\n }\r\n\r\n const optimizelyDisplayResortFeeWithTotalInSuiteCardJ = getTestValueAB(\r\n TESTS_DICTIONARY.optimizelyDisplayResortFeeWithTotalInSuiteCardJ,\r\n false\r\n );\r\n\r\n const optimizelyDisplayResortFeeWithTotalInSuiteCardH = getTestValueAB(\r\n TESTS_DICTIONARY.optimizelyDisplayResortFeeWithTotalInSuiteCardH,\r\n false\r\n );\r\n\r\n const isRoomOnly = rateType === ROOM_RATE_TYPE.roomOnlyWithoutWaterParkPass;\r\n\r\n /* ABCD TEST FOR PARKING FEE */\r\n\r\n return (\r\n <>\r\n \r\n \r\n {COPY.ADDITIONAL_CHARGES}\r\n \r\n\r\n {ABTestTaxesAndFees.map(item => {\r\n let taxAmount = handleTaxes(\r\n item.amount,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n roomAdjustmentTax,\r\n userOffers,\r\n activeOffers\r\n ).toFixed(2);\r\n\r\n return (\r\n \r\n \r\n {item.name}\r\n {item.tooltip && (\r\n \r\n \r\n \r\n )}\r\n \r\n {`$${\r\n item.name === 'Taxes' ? taxAmount : item.amount.toFixed(2)\r\n }`}\r\n \r\n );\r\n })}\r\n >\r\n );\r\n};\r\n\r\nAdditionalCharges.propTypes = propTypes;\r\n\r\nAdditionalCharges.defaultProps = {\r\n hasAdditionalCharges: false,\r\n taxesAndFees: [],\r\n iconSize: 16\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { useHistory } from 'react-router';\r\nimport { buildAddToCartEnhancedEcommerceObject } from '../../../../../../infrastructure/middleware/analytics/analyticsObjectBuilders';\r\nimport routes from '../../../../../../routes';\r\nimport { EVENT_CATEGORIES } from '../../../../../../utilities/constants';\r\nimport { pushEvent } from '../../../../../../utilities/dataLayerUtils';\r\nimport { Box, Flex, Text } from '../../../../../ui-kit';\r\nimport AlertSuccessIcon from '../../../../../ui-kit/icons/AlertSuccessIcon';\r\nimport CheckedIconIcon from '../../../../../ui-kit/icons/CheckedIcon';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { SummaryContent } from '../../../Content';\r\nimport { CART_MODIFY_MODAL_TYPES, CART_MODIFY_MODAL_VARIATIONS } from '../../utilities/constants';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { CartCardImageContainer, CartCardTitle, CartCardsContainer, SummaryPackagesCardContainer } from '../styles';\r\nimport { editCopyByReplaceMultipleStrings, editCopyByReplaceString } from './../../../../../utilities/copyFunctions';\r\n\r\nconst propTypes = {\r\n /** Title of the suite */\r\n suiteTitle: PropTypes.string.isRequired,\r\n\r\n /** Total for the suite */\r\n suiteTotal: PropTypes.number.isRequired,\r\n\r\n /** Promo code used in the reservation */\r\n promoCode: PropTypes.string,\r\n\r\n /** Number of guests as `1 Adult, 0 Kid` or `2 Adults, 2 Kids` */\r\n guestCountText: PropTypes.string.isRequired,\r\n\r\n /** Size for the promoCode icon */\r\n iconSize: PropTypes.number,\r\n\r\n promotionalSavings: PropTypes.string\r\n};\r\n\r\nexport const Details = ({\r\n suiteTitle,\r\n suiteTotal,\r\n guestCountText,\r\n promoCode,\r\n promotionalSavings,\r\n selectedSuite,\r\n checkIn,\r\n checkOut,\r\n isCartVariation = false,\r\n openModifyCartItemModal,\r\n clearPlanPackages,\r\n clearSelectedSuite,\r\n toggleOpen,\r\n setCartReturnedPageLinkClicked,\r\n resortLocationUrlParam,\r\n onPlanPage,\r\n clearSelectedPackages,\r\n kidsAges,\r\n resortLocation,\r\n arrival,\r\n departure,\r\n adultsCount,\r\n kidsCount,\r\n shouldDisplayRoomSavings,\r\n shouldDisplayPromoValue\r\n}) => {\r\n const history = useHistory();\r\n const showNegativeSign = promotionalSavings > 0 ? '-' : '';\r\n\r\n const copyObjectDates = {\r\n '': checkIn,\r\n '': checkOut\r\n };\r\n\r\n // Go to plan page, used on edit and remove suite based on last search\r\n const goToLastPlanSearch = () => {\r\n const lastSearch = JSON.parse(localStorage.getItem('GWL_LAST_SEARCH'));\r\n setTimeout(() => {\r\n window.location.href =\r\n resortLocationUrlParam +\r\n `plan?\r\n numberOfAdults=${lastSearch.numberOfAdults}&\r\n arrival=${lastSearch.arrival}&\r\n departure=${lastSearch.departure}&\r\n offerCode=${lastSearch.offerCode}&\r\n kidsAges=${lastSearch.kidsAges}&\r\n cal=${lastSearch.cal}`.replace(/\\s/g, '');\r\n }, 500);\r\n };\r\n\r\n // Handle remove suite modal\r\n const handleRemoveSuiteModal = () => {\r\n const goToPlanPageOnRemove = () => {\r\n const eventObject = buildAddToCartEnhancedEcommerceObject(\r\n EVENT_CATEGORIES.GTM.removeFromCart,\r\n kidsAges,\r\n selectedSuite,\r\n resortLocation,\r\n departure,\r\n arrival,\r\n adultsCount,\r\n kidsCount,\r\n 1,\r\n 'standard purchase - cart'\r\n );\r\n pushEvent(eventObject);\r\n\r\n toggleOpen();\r\n clearPlanPackages();\r\n clearSelectedSuite();\r\n if (!onPlanPage) {\r\n goToLastPlanSearch();\r\n }\r\n };\r\n openModifyCartItemModal(\r\n selectedSuite,\r\n CART_MODIFY_MODAL_TYPES.REMOVE,\r\n CART_MODIFY_MODAL_VARIATIONS.SUITE,\r\n goToPlanPageOnRemove\r\n );\r\n };\r\n\r\n // Handle edit suite modal and dont remove the suite\r\n const handleEditSuiteModal = () => {\r\n const goToPlanPageOnEdit = () => {\r\n setCartReturnedPageLinkClicked('plan');\r\n toggleOpen();\r\n clearSelectedPackages();\r\n goToLastPlanSearch();\r\n };\r\n openModifyCartItemModal(\r\n selectedSuite,\r\n CART_MODIFY_MODAL_TYPES.EDIT,\r\n CART_MODIFY_MODAL_VARIATIONS.SUITE,\r\n goToPlanPageOnEdit\r\n );\r\n };\r\n\r\n const goToPlanPageByTitle = () => {\r\n setCartReturnedPageLinkClicked('plan');\r\n goToLastPlanSearch();\r\n toggleOpen();\r\n };\r\n\r\n return (\r\n <>\r\n {!isCartVariation ? : null}\r\n\r\n \r\n \r\n {/* Suite Card Image */}\r\n {isCartVariation ? (\r\n \r\n
\r\n \r\n ) : null}\r\n\r\n \r\n \r\n {/* Suite Card title */}\r\n \r\n {!isCartVariation ? (\r\n {suiteTitle}\r\n ) : (\r\n \r\n {selectedSuite.headline}\r\n \r\n )}\r\n {!isCartVariation ? (\r\n {`$${suiteTotal.toFixed(\r\n 2\r\n )}`}\r\n ) : null}\r\n \r\n {/* Guest Count */}\r\n \r\n {!isCartVariation ? (\r\n {guestCountText}\r\n ) : (\r\n \r\n {guestCountText}\r\n \r\n )}\r\n \r\n {/* Dates */}\r\n {isCartVariation ? (\r\n \r\n {editCopyByReplaceMultipleStrings(COPY.DATES, copyObjectDates)}\r\n \r\n ) : null}\r\n {/* Promo Code */}\r\n {!isCartVariation && promoCode ? (\r\n \r\n \r\n \r\n {editCopyByReplaceString(COPY.PROMO_CODE_COPY, promoCode, '')}\r\n \r\n {shouldDisplayPromoValue ? (\r\n \r\n {`${showNegativeSign}$${promotionalSavings.toFixed(2)}`}\r\n \r\n ) : null}\r\n \r\n ) : null}\r\n {shouldDisplayRoomSavings && (\r\n \r\n \r\n \r\n {COPY.ROOM_SAVINGS_APPLIED}\r\n \r\n \r\n \r\n \r\n {`${showNegativeSign}$${promotionalSavings.toFixed(2)}`}\r\n \r\n \r\n \r\n )}\r\n {isCartVariation && promoCode ? (\r\n \r\n \r\n \r\n {editCopyByReplaceString(COPY.PROMOTION_CODE, promoCode, '')}\r\n \r\n \r\n ) : null}\r\n {/* Change Suite Selection */}\r\n {!isCartVariation ? (\r\n \r\n history.push(routes.plan.self)}>\r\n {COPY.CHANGE_SUITE_SELECTION}\r\n \r\n \r\n ) : null}\r\n \r\n {isCartVariation ? (\r\n \r\n \r\n \r\n \r\n {COPY.REMOVE}\r\n \r\n \r\n \r\n \r\n {COPY.EDIT}\r\n \r\n \r\n \r\n \r\n \r\n ${suiteTotal.toFixed(2)}\r\n \r\n \r\n \r\n ) : null}\r\n \r\n \r\n \r\n >\r\n );\r\n};\r\n\r\nDetails.propTypes = propTypes;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\n\r\nimport { isValidPrice } from '../../../../../../utilities/cmpPackagesUtils';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { handleDueAmounts, handleTotalWithTaxes } from '../../../../../utilities/utils';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../../utilities/copy';\r\n\r\nconst propTypes = {\r\n /** Due Amount for today */\r\n dueTodayAmount: PropTypes.number.isRequired,\r\n\r\n /** Due Amount at check in */\r\n dueAtCheckinAmount: PropTypes.number.isRequired\r\n};\r\n\r\nexport const DueAmount = ({\r\n dueTodayAmount,\r\n dueAtCheckinAmount,\r\n roomAdjustmentTax,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n numberOfNights,\r\n isUserAuthenticated,\r\n userOffers,\r\n activeOffers,\r\n setExcedent,\r\n isParkingFeeABCDTestActive,\r\n parkingFeeTotal,\r\n taxesAndFees,\r\n currentSelectedPackages,\r\n summaryTotal,\r\n optimizelyHierarchyFlip\r\n}) => {\r\n const shouldDisplay = isValidPrice(dueTodayAmount) && isValidPrice(dueAtCheckinAmount);\r\n\r\n if (!shouldDisplay) return null;\r\n\r\n const handleSummaryTotal = isUserAuthenticated\r\n ? handleTotalWithTaxes(\r\n userOffers,\r\n activeOffers,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n taxesAndFees,\r\n roomAdjustmentTax,\r\n currentSelectedPackages,\r\n setExcedent\r\n )\r\n : summaryTotal.toFixed(2);\r\n\r\n const handleDueToday = isUserAuthenticated\r\n ? handleDueAmounts(\r\n dueTodayAmount,\r\n dueAtCheckinAmount,\r\n roomAdjustmentTax,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n numberOfNights,\r\n userOffers,\r\n activeOffers,\r\n handleSummaryTotal\r\n ).today\r\n : dueTodayAmount.toFixed(2);\r\n\r\n const handleDuetAtCheckIn = isUserAuthenticated\r\n ? handleDueAmounts(\r\n dueTodayAmount,\r\n dueAtCheckinAmount,\r\n roomAdjustmentTax,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n numberOfNights,\r\n userOffers,\r\n activeOffers,\r\n handleSummaryTotal\r\n ).atCheckIn\r\n : dueAtCheckinAmount.toFixed(2);\r\n\r\n /* ABCD TEST FOR PARKING FEE */\r\n const ABCDTestForParkingFeeDueAtCheckIn = (+handleDuetAtCheckIn + parkingFeeTotal).toFixed(2);\r\n /* ABCD TEST FOR PARKING FEE */\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n {optimizelyHierarchyFlip ? COPY.DUE_TODAY_CAP : COPY.DUE_TODAY}\r\n \r\n \r\n {`$${handleDueToday}`}\r\n \r\n \r\n \r\n \r\n {COPY.DUE_CHECKIN}\r\n \r\n \r\n {`$${isParkingFeeABCDTestActive ? ABCDTestForParkingFeeDueAtCheckIn : handleDuetAtCheckIn}`}\r\n \r\n \r\n >\r\n );\r\n};\r\n\r\nDueAmount.propTypes = propTypes;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\n\r\nimport { CheckInOutDate } from '../../../../../CheckInOutDates';\r\nimport { Flex } from '../../../../../ui-kit';\r\nimport ArrowRightIcon from '../../../../../ui-kit/icons/ArrowRight';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../../utilities/copy';\r\n\r\nconst propTypes = {\r\n /** Checkin Date in the MM/DD format */\r\n checkIn: PropTypes.string.isRequired,\r\n\r\n /** Checkout Date in the MM/DD format */\r\n checkOut: PropTypes.string.isRequired,\r\n\r\n /** Number of nights for the reservation */\r\n numberOfNights: PropTypes.number.isRequired\r\n};\r\n\r\nexport const Header = ({ checkIn, checkOut, numberOfNights }) => {\r\n const numberOfNightsLabel = `${numberOfNights} ${numberOfNights && numberOfNights > 1 ? 'Nights' : 'Night'}`;\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n {COPY.CHECK_IN}\r\n \r\n \r\n {checkIn}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {COPY.CHECK_OUT}\r\n \r\n \r\n {checkOut}\r\n \r\n \r\n \r\n \r\n {numberOfNightsLabel}\r\n \r\n >\r\n );\r\n};\r\n\r\nHeader.propTypes = propTypes;\r\n","import { Fragment } from 'react';\r\nimport { OFFERS_IMAGES } from '../../../../../../components/LoyaltySummary/assets/images';\r\nimport { GwDatesWrapper } from '../../../../../_internal_date_/gwDatesWrapper';\r\nimport { Box, Flex, Text } from '../../../../../ui-kit';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { CustomSummaryItemOffer, CustomSummaryItemTitle, OfferImageContainer, OffersContainer } from '../styles';\r\n\r\nconst Offers = ({ userOffers, activeOffers, removeOffer, excedent, isCartVariation }) => {\r\n if (!activeOffers || activeOffers?.length === 0) {\r\n return null;\r\n }\r\n\r\n const offerSkeleton = (offerCode, index) => {\r\n const offerInfo = userOffers.find(offer => offer.id === offerCode);\r\n if (!offerInfo) return;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n {offerInfo.title}\r\n \r\n \r\n \r\n \r\n removeOffer(offerInfo)}>\r\n {COPY.REMOVE}\r\n \r\n \r\n {`-$${offerInfo.dollarValue.toFixed(2)}`}\r\n \r\n \r\n \r\n \r\n \r\n {COPY.EXPIRATION_DATE} {GwDatesWrapper.format(offerInfo.bookByDate, 'MMM DD, YYYY')}\r\n \r\n \r\n \r\n \r\n );\r\n };\r\n\r\n return (\r\n \r\n {!isCartVariation ? : null}\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n {COPY.BONUS_DEALS_APPLIED}\r\n \r\n \r\n\r\n {excedent && (\r\n \r\n {COPY.EXCEED_AMOUNT}\r\n \r\n )}\r\n \r\n \r\n \r\n \r\n {activeOffers.map((activeOffer, index) => (\r\n {offerSkeleton(activeOffer, index)}\r\n ))}\r\n \r\n \r\n );\r\n};\r\n\r\nexport default Offers;\r\n","import { PACKAGE_CHARGE_TYPE } from '../../../../../utilities/constants';\r\nimport { DINING_CREDIT, DINING_CREDIT_COINS } from '../../../../DiningCredit/assets/images';\r\n\r\n// Get the correct image to display from the packages\r\nexport function getPkgImage(pkg) {\r\n // check if the package is dining credit and return image\r\n if (\r\n pkg.packageName &&\r\n pkg.packageType?.includes('dining') &&\r\n pkg.packageName.toLowerCase().includes('dining credit')\r\n ) {\r\n if (pkg.allowance && DINING_CREDIT_COINS.includes(pkg.allowance)) {\r\n return DINING_CREDIT[pkg.allowance];\r\n }\r\n }\r\n\r\n // check if the package has a packageIcon\r\n if (pkg.packageIcon) return pkg.packageIcon;\r\n // check if image is a string\r\n if (typeof pkg.image === 'string') return pkg.image;\r\n // check if image is an object and return the url\r\n if (pkg.image && pkg.image.url) return pkg.image.url;\r\n}\r\n\r\n// check if the package is a json\r\nexport function getPkgImageValidation(pkg) {\r\n if (typeof pkg.image === 'string' && pkg.image.includes('.json')) return true;\r\n\r\n return false;\r\n}\r\n\r\n// validate if is dining credit\r\nexport function isDiningCredit(pkg) {\r\n return (\r\n pkg.packageName && pkg.packageType?.includes('dining') && pkg.packageName.toLowerCase().includes('dining credit')\r\n );\r\n}\r\n\r\n// show counter if package has a queryByTestId, is not bundle or dining and is per package charge\r\nexport function showCounter(packageItem) {\r\n return (\r\n packageItem.quantity &&\r\n packageItem.chargeType === PACKAGE_CHARGE_TYPE.byPackage &&\r\n !packageItem.packageType?.includes('bundle') &&\r\n !packageItem.packageType?.includes('dining')\r\n );\r\n}\r\n","import PropTypes from 'prop-types';\r\nimport React, { useEffect, useState } from 'react';\r\nimport { Counter, Flex } from '../../../../../ui-kit';\r\n\r\nconst propTypes = {\r\n handleUpdatePackageQuantity: PropTypes.func,\r\n handleDeletePackage: PropTypes.func,\r\n packageItem: PropTypes.object\r\n};\r\n\r\nconst defaultProps = {\r\n handleUpdatePackageQuantity: () => {},\r\n handleDeletePackage: () => {},\r\n packageItem: null\r\n};\r\n\r\nconst CartCounterContainer = ({ handleUpdatePackageQuantity, handleDeletePackage, packageItem }) => {\r\n const [value, setValue] = useState(packageItem?.quantity ?? 0);\r\n\r\n const handleUpdateStates = value => {\r\n if (value === 0) return handleDeletePackage(packageItem);\r\n handleUpdatePackageQuantity(value, packageItem);\r\n };\r\n\r\n useEffect(() => {\r\n setValue(packageItem?.quantity ?? 0);\r\n }, [packageItem]);\r\n\r\n return (\r\n \r\n handleUpdateStates(e)}\r\n value={value}\r\n variation=\"small\"\r\n min={0}\r\n width={40}\r\n max={+packageItem?.maxPackageLimit}\r\n />\r\n \r\n );\r\n};\r\n\r\nCartCounterContainer.propTypes = propTypes;\r\nCartCounterContainer.defaultProps = defaultProps;\r\n\r\nexport default CartCounterContainer;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport ReactHtmlParser from 'react-html-parser';\r\nimport routes from '../../../../../../routes';\r\nimport { getTheFirstElementOfArray } from '../../../../../../utilities/arraysUtils';\r\nimport { PACKAGE_CHARGE_TYPE, ROOM_RATE_TYPE } from '../../../../../../utilities/constants';\r\nimport { getNumberOfBillableGuests } from '../../../../../../utilities/guestsUtils';\r\nimport { getCurrencyCodeText } from '../../../../../../utilities/planUtils';\r\nimport SelectPackageQuantity from '../../../../../Packages/SelectPackageQuantity';\r\nimport { Animation, Box, Flex, Text } from '../../../../../ui-kit';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport {\r\n editCopyByReplaceMultipleStrings,\r\n editCopyByReplaceString,\r\n pluralize\r\n} from '../../../../../utilities/copyFunctions';\r\nimport { SummaryContent } from '../../../Content';\r\nimport { CART_MODIFY_MODAL_TYPES, CART_MODIFY_MODAL_VARIATIONS } from '../../utilities/constants';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { getPkgImage, getPkgImageValidation, isDiningCredit } from '../../utilities/functions';\r\nimport {\r\n AddWaterPassesSummary,\r\n CartCardImageContainer,\r\n CartCardTitle,\r\n CartCardsContainer,\r\n CartPackageListItemContainer,\r\n DisableAddButtonText,\r\n SummaryPackagesCardContainer\r\n} from '../styles';\r\nimport CartCounterContainer from './CartCounterContainer';\r\nconst propTypes = {\r\n /** String date object with the checkin date */\r\n checkinDateSelection: PropTypes.string.isRequired,\r\n\r\n /** String date object with the checkout date */\r\n checkoutDateSelection: PropTypes.string.isRequired,\r\n\r\n /** Currenty selected packages */\r\n currentSelectedPackages: PropTypes.arrayOf(\r\n PropTypes.shape({\r\n packageCode: PropTypes.string,\r\n packageName: PropTypes.string,\r\n currencyCode: PropTypes.string,\r\n quantity: PropTypes.number,\r\n amount: PropTypes.number,\r\n isAdjustment: PropTypes.bool,\r\n showQuantitySelect: PropTypes.bool\r\n })\r\n ),\r\n\r\n /** Number of guests for the reservation */\r\n numberOfGuests: PropTypes.number.isRequired,\r\n\r\n /** Flag to indicate the property is in Niagara */\r\n isNiagaraProperty: PropTypes.bool,\r\n\r\n /** Function to update the package quantity */\r\n upsertPackage: PropTypes.func,\r\n\r\n /** Funtion to delete a package */\r\n handleDeletePackage: PropTypes.func,\r\n\r\n /** Flag to indicate if the reservation has selected packages */\r\n hasSelectedPackages: PropTypes.bool\r\n};\r\n\r\nconst getPackagePriceDisplay = packageItem => {\r\n if (packageItem.maxPackageLimit === '1') return `${packageItem.amount.toFixed(2)}`;\r\n return `${(parseInt(packageItem.quantity) * packageItem.amount).toFixed(2)}`;\r\n};\r\n\r\nconst PackageList = ({\r\n currentSelectedPackages,\r\n handleDeletePackage,\r\n isNiagaraProperty,\r\n checkinDateSelection,\r\n checkoutDateSelection,\r\n numberOfGuests,\r\n handleUpdatePackageQuantity,\r\n isCartVariation,\r\n handleUpdatePackageQuantityCounter,\r\n openModifyCartItemModal,\r\n setCartReturnedPageLinkClicked,\r\n resortLocationUrlParam,\r\n toggleOpen,\r\n lcoCode\r\n}) => {\r\n if (!currentSelectedPackages || !currentSelectedPackages.length) return null;\r\n\r\n const handleRemovePackageModal = packageItem => {\r\n const removeItemConfirmationFunction = () => handleDeletePackage(packageItem);\r\n openModifyCartItemModal(\r\n packageItem,\r\n CART_MODIFY_MODAL_TYPES.REMOVE,\r\n CART_MODIFY_MODAL_VARIATIONS.PACKAGE,\r\n removeItemConfirmationFunction\r\n );\r\n };\r\n\r\n const moveToActivitiesAndCloseCart = () => {\r\n setCartReturnedPageLinkClicked('activities');\r\n toggleOpen();\r\n setTimeout(() => {\r\n window.location.href = removeLastSlash(resortLocationUrlParam) + routes.plan.activities;\r\n }, 500);\r\n };\r\n\r\n const moveToDiningAndCloseCart = () => {\r\n setCartReturnedPageLinkClicked('dining');\r\n toggleOpen();\r\n setTimeout(() => {\r\n window.location.href = removeLastSlash(resortLocationUrlParam) + routes.plan.dining;\r\n }, 500);\r\n };\r\n\r\n return (\r\n <>\r\n \r\n {/* Packages Card */}\r\n {currentSelectedPackages.map((item, index) => {\r\n const priceToDisplay = getPackagePriceDisplay(item);\r\n return (\r\n !item.isAdjustment && (\r\n \r\n {/* Package Image */}\r\n {isCartVariation ? (\r\n \r\n {getPkgImageValidation(item) ? (\r\n \r\n ) : (\r\n
\r\n )}\r\n \r\n ) : null}\r\n {/* Package Details */}\r\n \r\n \r\n \r\n \r\n {isCartVariation ? (\r\n \r\n {item.headline || item.title}\r\n \r\n ) : (\r\n \r\n {item.packageName || item.headline}\r\n \r\n )}\r\n {(!isNiagaraProperty &&\r\n item.quantity &&\r\n !item.packageType?.includes('dining') &&\r\n !item.packageType?.includes('bundle') &&\r\n item.packageCode !== lcoCode) ||\r\n (isNiagaraProperty &&\r\n item.quantity &&\r\n item.chargeType === PACKAGE_CHARGE_TYPE.byPackage &&\r\n !item.packageType?.includes('bundle') &&\r\n item.packageCode !== lcoCode) ? (\r\n isCartVariation ? (\r\n \r\n ) : (\r\n \r\n \r\n \r\n )\r\n ) : null}\r\n \r\n \r\n {!isCartVariation ? (\r\n handleDeletePackage(item)}>\r\n {COPY.REMOVE}\r\n \r\n ) : null}\r\n \r\n {isCartVariation ? (\r\n \r\n \r\n \r\n handleRemovePackageModal(item)}>\r\n {COPY.REMOVE}\r\n \r\n \r\n \r\n \r\n {COPY.EDIT}\r\n \r\n \r\n \r\n\r\n \r\n \r\n ${priceToDisplay}\r\n \r\n \r\n \r\n ) : (\r\n \r\n ${priceToDisplay} {getCurrencyCodeText(item.currencyCode)}\r\n \r\n )}\r\n \r\n \r\n \r\n \r\n \r\n \r\n )\r\n );\r\n })}\r\n \r\n >\r\n );\r\n};\r\n\r\nexport const PackagesList = ({\r\n checkinDateSelection,\r\n checkoutDateSelection,\r\n currentSelectedPackages,\r\n numberOfGuests,\r\n isNiagaraProperty,\r\n upsertPackage,\r\n deletePackage,\r\n hasSelectedPackages,\r\n isCartVariation = false,\r\n openModifyCartItemModal,\r\n resortLocationUrlParam,\r\n setCartReturnedPageLinkClicked,\r\n cartReturnedPageLinkClicked,\r\n toggleOpen,\r\n selectedSuite,\r\n updateSuite,\r\n adultsCount,\r\n kidsAges\r\n}) => {\r\n const handleUpdatePackageQuantitySelect = (e, packageItem) => {\r\n upsertPackage({ ...packageItem, quantity: e.target.value });\r\n };\r\n const handleUpdatePackageQuantityCounter = (value, packageItem) => {\r\n upsertPackage({ ...packageItem, quantity: value });\r\n };\r\n\r\n const price =\r\n selectedSuite?.rateOptions?.length > 1\r\n ? selectedSuite?.rateOptions?.find(rate => rate.rateType === ROOM_RATE_TYPE.roomWithWaterParkPass)\r\n ?.averageNightlyBaseRate -\r\n selectedSuite?.rateOptions?.find(rate => rate.rateType === ROOM_RATE_TYPE.roomOnlyWithoutWaterParkPass)\r\n ?.averageNightlyBaseRate\r\n : 0;\r\n const numberOfBillableGuests = getNumberOfBillableGuests(adultsCount, kidsAges);\r\n const copyObject = {\r\n '': numberOfBillableGuests,\r\n '': Math.round(price),\r\n '': pluralize('pass', numberOfBillableGuests)\r\n };\r\n\r\n const lcoCode = selectedSuite?.lcoPackageCode ?? '';\r\n\r\n return (\r\n <>\r\n {!isCartVariation ? (\r\n <>\r\n \r\n \r\n {selectedSuite?.rateType === ROOM_RATE_TYPE.roomOnlyWithoutWaterParkPass ? (\r\n \r\n \r\n {ReactHtmlParser(editCopyByReplaceMultipleStrings(COPY.ROOM_WITH_NO_WATER_PASS, copyObject))}\r\n \r\n \r\n \r\n \r\n {editCopyByReplaceString(COPY.ADD_PASSES, pluralize('pass', numberOfGuests), '')}\r\n \r\n \r\n \r\n \r\n ) : (\r\n <>\r\n {COPY.WATERPARK_PASS}\r\n {COPY.INCLUDED}\r\n >\r\n )}\r\n \r\n >\r\n ) : null}\r\n\r\n {hasSelectedPackages && (\r\n \r\n )}\r\n >\r\n );\r\n};\r\n\r\nPackagesList.propTypes = propTypes;\r\n\r\nPackagesList.defaultProps = {\r\n isNiagaraProperty: false,\r\n hasSelectedPackages: false\r\n};\r\n\r\n// Function to remove last slash from string\r\nfunction removeLastSlash(str) {\r\n return str.replace(/\\/$/, '');\r\n}\r\n","import React from 'react';\r\n\r\nimport theme from '../../../../../../components/ui-kit/themes/theme';\r\nimport { store } from '../../../../../../store/configureStore';\r\nimport { Text } from '../../../../../ui-kit';\r\nimport { SummaryContent } from '../../../Content';\r\n\r\nexport const ParkingFee = () => {\r\n const { lodgeConfig } = store?.getState() || '';\r\n return (\r\n <>\r\n {lodgeConfig?.bookingSummaryParkingFee ? (\r\n \r\n \r\n {lodgeConfig.bookingSummaryParkingFee}\r\n \r\n \r\n ) : null}\r\n >\r\n );\r\n};\r\n","import React from 'react';\r\nimport { OFFERS_IMAGES } from '../../../../../LoyaltySummary/assets/images';\r\nimport { Flex, Text } from '../../../../../ui-kit';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { editCopyByReplaceWithComponent } from '../../../../../utilities/copyFunctions';\r\nimport { handlePointsBalance } from '../../../../../utilities/utils';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { OfferImageContainer, PointsContainer } from '../styles';\r\n\r\nconst Points = ({\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n userOffers,\r\n activeOffers,\r\n isCartVariation\r\n}) => {\r\n const pointsBalanceAmount = handlePointsBalance(\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n userOffers,\r\n activeOffers\r\n );\r\n\r\n const pointsBalanceValue = () => {\r\n return {`${pointsBalanceAmount.toFixed(0)}`};\r\n };\r\n return (\r\n \r\n {!isCartVariation ? : null}\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n {editCopyByReplaceWithComponent(COPY.POINTS_APPLIED, pointsBalanceValue(), '')}\r\n \r\n \r\n {`-$${pointsBalanceAmount.toFixed(\r\n 2\r\n )}`}\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default Points;\r\n","import styled, { css } from 'styled-components';\r\nimport { fontSize } from 'styled-system';\r\nimport Box from '../ui-kit/Box';\r\nimport theme, { mediaQueries } from '../ui-kit/themes/theme';\r\n\r\nexport const AffirmContainer = styled(Box)`\r\n ${theme.mediaScreens.phone`\r\n margin-right: auto;\r\n border-radius: 25px;\r\n margin-left: auto;\r\n display: inline-block;\r\n `}\r\n ${theme.mediaScreens.tablet`\r\n margin-right: ${props => (props.rightAlign ? '0' : 'auto')};\r\n `}\r\n`;\r\n\r\nexport const StyledFinancingOptionText = styled.p`\r\n margin-bottom: 0;\r\n display: flex;\r\n flex-wrap: wrap;\r\n justify-content: center;\r\n align-items: baseline;\r\n color: ${props => props.color || theme.colors.deepLakeBlue[100]};\r\n ${fontSize}\r\n font-weight: ${props => props.fontWeight || theme.fontWeights.regular};\r\n text-decoration: ${props => (props.textDecoration && props.textDecoration.sm) || props.textDecoration || 'none'};\r\n cursor: pointer;\r\n text-decoration-color: ${props => props.color || theme.colors.deepLakeBlue[100]};\r\n border-bottom: 1px solid transparent;\r\n \r\n .affirm-ala-price {\r\n padding-left: 4px;\r\n }\r\n \r\n .affirm-promo-underline {\r\n margin-right: 5px;\r\n text-decoration: none;\r\n cursor: pointer;\r\n }\r\n\r\n .__affirm-logo {\r\n margin-left: 7px;\r\n }\r\n\r\n .affirm-modal-trigger {\r\n display: none;\r\n }\r\n\r\n &:hover {\r\n ${theme.mediaScreens.tablet`\r\n border-bottom: 1px solid ${props => props.color || theme.colors.deepLakeBlue[100]};\r\n `}\r\n }\r\n ${({ lineHeight }) => {\r\n return css`\r\n line-height: ${lineHeight};\r\n `;\r\n }};\r\n ${mediaQueries.lg} {\r\n text-decoration: ${props => (props.textDecoration && props.textDecoration.lg) || props.textDecoration || 'none'};\r\n }\r\n`;\r\n","// TODO - revisit this component to fix how hooks are working\r\n/* eslint-disable react-hooks/exhaustive-deps */\r\nimport throttle from 'lodash-es/throttle';\r\nimport React, { createRef, useEffect } from 'react';\r\nimport { AffirmContainer, StyledFinancingOptionText } from './styles';\r\n\r\nimport { useHistory } from 'react-router';\r\nimport { isLocationAvailableWithAffirm } from '../../api/Utils/affirmUtils';\r\n\r\nconst refreshAffirm = throttle(() => {\r\n try {\r\n window.affirm.ui.refresh();\r\n } catch (e) {}\r\n}, 500);\r\n\r\nconst FinancingOptionText = ({ productType, amount, shouldRefresh, rightAlign, resortLocation, ...restProps }) => {\r\n const rateContainer = createRef();\r\n const shouldEnableAffirm = isLocationAvailableWithAffirm(resortLocation);\r\n const history = useHistory();\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (history?.action === 'POP') window.affirm?.ui?.modal?.close();\r\n };\r\n }, [history]);\r\n\r\n useEffect(() => {\r\n refreshAffirm();\r\n }, [shouldRefresh]);\r\n\r\n useEffect(() => {\r\n if (shouldEnableAffirm) {\r\n const setListeners = event => {\r\n const { target } = event;\r\n target.parentElement.querySelector('.affirm-modal-trigger').click();\r\n };\r\n // This sucks but is the only way to emulate production behavior\r\n rateContainer.current.addEventListener('click', setListeners);\r\n\r\n return () => {\r\n if (rateContainer && rateContainer.current) {\r\n rateContainer.current.removeEventListener('click', setListeners);\r\n }\r\n };\r\n }\r\n }, []);\r\n\r\n if (!shouldEnableAffirm) return null;\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n >\r\n );\r\n};\r\n\r\nexport default FinancingOptionText;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\n\r\nimport FinancingOptionText from '../../../../../FinancingOptionText';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\n\r\nconst propTypes = {\r\n /** Summary total for the reservation */\r\n summaryTotal: PropTypes.number.isRequired,\r\n\r\n /** Flag to indicate if affirm should refresh */\r\n refreshAffirm: PropTypes.bool\r\n};\r\n\r\nexport const AffirmLink = ({ summaryTotal, refreshAffirm, optimizelyHierarchyFlip, resortLocation }) => {\r\n const isDesktop = useMediaQuery({\r\n query: `(min-width: ${theme.breakpoints.lg})`\r\n });\r\n return (\r\n \r\n );\r\n};\r\n\r\nAffirmLink.propTypes = propTypes;\r\n\r\nAffirmLink.defaultProps = {\r\n refreshAffirm: false\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React, { useEffect, useState } from 'react';\r\nimport { isLocationAvailableWithAffirm } from '../../../../../../api/Utils/affirmUtils';\r\nimport { isValidPrice } from '../../../../../../utilities/cmpPackagesUtils';\r\nimport { SupAmount } from '../../../../../ui-kit';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { handleTotal } from '../../../../../utilities/utils';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { AffirmLink } from './AffirmLink';\r\n\r\nconst propTypes = {\r\n /** Flag to indicate if the user has packages selected */\r\n hasSelectedPackages: PropTypes.bool,\r\n\r\n /** Subtotal for the current reservation */\r\n summaryTotal: PropTypes.number.isRequired,\r\n\r\n /** loyalty points balance */\r\n pointsBalance: PropTypes.number,\r\n\r\n /** loyalty boolean to show or not the value */\r\n loyaltyOptIn: PropTypes.bool\r\n};\r\n\r\nexport const Subtotal = ({\r\n isSuperscriptStaySummarySuite,\r\n hasSelectedPackages,\r\n summaryTotal,\r\n pointsBalance,\r\n loyaltyOptIn,\r\n showLoyalty,\r\n userOffers,\r\n activeOffers,\r\n suiteTotal,\r\n isUserAuthenticated,\r\n currentSelectedPackages,\r\n setExcedent,\r\n resortLocation,\r\n optimizelyHierarchyFlip\r\n}) => {\r\n const [refreshAffirm, setRefreshAffirm] = useState(new Date().getTime());\r\n\r\n const handleSummarySubTotal = isUserAuthenticated\r\n ? handleTotal(\r\n userOffers,\r\n activeOffers,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n currentSelectedPackages,\r\n setExcedent\r\n ).toFixed(2)\r\n : summaryTotal?.toFixed(2);\r\n\r\n useEffect(() => {\r\n setRefreshAffirm(new Date().getTime());\r\n }, [hasSelectedPackages, summaryTotal, handleSummarySubTotal]);\r\n\r\n return isValidPrice(summaryTotal) ? (\r\n <>\r\n \r\n\r\n \r\n {COPY.SUBTOTAL}\r\n \r\n \r\n \r\n \r\n \r\n \r\n ({COPY.TAXES_NOT_INCLUDED})\r\n \r\n \r\n {isLocationAvailableWithAffirm(resortLocation) ? (\r\n \r\n \r\n \r\n ) : null}\r\n >\r\n ) : null;\r\n};\r\nSubtotal.propTypes = propTypes;\r\nSubtotal.defaultProps = {\r\n hasSelectedPackages: false,\r\n pointsBalance: 0,\r\n loyaltyOptIn: false\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { TotalSavingsContainer } from '../styles';\r\n\r\nconst propTypes = {\r\n handleSavings: PropTypes.func\r\n};\r\n\r\nexport const TotalSavings = ({\r\n handleSavings,\r\n optimizelyHierarchyFlip = false,\r\n isCartVariation,\r\n shouldDisplayTotalSavings\r\n}) => {\r\n const value = handleSavings();\r\n if (!shouldDisplayTotalSavings) return null;\r\n return (\r\n <>\r\n {!isCartVariation ? : null}\r\n \r\n \r\n {COPY.TOTAL_SAVINGS}\r\n \r\n {`${!isCartVariation && value > 0 ? '-' : ''}$${value.toFixed(2)}`}\r\n \r\n \r\n \r\n >\r\n );\r\n};\r\n\r\nTotalSavings.propTypes = propTypes;\r\n","import PropTypes from 'prop-types';\r\nimport React, { useEffect, useState } from 'react';\r\n\r\nimport { isLocationAvailableWithAffirm } from '../../../../../../api/Utils/affirmUtils';\r\nimport { isValidPrice } from '../../../../../../utilities/cmpPackagesUtils';\r\nimport { SupAmount } from '../../../../../ui-kit';\r\nimport theme, { fontSizes } from '../../../../../ui-kit/themes/theme';\r\nimport { handleTotalWithTaxes } from '../../../../../utilities/utils';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { AffirmLink } from './AffirmLink';\r\n\r\nconst propTypes = {\r\n /** Flag to indicate if exist packages for the reservation */\r\n hasSelectedPackages: PropTypes.bool,\r\n\r\n /** Total for the reservation */\r\n summaryTotal: PropTypes.number.isRequired,\r\n\r\n /** loyalty points balance */\r\n pointsBalance: PropTypes.number,\r\n\r\n /** loyalty boolean to show or not the value */\r\n loyaltyOptIn: PropTypes.bool\r\n};\r\n\r\nexport const Totals = ({\r\n isSuperscriptStaySummarySuite,\r\n hasSelectedPackages,\r\n summaryTotal,\r\n pointsBalance,\r\n loyaltyOptIn,\r\n showLoyalty,\r\n userOffers,\r\n activeOffers,\r\n suiteTotal,\r\n taxesAndFees,\r\n roomAdjustmentTax,\r\n isUserAuthenticated,\r\n currentSelectedPackages,\r\n setExcedent,\r\n parkingFeeTotal,\r\n isParkingFeeABCDTestActive,\r\n resortLocation,\r\n optimizelyHierarchyFlip,\r\n isDesktop\r\n}) => {\r\n const [refreshAffirm, setRefreshAffirm] = useState(new Date().getTime());\r\n\r\n const handleSummaryTotal = isUserAuthenticated\r\n ? handleTotalWithTaxes(\r\n userOffers,\r\n activeOffers,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n taxesAndFees,\r\n roomAdjustmentTax,\r\n currentSelectedPackages,\r\n setExcedent\r\n )\r\n : summaryTotal?.toFixed(2);\r\n\r\n useEffect(() => {\r\n setRefreshAffirm(new Date().getTime());\r\n }, [hasSelectedPackages, summaryTotal, handleSummaryTotal]);\r\n\r\n /* ABCD TEST FOR PARKING FEE */\r\n const ABCDTestForParkingFeeSummaryTotal = () => {\r\n const summaryTotalWithParkingFee = Number(handleSummaryTotal) + parkingFeeTotal;\r\n return summaryTotalWithParkingFee.toFixed(2);\r\n };\r\n /* ABCD TEST FOR PARKING FEE */\r\n\r\n return isValidPrice(summaryTotal) ? (\r\n <>\r\n \r\n \r\n {COPY.TOTAL}\r\n \r\n \r\n \r\n \r\n\r\n {isLocationAvailableWithAffirm(resortLocation) ? (\r\n \r\n \r\n \r\n ) : null}\r\n >\r\n ) : null;\r\n};\r\n\r\nTotals.propTypes = propTypes;\r\n\r\nTotals.defaultProps = {\r\n hasSelectedPackages: false,\r\n pointsBalance: 0,\r\n loyaltyOptIn: false\r\n};\r\n","import React, { useState } from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport {\r\n TESTS_DICTIONARY,\r\n getTestValueAB,\r\n optimizelyHideVoyagersBannerMobile\r\n} from '../../../../../../utilities/ABTesting';\r\n\r\nimport Loyalty from '../../../../../Loyalty/Loyalty';\r\nimport { LOYALTY_TYPES } from '../../../../../Loyalty/utilities/constants';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { handlePointsBalance } from '../../../../../utilities/utils';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { AdditionalCharges } from './AdditionalCharges';\r\nimport { Details } from './Details';\r\nimport { DueAmount } from './DueAmount';\r\nimport { Header as SuiteHeader } from './Header';\r\nimport Offers from './Offers';\r\nimport { PackagesList } from './PackageList';\r\nimport { ParkingFee } from './ParkingFee';\r\nimport Points from './Points';\r\nimport { Subtotal } from './Subtotal';\r\nimport { TotalSavings } from './TotalSavings';\r\nimport { Totals } from './Totals';\r\n\r\nconst SuitePlanContent = ({ expanded, onPaymentPage, clearSelectedSuite, isHighestRatesEnabled, ...restProps }) => {\r\n const {\r\n promotionalSavings,\r\n loyaltyOptIn,\r\n suiteTotal,\r\n numberOfNights,\r\n userOffers,\r\n activeOffers,\r\n removeActiveOffer,\r\n showLoyalty,\r\n isUserAuthenticated,\r\n getPointsMultiplier,\r\n offerCode,\r\n pointsBalance,\r\n isCartVariation,\r\n resortLocation,\r\n loyaltyEarnThresholdNights,\r\n setCartReturnedPageLinkClicked,\r\n clearPlanPackages,\r\n deletePackage,\r\n upsertPackage,\r\n promoCode\r\n } = restProps;\r\n\r\n const isDesktop = useMediaQuery({\r\n query: `(min-width: ${theme.breakpoints.lg})`\r\n });\r\n const iconSize = isDesktop ? '16px' : '24px';\r\n\r\n const [showBonusExcedent, setShowBonusExcedent] = useState(false);\r\n\r\n const renderHeader = expanded || onPaymentPage || isDesktop;\r\n const renderTaxes = expanded && onPaymentPage;\r\n const renderExpandedNonPaymentPage = expanded && !onPaymentPage;\r\n const renderPackages = expanded;\r\n const renderTotal = ((expanded || isDesktop) && onPaymentPage && isDesktop) || (!isDesktop && onPaymentPage);\r\n const abTestingHideEarnBanner = !isDesktop && optimizelyHideVoyagersBannerMobile;\r\n\r\n const isSuperscriptStaySummarySuite = getTestValueAB(TESTS_DICTIONARY.optimizelySuperscriptStaySummarySuite, false);\r\n const optimizelyHierarchyFlip = getTestValueAB(TESTS_DICTIONARY.optimizelyHierarchyFlip, false);\r\n const shouldDisplayRoomSavings = !isCartVariation && !promoCode && isHighestRatesEnabled;\r\n\r\n const handleSavings = () => {\r\n const roomSavings = ~~parseFloat(promotionalSavings.toFixed(2));\r\n const pointsSavings = handlePointsBalance(showLoyalty, loyaltyOptIn, pointsBalance, suiteTotal);\r\n let offersSavings = 0;\r\n if (userOffers && userOffers.length > 0) {\r\n offersSavings = userOffers.reduce((previousValue, currentValue) => {\r\n if (activeOffers.length > 0 && activeOffers.includes(currentValue.id)) {\r\n return previousValue + currentValue.dollarValue;\r\n } else {\r\n return previousValue;\r\n }\r\n }, 0);\r\n }\r\n return Number(roomSavings) + Number(pointsSavings) + offersSavings;\r\n };\r\n\r\n return (\r\n \r\n {showLoyalty && !abTestingHideEarnBanner && offerCode !== COPY.SEASONS_CODE && !isCartVariation ? (\r\n \r\n ) : null}\r\n\r\n {renderHeader && !isCartVariation ? : null}\r\n {expanded ? (\r\n \r\n ) : null}\r\n {renderPackages ? (\r\n \r\n ) : null}\r\n {showLoyalty && expanded && userOffers ? (\r\n \r\n ) : null}\r\n {showLoyalty && expanded && pointsBalance ? : null}\r\n\r\n {renderTaxes && !isCartVariation ? : null}\r\n {expanded && !isCartVariation ? (\r\n \r\n ) : null}\r\n {renderExpandedNonPaymentPage && !isCartVariation ? (\r\n \r\n ) : null}\r\n\r\n {renderTotal && !optimizelyHierarchyFlip && !isCartVariation ? (\r\n \r\n ) : null}\r\n {renderTotal && !isCartVariation ? (\r\n \r\n ) : null}\r\n {renderTotal && !renderExpandedNonPaymentPage && !isCartVariation ? : null}\r\n {renderTotal && optimizelyHierarchyFlip && !isCartVariation ? (\r\n \r\n ) : null}\r\n {expanded && isCartVariation && handleSavings() ? (\r\n \r\n ) : null}\r\n \r\n );\r\n};\r\n\r\nexport default SuitePlanContent;\r\n","import { ASSETS_LOCATIONS, getAssetsUrl } from '../../../../../../utilities/constants';\r\n\r\nexport const SUMMARY_IMAGES = {\r\n CART_LOGO: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'Cart.svg'),\r\n CART_EMPTY_LOGO: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'CartEmpty.svg'),\r\n CLOSE_MODAL_IMAGE: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'close-icon.svg'),\r\n COUNTER_CONFETTI: getAssetsUrl(ASSETS_LOCATIONS.ANIMATION, 'Shopping_Cart_Confetti_Animation.json')\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { Animation, Box, Text } from '../../../../../ui-kit';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { SUMMARY_IMAGES } from '../assets/images';\r\nimport {\r\n CartBubble,\r\n CartBubleTopArrow,\r\n CartLogoContainer,\r\n CartLogoCounter,\r\n CartLogoImg,\r\n CartLogoWithAnimation,\r\n CartMobileSubtotalTopArrow\r\n} from '../styles';\r\n\r\nconst propTypes = {\r\n packagesCount: PropTypes.number,\r\n toggleOpen: PropTypes.func\r\n};\r\n\r\nconst defaultProps = {\r\n packagesCount: 0,\r\n toggleOpen: () => {}\r\n};\r\n\r\nconst CartLogo = ({ packagesCount = 0, toggleOpen, overlayVisible, summaryTotal, isMobile, isTablet }) => {\r\n const [showAnimation, setShowAnimation] = useState(false);\r\n const [showArrow, setShowArrow] = useState(true);\r\n const currentPackageCount = useRef(packagesCount);\r\n const headerElement = document.querySelector('.header-container');\r\n const [arrowPosition, setArrowPosition] = useState(headerElement?.offsetHeight / 2 + 8);\r\n\r\n const path = window.location.pathname;\r\n const isActivitiesOrDining = path.includes('plan') && (path.includes('activities') || path.includes('dining'));\r\n\r\n const appYPosition = useCallback(() => {\r\n const headerSize = headerElement\r\n ? headerElement?.clientHeight - (headerElement?.clientHeight - 45)\r\n : isMobile\r\n ? 58\r\n : 68;\r\n setArrowPosition(headerElement?.offsetHeight / 2 + 8);\r\n const appScrollYPosition = window.scrollY;\r\n\r\n if (appScrollYPosition > headerSize) setShowArrow(false);\r\n if (appScrollYPosition <= headerSize) setShowArrow(true);\r\n }, [isMobile, headerElement]);\r\n\r\n useEffect(() => {\r\n window.addEventListener('scroll', e => appYPosition(e));\r\n return () => {\r\n window.removeEventListener('scroll', e => appYPosition(e));\r\n };\r\n }, [appYPosition]);\r\n\r\n useEffect(() => {\r\n if (packagesCount > currentPackageCount.current) {\r\n setShowAnimation(true);\r\n currentPackageCount.current = packagesCount;\r\n const closeAnimation = setTimeout(() => {\r\n setShowAnimation(false);\r\n }, 1500);\r\n\r\n return () => {\r\n clearTimeout(closeAnimation);\r\n };\r\n } else if (packagesCount !== currentPackageCount.current) {\r\n currentPackageCount.current = packagesCount;\r\n }\r\n }, [packagesCount]);\r\n\r\n return (\r\n \r\n \r\n {packagesCount > 0 ? (\r\n \r\n {showAnimation ? (\r\n \r\n \r\n \r\n ) : null}\r\n \r\n \r\n {packagesCount}\r\n \r\n \r\n {isActivitiesOrDining && showArrow && (isMobile || isTablet) ? (\r\n \r\n ) : null}\r\n \r\n ) : null}\r\n {!overlayVisible && isActivitiesOrDining && !isMobile && !isTablet ? (\r\n \r\n \r\n \r\n {COPY.SUBTOTAL}: ${Number(summaryTotal).toFixed()}\r\n \r\n \r\n ) : null}\r\n \r\n );\r\n};\r\n\r\nCartLogo.propTypes = propTypes;\r\nCartLogo.defaultProps = defaultProps;\r\n\r\nexport default CartLogo;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport routes from '../../../../../../routes';\r\nimport { TIMER_MODAL_CONTENT_IMAGES } from '../../../../../TimerModalContent/assets/images';\r\nimport { Box, Button, Flex, Text } from '../../../../../ui-kit';\r\nimport * as COPY from '../../utilities/copy';\r\nimport { SUMMARY_IMAGES } from '../assets/images';\r\nimport { EmptyCartImageContainer } from '../styles';\r\n\r\nconst propTypes = {\r\n resortLocationUrlParam: PropTypes.string\r\n};\r\n\r\nconst defaultProps = {\r\n resortLocationUrlParam: ''\r\n};\r\n\r\nconst EmptyCartContent = ({ resortLocationUrlParam, isCartExpired }) => {\r\n // Redirect to plan page\r\n const redirectToPlanPage = () => {\r\n window.location.href = resortLocationUrlParam ? `${resortLocationUrlParam}plan` : routes.plan.self;\r\n };\r\n return (\r\n \r\n \r\n
\r\n \r\n \r\n {isCartExpired ? COPY.EXPIRED_BOOKING_TITLE : COPY.BOOKING_CART_EMPTY}\r\n \r\n {isCartExpired ? (\r\n \r\n {COPY.EXPIRED_BOOKING_TEXT}\r\n \r\n ) : null}\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nEmptyCartContent.propTypes = propTypes;\r\nEmptyCartContent.defaultProps = defaultProps;\r\n\r\nexport default EmptyCartContent;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\n\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { isValidPrice } from '../../../../../utilities/cmpPackagesUtils';\r\nimport { Flex } from '../../../../ui-kit';\r\nimport theme from '../../../../ui-kit/themes/theme';\r\nimport {\r\n HeaderTextDesktop,\r\n HeaderTextMobile,\r\n HeaderTextSubtotal,\r\n HeaderTextTotalContainer,\r\n HeaderTextTotalMobile\r\n} from './styles';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nconst propTypes = {\r\n /** Flag to indicate if the component is on the payment page */\r\n onPaymentPage: PropTypes.bool,\r\n\r\n /** Total for the reservation */\r\n total: PropTypes.number\r\n};\r\n\r\nexport const Header = ({ onPaymentPage, total }) => {\r\n const isDesktop = useMediaQuery({\r\n query: `(min-width: ${theme.breakpoints.lg})`\r\n });\r\n\r\n if (isDesktop) {\r\n return {COPY.STAY_SUMMARY_DESKTOP};\r\n }\r\n\r\n return (\r\n \r\n {COPY.STAY_SUMMARY_MOBILE}\r\n {isValidPrice(total) && (\r\n \r\n {`$${total}`}\r\n {onPaymentPage ? '(Total)' : '(Subtotal)'}\r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\nHeader.propTypes = propTypes;\r\n\r\nHeader.defaultProps = {\r\n onPaymentPage: false,\r\n total: 0\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React, { useCallback, useEffect, useState } from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { useHistory } from 'react-router-dom';\r\nimport { getBrowserId } from '../../../../../utilities/browserUtils';\r\nimport { DATE_FORMATS, PACKAGE_CHARGE_TYPE, ROOM_RATE_TYPE } from '../../../../../utilities/constants';\r\nimport { getNumberOfBillableGuests } from '../../../../../utilities/guestsUtils';\r\nimport { getInteractionsUserId } from '../../../../../utilities/interactionsUtils';\r\nimport { GwDatesWrapper } from '../../../../_internal_date_/gwDatesWrapper';\r\nimport { MODAL_KEYS } from '../../../../GlobalModal/modalSource';\r\nimport Loyalty from '../../../../Loyalty/Loyalty';\r\nimport { LOYALTY_TYPES } from '../../../../Loyalty/utilities/constants';\r\nimport { getTimeRemaining } from '../../../../TimerModalContent/utilities/timerFunctions';\r\nimport { Box } from '../../../../ui-kit';\r\nimport theme from '../../../../ui-kit/themes/theme';\r\nimport {\r\n editCopyByReplaceMultipleStrings,\r\n editCopyByReplaceString,\r\n pluralize\r\n} from '../../../../utilities/copyFunctions';\r\nimport { handleTotal, handleTotalWithTaxes } from '../../../../utilities/utils';\r\nimport { SummaryAccordion } from '../../Accordion';\r\nimport * as COPY from '../utilities/copy';\r\nimport CartOverlay from './CartOverlay';\r\nimport { SuitePlanContent } from './Content';\r\nimport CartLogo from './Content/CartLogo';\r\nimport EmptyCartContent from './Content/EmptyCartContent';\r\nimport { Header } from './Header';\r\n\r\nconst propTypes = {\r\n /** Flag to indicate if the cost summary should start open */\r\n shouldStartOpened: PropTypes.bool,\r\n\r\n /** Flag to indicat if the cost summary is on the payment page */\r\n onPaymentPage: PropTypes.bool\r\n};\r\n\r\nexport const Summary = ({\r\n shouldStartOpened,\r\n onPaymentPage,\r\n openModal,\r\n showLoyaltyDisclaimerOnly,\r\n isHighestRatesEnabled,\r\n avoidCartLogoRender,\r\n ...restProps\r\n}) => {\r\n // Overlay State\r\n const [overlayVisible, setOverlayVisible] = useState(false);\r\n // Handle Open Cart\r\n const handleOpenCart = () => {\r\n setOverlayVisible(prev => !prev);\r\n };\r\n\r\n const isMobile = useMediaQuery({\r\n query: `(max-width: ${theme.breakpoints.md})`\r\n });\r\n\r\n const isTablet = useMediaQuery({ maxWidth: theme.breakpoints.xl });\r\n\r\n const history = useHistory();\r\n\r\n const {\r\n summaryTotal,\r\n userOffers,\r\n activeOffers,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n currentSelectedPackages,\r\n isUserAuthenticated,\r\n taxesAndFees,\r\n roomAdjustmentTax,\r\n selectedSuite,\r\n resortLocationUrlParam,\r\n isCartVariation,\r\n onCmpPage,\r\n resortLocation,\r\n cartResortLocation,\r\n clearSelectedSuite,\r\n clearSelectedPackages,\r\n resetCartResortLocation,\r\n setExpiredCart,\r\n isCartExpired,\r\n adultsCount,\r\n arrival,\r\n departure,\r\n offerCode,\r\n kidsAges,\r\n updateRateCodes,\r\n numberOfGuests,\r\n loyaltyEarnThresholdNights,\r\n setIsCartOpenClose\r\n } = restProps;\r\n\r\n const handleSummaryHeaderTotalAmount = () => {\r\n return Number(\r\n isUserAuthenticated\r\n ? !onPaymentPage\r\n ? handleTotal(\r\n userOffers,\r\n activeOffers,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n currentSelectedPackages\r\n ).toFixed(2)\r\n : handleTotalWithTaxes(\r\n userOffers,\r\n activeOffers,\r\n showLoyalty,\r\n loyaltyOptIn,\r\n pointsBalance,\r\n suiteTotal,\r\n taxesAndFees,\r\n roomAdjustmentTax,\r\n currentSelectedPackages\r\n )\r\n : summaryTotal.toFixed(2)\r\n );\r\n };\r\n\r\n // Cart Has at least suite\r\n const cartHasSuite = selectedSuite && Object.keys(selectedSuite).length > 0;\r\n // Count of packages in the cart\r\n let packagesCount = 0;\r\n if (isCartVariation && cartHasSuite) {\r\n const totalPackages = currentSelectedPackages\r\n .filter(packageItem => !packageItem.isAdjustment)\r\n .reduce((acc, packageItem) => {\r\n if (packageItem.chargeType === PACKAGE_CHARGE_TYPE.personPerDay) {\r\n return acc + 1;\r\n }\r\n if (packageItem.quantity) {\r\n return acc + packageItem.quantity;\r\n }\r\n return acc;\r\n }, 1);\r\n\r\n packagesCount = totalPackages;\r\n }\r\n\r\n // Block body scroll if overlay is visible and mobile\r\n if (isCartVariation && isMobile) {\r\n if (overlayVisible) {\r\n document.body.style.overflow = 'hidden';\r\n } else {\r\n document.body.style.overflow = 'auto';\r\n }\r\n }\r\n\r\n // Check if there is a PUSH action on history and close the cart\r\n if (isCartVariation) {\r\n history.listen(action => {\r\n if (action === 'PUSH') {\r\n setOverlayVisible(false);\r\n }\r\n });\r\n }\r\n\r\n // Open Modal for modify cart item\r\n const openModifyCartItemModal = (item, type, variation, confirmationFunction) => {\r\n openModal(\r\n {\r\n keyContentComponent: MODAL_KEYS.CART_MODIFY_MODAL,\r\n params: {\r\n item,\r\n type,\r\n variation,\r\n confirmationFunction\r\n }\r\n },\r\n false\r\n );\r\n };\r\n\r\n // Clear selected suite and packages if cart location is different from resort location\r\n useEffect(() => {\r\n if (!isCartVariation || !cartResortLocation) return;\r\n if (cartResortLocation !== resortLocation) {\r\n clearSelectedSuite();\r\n clearSelectedPackages();\r\n resetCartResortLocation();\r\n }\r\n }, [\r\n cartResortLocation,\r\n clearSelectedPackages,\r\n clearSelectedSuite,\r\n isCartVariation,\r\n resetCartResortLocation,\r\n resortLocation\r\n ]);\r\n\r\n // expiration timer\r\n useEffect(() => {\r\n // Dont run if not on cart version\r\n if (!isCartVariation) return;\r\n // Dont run if no suite selected\r\n if (!selectedSuite || isCartExpired) return;\r\n const expirationTime = localStorage.getItem('timerObj');\r\n // Dont run if no expiration time, this is set byt the timer on Plan page\r\n if (!expirationTime) return;\r\n const countdown = setInterval(() => {\r\n const timer = getTimeRemaining(expirationTime);\r\n\r\n if (timer.total < 0) {\r\n setExpiredCart();\r\n clearSelectedSuite();\r\n clearSelectedPackages();\r\n clearInterval(countdown);\r\n\r\n return;\r\n }\r\n }, 1000);\r\n return () => {\r\n clearInterval(countdown);\r\n };\r\n }, [clearSelectedPackages, clearSelectedSuite, isCartExpired, isCartVariation, selectedSuite, setExpiredCart]);\r\n\r\n const updateSuite = useCallback(\r\n async e => {\r\n e.target.classList.add('disabled');\r\n const roomWithPassRate = selectedSuite?.rateOptions?.find(\r\n rate => rate.rateType === ROOM_RATE_TYPE.roomWithWaterParkPass\r\n );\r\n const requestObject = {\r\n NumberOfAdults: adultsCount,\r\n Arrival: GwDatesWrapper.format(arrival, DATE_FORMATS.default),\r\n Departure: GwDatesWrapper.format(departure, DATE_FORMATS.default),\r\n OfferCode: offerCode,\r\n Location: resortLocation,\r\n RateCode: roomWithPassRate.rateCode,\r\n kidsAges: kidsAges.join(','),\r\n uuid: getBrowserId(),\r\n intUserId: getInteractionsUserId(),\r\n suiteType: selectedSuite.suiteCategory,\r\n isDateChanged: false,\r\n skipCompareValidation: true,\r\n availabilityKey: roomWithPassRate.availabilityKey\r\n };\r\n const newSelectedSuite = {\r\n ...selectedSuite,\r\n ...roomWithPassRate\r\n };\r\n\r\n await updateRateCodes(requestObject, newSelectedSuite);\r\n e?.target?.classList?.remove('disabled');\r\n },\r\n [adultsCount, arrival, departure, kidsAges, offerCode, resortLocation, selectedSuite, updateRateCodes]\r\n );\r\n\r\n useEffect(() => {\r\n const waterPassNoticeContainer = document.querySelector('#water-pass-notice');\r\n if (!waterPassNoticeContainer) return;\r\n\r\n if (\r\n selectedSuite?.rateType === ROOM_RATE_TYPE.roomOnlyWithoutWaterParkPass &&\r\n selectedSuite?.rateOptions?.length > 1\r\n ) {\r\n waterPassNoticeContainer.style.display = 'block';\r\n const roomWithPassRate = selectedSuite?.rateOptions?.find(\r\n rate => rate.rateType === ROOM_RATE_TYPE.roomWithWaterParkPass\r\n );\r\n const roomOnlyRate = selectedSuite?.rateOptions?.find(\r\n rate => rate.rateType === ROOM_RATE_TYPE.roomOnlyWithoutWaterParkPass\r\n );\r\n const price = roomWithPassRate?.averageNightlyBaseRate - roomOnlyRate?.averageNightlyBaseRate ?? 0;\r\n\r\n const numberOfBillableGuests = getNumberOfBillableGuests(adultsCount, kidsAges);\r\n const copyObject = {\r\n '': numberOfBillableGuests,\r\n '': Math.round(price),\r\n '': pluralize('pass', numberOfBillableGuests)\r\n };\r\n const waterPassNoticeText = document.querySelector('#water-pass-notice-text');\r\n waterPassNoticeText.innerHTML = editCopyByReplaceMultipleStrings(COPY.ROOM_WITH_NO_WATER_PASS, copyObject);\r\n const waterPassNoticeActionText = document.querySelector('#water-pass-notice-action-text > span');\r\n waterPassNoticeActionText.innerHTML = editCopyByReplaceString(\r\n COPY.ADD_PASSES,\r\n pluralize('pass', numberOfGuests),\r\n ''\r\n );\r\n waterPassNoticeActionText.addEventListener('click', updateSuite, false);\r\n } else {\r\n // remove the notice\r\n waterPassNoticeContainer.style.display = 'none';\r\n }\r\n }, [numberOfGuests, selectedSuite, updateSuite, adultsCount, kidsAges]);\r\n\r\n if (showLoyaltyDisclaimerOnly) {\r\n return (\r\n \r\n \r\n \r\n );\r\n }\r\n\r\n return (\r\n \r\n {!isCartVariation ? (\r\n \r\n \r\n \r\n ) : null}\r\n {/* Cart logo */}\r\n {isCartVariation && !avoidCartLogoRender && !onCmpPage ? (\r\n \r\n ) : null}\r\n {/* Suite Plan Content */}\r\n \r\n {/* Empty Cart */}\r\n {isCartVariation && (!cartHasSuite || isCartExpired) ? (\r\n \r\n ) : (\r\n \r\n {({ expanded }) => {\r\n return (\r\n \r\n );\r\n }}\r\n \r\n )}\r\n \r\n \r\n );\r\n};\r\n\r\nSummary.propTypes = propTypes;\r\n\r\nSummary.defaultProps = {\r\n shouldStartOpened: true\r\n};\r\n","import { connect } from 'react-redux';\r\nimport {\r\n getCheckIn,\r\n getCheckOut,\r\n getTotalNumberOfNights\r\n} from '../../../../../store/componentStores/Dates/dates.selectors';\r\nimport { openModal } from '../../../../../store/componentStores/GlobalModal/globalModal.actions';\r\nimport {\r\n getAdultsCount,\r\n getKidsAges,\r\n getKidsCount,\r\n getNumberOfGuests\r\n} from '../../../../../store/componentStores/Guests/guests.selectors';\r\nimport {\r\n getIsCartActive,\r\n getIsHighestRatesEnabled,\r\n getLoyaltyEarnThresholdNights,\r\n getParkingFeeEndDate,\r\n getParkingFeeStartDate,\r\n getPerNightParkingFee1,\r\n getPerNightParkingFee2,\r\n getPerNightParkingFee3,\r\n getPointsMultiplier,\r\n getshowCaliforniaResortFeeVariation,\r\n getTaxAndFeesLabels\r\n} from '../../../../../store/componentStores/LodgeConfig/lodgeConfig.selectors';\r\nimport {\r\n clearPlanPackages,\r\n clearSelectedPackages,\r\n deletePackage,\r\n upsertPackage\r\n} from '../../../../../store/componentStores/Packages/packages.actions';\r\nimport {\r\n getPackagesGrossTotal,\r\n getPackagesTaxes,\r\n getSelectedPackages\r\n} from '../../../../../store/componentStores/Packages/packages.selectors';\r\nimport {\r\n setCartReturnedPageLinkClicked,\r\n setIsCartOpenClose\r\n} from '../../../../../store/componentStores/Plans/plans.actions';\r\nimport { getIsCaliforniaResident } from '../../../../../store/componentStores/Plans/plans.selectors';\r\nimport {\r\n clearSelectedSuite,\r\n pushToDiningPackagesPage,\r\n pushToPackagesPage,\r\n pushToPayment,\r\n updateRateCodes\r\n} from '../../../../../store/componentStores/Suite/suite.actions';\r\nimport {\r\n getParkingFee,\r\n getPromotionalSavings,\r\n getRateType,\r\n getResortFee,\r\n getRoomAdjustmentTax,\r\n getSelectedSuite,\r\n getSuiteGrossTotal,\r\n getSuiteHeadline,\r\n getSuiteTaxes,\r\n getSustainabilityFee,\r\n getTaxesAndFeesDetailAvailability\r\n} from '../../../../../store/componentStores/Suite/suite.selectors';\r\nimport {\r\n getDueAtCheckInAmount,\r\n getDueTodayAmount,\r\n getGrossSummaryTotal,\r\n getSummaryTotal,\r\n getValidOfferCode\r\n} from '../../../../../store/reducers';\r\n\r\nimport isEmpty from 'lodash-es/isEmpty';\r\nimport {\r\n getUserIsLoggedIn,\r\n getUserLoyaltyOptIn,\r\n getUserLoyaltyPointsBalance,\r\n getUserOffers\r\n} from '../../../../../store/componentStores/Account/account.selectors';\r\nimport {\r\n pushToLastVisitedStep,\r\n resetCartResortLocation,\r\n setExpiredCart\r\n} from '../../../../../store/componentStores/Cart/cart.actions';\r\nimport {\r\n getCartLastVisitedStep,\r\n getCartResortLocation,\r\n getExpiredCart\r\n} from '../../../../../store/componentStores/Cart/cart.selectors';\r\nimport {\r\n getResortLocation,\r\n getResortLocationUrlParam\r\n} from '../../../../../store/componentStores/CurrentLodge/currentLodge.selectors';\r\nimport { removeActiveOffer } from '../../../../../store/componentStores/Offer/offer.actions';\r\nimport {\r\n getActiveOffers,\r\n getEmailActiveOffers,\r\n getOfferCode\r\n} from '../../../../../store/componentStores/Offer/offer.selectors';\r\nimport {\r\n getCartReturnedPageLinkClicked,\r\n getIsAPScall,\r\n getIsCartOpenClose\r\n} from '../../../../../store/componentStores/Plans/plans.selectors';\r\nimport { showLoyalty } from '../../../../../store/reducers';\r\nimport { getTestValueAB, TESTS_DICTIONARY } from '../../../../../utilities/ABTesting';\r\nimport { DATE_FORMATS } from '../../../../../utilities/constants';\r\nimport { getDateMonthDayFormat } from '../../../../../utilities/dates';\r\nimport { getGuestCountLabel } from '../../../../../utilities/guestsUtils';\r\nimport { checkIfIsNiagaraProperty } from '../../../../../utilities/navigationUtils';\r\nimport { getTaxesAndFees, getTaxesAndFeesDynamic } from '../../../../../utilities/taxes';\r\nimport { GwDatesWrapper } from '../../../../_internal_date_/gwDatesWrapper';\r\nimport { SUMMARY_CART_VARIATIONS } from '../utilities/constants';\r\nimport { Summary } from './Summary';\r\n\r\nconst getPlanSummaryTotal = (onPaymentPage, state) => {\r\n return onPaymentPage ? getSummaryTotal(state) : getGrossSummaryTotal(state);\r\n};\r\n\r\nconst mapStateToProps = (state, { location, variation }) => {\r\n const { pathname } = location;\r\n\r\n const onPaymentPage = pathname.includes('/payment');\r\n const onActivitiesPage = pathname.includes('/packages-activities');\r\n const onDiningPage = pathname.includes('/packages-dining');\r\n const avoidCartLogoRender = onPaymentPage || onActivitiesPage || onDiningPage;\r\n\r\n const cmpUrls = ['confirmation', /my-reservations\\/[\\w\\d]+/];\r\n const onCmpPage = cmpUrls.some(keyword => {\r\n if (keyword instanceof RegExp) {\r\n return keyword.test(pathname);\r\n }\r\n return pathname.includes(keyword);\r\n });\r\n\r\n const onPlanPage = pathname.includes('/plan');\r\n\r\n const selectedPackages = getSelectedPackages(state.packages);\r\n\r\n const taxAndFeeLabels = getTaxAndFeesLabels(state.lodgeConfig);\r\n\r\n const taxesAndFeesPrices = getTaxesAndFeesDetailAvailability(state.suite);\r\n // This is added until backend changes are ready\r\n const taxesAndFees =\r\n !isEmpty(taxAndFeeLabels) && !isEmpty(taxesAndFeesPrices)\r\n ? getTaxesAndFeesDynamic(taxAndFeeLabels, taxesAndFeesPrices, getPackagesTaxes(state.packages))\r\n : getTaxesAndFees(\r\n getSustainabilityFee(state.suite),\r\n getPackagesTaxes(state.packages) + getSuiteTaxes(state.suite),\r\n getResortFee(state.suite),\r\n getParkingFee(state.suite)\r\n );\r\n\r\n /* ABCD TEST FOR PARKING FEE */\r\n const optimizelyAddParkingFee1 = getTestValueAB(TESTS_DICTIONARY.optimizelyAddParkingFee1, false);\r\n const optimizelyAddParkingFee2 = getTestValueAB(TESTS_DICTIONARY.optimizelyAddParkingFee2, false);\r\n const optimizelyAddParkingFee3 = getTestValueAB(TESTS_DICTIONARY.optimizelyAddParkingFee3, false);\r\n const checkInDateIsInTheParkingFeeInterval = GwDatesWrapper.isBetween(\r\n GwDatesWrapper.format(getCheckIn(state.dates), DATE_FORMATS.default),\r\n GwDatesWrapper.format(getParkingFeeStartDate(state.lodgeConfig), DATE_FORMATS.default),\r\n GwDatesWrapper.format(getParkingFeeEndDate(state.lodgeConfig), DATE_FORMATS.default)\r\n );\r\n\r\n let currentParkingFeeAmount = 0;\r\n\r\n if (optimizelyAddParkingFee1) {\r\n currentParkingFeeAmount = Number(getPerNightParkingFee1(state.lodgeConfig));\r\n } else if (optimizelyAddParkingFee2) {\r\n currentParkingFeeAmount = Number(getPerNightParkingFee2(state.lodgeConfig));\r\n } else if (optimizelyAddParkingFee3) {\r\n currentParkingFeeAmount = Number(getPerNightParkingFee3(state.lodgeConfig));\r\n }\r\n\r\n const isParkingFeeABCDTestActive =\r\n checkInDateIsInTheParkingFeeInterval &&\r\n (optimizelyAddParkingFee1 || optimizelyAddParkingFee2 || optimizelyAddParkingFee3);\r\n\r\n const parkingFeeTotal = currentParkingFeeAmount * getTotalNumberOfNights(state.dates);\r\n\r\n /* ABCD TEST FOR PARKING FEE */\r\n\r\n const resortLocation = getResortLocation(state.currentLodge);\r\n\r\n return {\r\n checkIn:\r\n variation === SUMMARY_CART_VARIATIONS.CART\r\n ? GwDatesWrapper.format(getCheckIn(state.dates), DATE_FORMATS.monthDayYear)\r\n : getDateMonthDayFormat(getCheckIn(state.dates)),\r\n checkOut:\r\n variation === SUMMARY_CART_VARIATIONS.CART\r\n ? GwDatesWrapper.format(getCheckOut(state.dates), DATE_FORMATS.monthDayYear)\r\n : getDateMonthDayFormat(getCheckOut(state.dates)),\r\n currentSelectedPackages: selectedPackages,\r\n dueTodayAmount: getDueTodayAmount(state),\r\n dueAtCheckinAmount: getDueAtCheckInAmount(state),\r\n isCaliforniaResident: getIsCaliforniaResident(state.plans),\r\n guestCountText: getGuestCountLabel(getAdultsCount(state.guests), getKidsCount(state.guests), variation),\r\n hasAdditionalCharges: taxesAndFees && taxesAndFees.length > 0,\r\n hasSelectedPackages: selectedPackages && selectedPackages.length > 0,\r\n isNiagaraProperty: checkIfIsNiagaraProperty(resortLocation),\r\n rateType: getRateType(state.suite),\r\n numberOfGuests: getNumberOfGuests(state.guests),\r\n numberOfNights: getTotalNumberOfNights(state.dates),\r\n onPaymentPage: onPaymentPage,\r\n packagesTotal: getPackagesGrossTotal(state.packages),\r\n promoCode: getValidOfferCode(state),\r\n promotionalSavings: getPromotionalSavings(state.suite),\r\n suiteTitle: getSuiteHeadline(state.suite),\r\n suiteTotal: getSuiteGrossTotal(state.suite),\r\n summaryTotal: getPlanSummaryTotal(onPaymentPage, state),\r\n taxesAndFees: taxesAndFees,\r\n pointsBalance: getUserLoyaltyPointsBalance(state.account),\r\n loyaltyOptIn: getUserLoyaltyOptIn(state.account),\r\n showLoyalty: showLoyalty(state),\r\n userOffers: getUserOffers(state.account),\r\n activeOffers: getActiveOffers(state.offer),\r\n emailActiveOffers: getEmailActiveOffers(state.offer),\r\n isUserAuthenticated: getUserIsLoggedIn(state.account),\r\n getPointsMultiplier: getPointsMultiplier(state.lodgeConfig),\r\n roomAdjustmentTax: getRoomAdjustmentTax(state),\r\n isParkingFeeABCDTestActive: isParkingFeeABCDTestActive,\r\n showCaliforniaResortFeeVariation: getshowCaliforniaResortFeeVariation(state.lodgeConfig),\r\n currentParkingFeeAmount: currentParkingFeeAmount,\r\n parkingFeeTotal: parkingFeeTotal,\r\n offerCode: getOfferCode(state.offer),\r\n resortLocation,\r\n selectedSuite: getSelectedSuite(state.suite),\r\n resortLocationUrlParam: getResortLocationUrlParam(state.currentLodge),\r\n onCmpPage,\r\n onPlanPage,\r\n isApsCall: getIsAPScall(state.plans),\r\n isCartOpenClose: getIsCartOpenClose(state.plans),\r\n cartReturnedPageLinkClicked: getCartReturnedPageLinkClicked(state.plans),\r\n isCartVariation:\r\n variation === SUMMARY_CART_VARIATIONS.CART &&\r\n getIsCartActive(state.lodgeConfig) &&\r\n getTestValueAB(TESTS_DICTIONARY.optimizelyCartFlow, false),\r\n cartResortLocation: getCartResortLocation(state.cart),\r\n cartLastVisitedStep: getCartLastVisitedStep(state.cart),\r\n isCartExpired: getExpiredCart(state.cart),\r\n adultsCount: getAdultsCount(state.guests),\r\n kidsAges: getKidsAges(state.guests),\r\n arrival: getCheckIn(state.dates),\r\n departure: getCheckOut(state.dates),\r\n loyaltyEarnThresholdNights: getLoyaltyEarnThresholdNights(state.lodgeConfig),\r\n kidsCount: getKidsCount(state.guests),\r\n isHighestRatesEnabled: getIsHighestRatesEnabled(state.lodgeConfig),\r\n avoidCartLogoRender\r\n };\r\n};\r\n\r\nconst mapDispatchToProps = {\r\n upsertPackage,\r\n deletePackage,\r\n clearPlanPackages,\r\n clearSelectedPackages,\r\n openModal,\r\n resetCartResortLocation: resetCartResortLocation,\r\n pushToLastVisitedStep: pushToLastVisitedStep,\r\n setExpiredCart: setExpiredCart,\r\n setIsCartOpenClose,\r\n setCartReturnedPageLinkClicked,\r\n clearSelectedSuite,\r\n pushToPayment,\r\n pushToDiningPackagesPage,\r\n pushToPackagesPage,\r\n updateRateCodes,\r\n removeActiveOffer\r\n};\r\n\r\nconst PlanSummary = connect(mapStateToProps, mapDispatchToProps)(Summary);\r\n\r\nexport { PlanSummary };\r\n\r\n","import { useState, useEffect } from 'react';\r\n\r\nfunction getWindowDimensions() {\r\n const { innerWidth: width, innerHeight: height } = window;\r\n return {\r\n width,\r\n height\r\n };\r\n}\r\n\r\nconst useWindowDimensions = () => {\r\n const [windowDimensions, setWindowDimensions] = useState(\r\n getWindowDimensions()\r\n );\r\n\r\n useEffect(() => {\r\n function handleResize() {\r\n setWindowDimensions(getWindowDimensions());\r\n }\r\n\r\n window.addEventListener('resize', handleResize);\r\n return () => window.removeEventListener('resize', handleResize);\r\n }, []);\r\n\r\n return windowDimensions;\r\n};\r\n\r\nexport default useWindowDimensions;\r\n","import styled from 'styled-components';\r\n\r\nimport { Modal } from '../../../Modal';\r\nimport { Absolute, Box, Flex, Text } from '../../../ui-kit';\r\nimport theme from '../../../ui-kit/themes/theme';\r\n\r\nexport const ModalWrapper = styled(Modal)``;\r\n\r\nexport const CloseButtonContainer = styled(Absolute)`\r\n right: 26px;\r\n top: 30px;\r\n cursor: pointer;\r\n`;\r\n\r\nexport const Content = styled(Box)`\r\n padding: 0px ${theme.space[7]}px;\r\n overflow-x: hidden;\r\n`;\r\n\r\nexport const Divider = styled(Box)`\r\n border: 1px solid ${theme.colors.kiddiePoolBlue[10]};\r\n margin-bottom: ${theme.space[4]}px;\r\n`;\r\n\r\nexport const Header = styled(Flex)`\r\n padding: ${theme.space[7]}px;\r\n color: ${theme.colors.deepLakeBlue[100]};\r\n align-items: center;\r\n width: 100%;\r\n position: relative;\r\n height: 82px;\r\n border-bottom: 1px solid ${theme.colors.snowMountainGrey[100]};\r\n`;\r\n\r\nexport const Title = styled(Text)`\r\n font-weight: ${theme.fontWeights.bold};\r\n color: ${theme.colors.preciousStoneBlue[100]};\r\n font-size: 18px;\r\n padding: 0px;\r\n flex: 1;\r\n text-align: center;\r\n`;\r\n","import React from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\n\r\nimport theme from '../../../../components/ui-kit/themes/theme';\r\nimport CloseIcon from '../../../ui-kit/icons/Close';\r\nimport { ModalContent } from './ModalContent';\r\nimport { CloseButtonContainer, Divider, Header, ModalWrapper, Title } from './styles';\r\n\r\nexport const SummaryModal = ({ opened, children, ...restProps }) => {\r\n const isMobile = useMediaQuery({\r\n query: `(max-width: ${theme.breakpoints.sm})`\r\n });\r\n const isTablet = useMediaQuery({\r\n query: `(min-width: ${theme.breakpoints.md}) and (max-width: ${theme.breakpoints.lg})`\r\n });\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nSummaryModal.CloseButton = ({ onClick }) => {\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nSummaryModal.Content = ModalContent;\r\n\r\nSummaryModal.Divider = () => {\r\n return ;\r\n};\r\n\r\nSummaryModal.Header = ({ children, ...restProps }) => {\r\n return ;\r\n};\r\n\r\nSummaryModal.Title = ({ children, ...restProps }) => {\r\n return {children};\r\n};\r\n","import React, { useCallback, useState } from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\n\r\nimport theme from '../../../../components/ui-kit/themes/theme';\r\nimport { Box } from '../../../ui-kit';\r\nimport useWindowDimensions from '../../../utilities/hooks/useWindowDimensions';\r\nimport { Content } from './styles';\r\n\r\nexport const ModalContent = ({ children, ...restProps }) => {\r\n const [currentHeight, setCurrentHeight] = useState(0);\r\n const { height } = useWindowDimensions();\r\n\r\n const isMobile = useMediaQuery({\r\n query: `(max-width: ${theme.breakpoints.sm})`\r\n });\r\n\r\n const isTablet = useMediaQuery({\r\n query: `(min-width: ${theme.breakpoints.md}) and (max-width: ${theme.breakpoints.lg})`\r\n });\r\n\r\n const maxHeightModalsMargin = 1417;\r\n const headerDistance = 68 + 24;\r\n const verticalMarginsLessThanMaxHeight = 141 * 2;\r\n const verticalMarginsAfterMaxHeight = 280 * 2;\r\n\r\n const measuredRef = useCallback(node => {\r\n if (node !== null) {\r\n setCurrentHeight(node.getBoundingClientRect().height);\r\n }\r\n }, []);\r\n\r\n const contentHeight =\r\n height < maxHeightModalsMargin\r\n ? height - (verticalMarginsLessThanMaxHeight + headerDistance)\r\n : height - (verticalMarginsAfterMaxHeight + headerDistance);\r\n\r\n const calculatedHeight = currentHeight > 0 && currentHeight < contentHeight ? currentHeight : contentHeight;\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { COSTSUMMARY_TOOLTIP, ROOM_RATE_TYPE } from '../../../../../../utilities/constants';\r\nimport { Box, Text } from '../../../../../ui-kit';\r\nimport Tooltip from '../../../../../ui-kit/Tooltip';\r\nimport QuestionIcon from '../../../../../ui-kit/icons/Question';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nconst SummaryTooltip = ({ isDesktop, title, children }) => {\r\n return (\r\n (\r\n \r\n {children}\r\n \r\n )}\r\n />\r\n );\r\n};\r\n\r\nconst propTypes = {\r\n /** Flag that indicates that the reservation has additional charges */\r\n hasAdditionalCharges: PropTypes.bool.isRequired,\r\n\r\n /** Array with the taxes and fees for reservation*/\r\n taxesAndFees: PropTypes.arrayOf(\r\n PropTypes.shape({\r\n id: PropTypes.string,\r\n name: PropTypes.string,\r\n amount: PropTypes.number,\r\n tooltip: PropTypes.string\r\n })\r\n )\r\n};\r\n\r\nexport const AdditionalCharges = ({ hasAdditionalCharges, taxesAndFees, rateType, addGuestReservation }) => {\r\n const isDesktop = useMediaQuery({\r\n minWidth: theme.breakpoints.sm\r\n });\r\n\r\n if (!hasAdditionalCharges) return null;\r\n\r\n const isRoomOnly = rateType === ROOM_RATE_TYPE.roomOnlyWithoutWaterParkPass;\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_ADDITIONAL_CHARGES}\r\n \r\n \r\n \r\n {addGuestReservation ? (\r\n \r\n \r\n \r\n {COPY.TAXES}\r\n \r\n \r\n \r\n \r\n {`$${Number(addGuestReservation.costSummary.taxesAndFees.TAX).toFixed(2)}`}\r\n \r\n \r\n \r\n ) : null}\r\n {addGuestReservation?.costSummary?.taxesAndFees?.RESORT ? (\r\n \r\n \r\n \r\n {COPY.RESORT_FEE}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {`$${Number(addGuestReservation.costSummary.taxesAndFees.RESORT).toFixed(2)}`}\r\n \r\n \r\n \r\n ) : null}\r\n {!addGuestReservation &&\r\n taxesAndFees.map(item => (\r\n \r\n \r\n \r\n {item.name}\r\n \r\n {item.tooltip && (\r\n \r\n \r\n \r\n )}\r\n \r\n \r\n {`$${item.amount.toFixed(2)}`}\r\n \r\n \r\n ))}\r\n >\r\n );\r\n};\r\n\r\nAdditionalCharges.propTypes = propTypes;\r\n\r\nAdditionalCharges.defaultProps = {\r\n hasAdditionalCharges: false,\r\n taxesAndFees: [],\r\n iconSize: 16\r\n};\r\n","import styled, { css } from 'styled-components';\r\nimport { Accordion } from 'react-accessible-accordion';\r\n\r\nconst BAR_WIDTH = '10px';\r\n\r\nexport const AccordionStyle = styled(Accordion)`\r\n cursor: pointer;\r\n`;\r\n\r\nexport const ArrowIcon = styled.div`\r\n height: 20px;\r\n width: 20px;\r\n display: inline-block;\r\n padding: 0.5em;\r\n margin-left: 0.5em;\r\n position: relative;\r\n cursor: pointer;\r\n border-radius: 4px;\r\n & > span {\r\n top: ${BAR_WIDTH};\r\n position: absolute;\r\n background-color: transparent;\r\n width: ${BAR_WIDTH};\r\n height: 5px;\r\n display: block;\r\n float: right;\r\n border-radius: 2px;\r\n &:after {\r\n width: ${BAR_WIDTH};\r\n content: '';\r\n background-color: #28384c;\r\n height: 1px;\r\n display: block;\r\n float: right;\r\n transition: all 0.7s cubic-bezier(0.25, 1.7, 0.35, 0.8);\r\n }\r\n }\r\n\r\n ${({ isExpanded }) => {\r\n if (isExpanded) {\r\n return css`\r\n & > span:nth-child(1) {\r\n &:after {\r\n transform-origin: center center;\r\n transform: rotate(-85deg);\r\n }\r\n }\r\n & > span:nth-child(2) {\r\n &:after {\r\n transform-origin: center center;\r\n transform: rotate(85deg);\r\n }\r\n }\r\n `;\r\n }\r\n }}\r\n`;\r\n\r\nexport const Leftbar = styled.span`\r\n left: 0;\r\n transform: rotate(45deg);\r\n &:after {\r\n border-radius: 6px 10px 10px 6px;\r\n }\r\n`;\r\n\r\nexport const RightBar = styled.span`\r\n left: ${BAR_WIDTH};\r\n transform: rotate(-45deg);\r\n &:after {\r\n border-radius: 10px 6px 6px 10px;\r\n z-index: -1;\r\n }\r\n`;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nimport {\r\n Accordion,\r\n AccordionItem,\r\n AccordionItemButton,\r\n AccordionItemHeading,\r\n AccordionItemPanel,\r\n AccordionItemState\r\n} from 'react-accessible-accordion';\r\nimport { isValidPrice } from '../../../../../../utilities/cmpPackagesUtils';\r\nimport { Flex, Text } from '../../../../../ui-kit';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { SummaryContent } from '../../../Content';\r\nimport { AccordionStyle, ArrowIcon, Leftbar, RightBar } from '../styles';\r\n\r\nconst propTypes = {\r\n /** Deposit paid for the reservation */\r\n depositPaid: PropTypes.number.isRequired,\r\n\r\n /** Due amount at check in */\r\n dueAtCheckinAmount: PropTypes.number.isRequired\r\n};\r\n\r\nconst DepositSummary = props => {\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_DEPOSIT_PAID}\r\n \r\n \r\n {({ expanded }) => (\r\n \r\n \r\n \r\n \r\n )}\r\n \r\n \r\n \r\n\r\n \r\n {`$${props.totalDeposit.toFixed(2)}`}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_CABANA_DEPOSIT}\r\n \r\n \r\n \r\n {`$${props.cabanaDeposit.toFixed(2)}`}\r\n \r\n \r\n\r\n \r\n \r\n \r\n {COPY.SUMMARY_SUITE_RESERVATION}\r\n \r\n \r\n \r\n {`$${props.roomDeposit.toFixed(2)}`}\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n >\r\n );\r\n};\r\n\r\nconst SimpleDeposit = ({ depositPaid, newCMPGuestsCount, addGuestReservation }) => {\r\n const removeNewGuestsValue = () => {\r\n return `$${(depositPaid - newCMPGuestsCount?.feeGuests * newCMPGuestsCount?.extraPerGuestAmount).toFixed(2)}`;\r\n };\r\n return (\r\n <>\r\n {newCMPGuestsCount?.feeGuests > 0 && !addGuestReservation ? (\r\n <>\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_DEPOSIT_PAID}\r\n \r\n \r\n {({ expanded }) => (\r\n \r\n \r\n \r\n \r\n )}\r\n \r\n \r\n \r\n\r\n \r\n {`$${depositPaid.toFixed(2)}`}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_SUITE_RESERVATION}\r\n \r\n \r\n \r\n {`${removeNewGuestsValue()}`}\r\n \r\n \r\n \r\n \r\n \r\n {newCMPGuestsCount?.feeGuests}{' '}\r\n {newCMPGuestsCount?.feeGuests > 1 ? COPY.NEW_GUESTS : COPY.NEW_GUEST}\r\n {' '}\r\n \r\n \r\n \r\n {`$${(\r\n newCMPGuestsCount?.feeGuests * newCMPGuestsCount?.extraPerGuestAmount\r\n ).toFixed(2)}`}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n >\r\n ) : (\r\n \r\n \r\n \r\n {COPY.SUMMARY_DEPOSIT_PAID}\r\n \r\n \r\n \r\n {`$${\r\n addGuestReservation ? addGuestReservation.costSummary.depositPaid.toFixed(2) : depositPaid.toFixed(2)\r\n }`}\r\n \r\n \r\n )}\r\n >\r\n );\r\n};\r\n\r\nexport const Deposit = ({\r\n cabanaDeposit,\r\n depositPaid,\r\n dueAtCheckinAmount,\r\n roomDeposit,\r\n newCMPGuestsCount,\r\n addGuestReservation\r\n}) => {\r\n const amountsNonValid = !isValidPrice(depositPaid) || !isValidPrice(dueAtCheckinAmount);\r\n if (amountsNonValid) return null;\r\n const totalDeposit = cabanaDeposit + roomDeposit;\r\n\r\n return (\r\n <>\r\n \r\n {cabanaDeposit > 0 ? (\r\n \r\n ) : (\r\n \r\n )}\r\n \r\n \r\n \r\n {COPY.SUMMARY_DUE_CHECKIN}\r\n \r\n \r\n \r\n \r\n {`$${\r\n addGuestReservation\r\n ? addGuestReservation.costSummary.dueAtCheckIn.toFixed(2)\r\n : dueAtCheckinAmount.toFixed(2)\r\n }`}\r\n \r\n \r\n \r\n >\r\n );\r\n};\r\n\r\nDeposit.propTypes = propTypes;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { Text } from '../../../../../ui-kit';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nimport { SummaryContent } from '../../../Content';\r\n\r\nconst propTypes = {\r\n /** Flag that indicates that the reservation has discount charges */\r\n hasDiscountCharges: PropTypes.bool.isRequired,\r\n\r\n /** Vyager points for reservation*/\r\n voyagerPointsDiscount: PropTypes.number,\r\n\r\n /** Offers points for reservation*/\r\n offersPointsDiscount: PropTypes.number\r\n};\r\n\r\nexport const DiscountCharges = ({ hasDiscountCharges, voyagerPointsDiscount, offersPointsDiscount }) => {\r\n if (!hasDiscountCharges) return null;\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_DISCOUNT_CHANGES}\r\n \r\n \r\n \r\n\r\n {voyagerPointsDiscount !== 0 && (\r\n \r\n \r\n \r\n {COPY.SUMMARY_VOYAGERS_POINTS_APPLIED}\r\n \r\n \r\n \r\n {`-$${String(voyagerPointsDiscount.toFixed(2)).replace('-', '')}`}\r\n \r\n \r\n )}\r\n\r\n {offersPointsDiscount !== 0 && (\r\n \r\n \r\n \r\n {COPY.SUMMARY_BONNUS_DEALS_APPLIED}\r\n \r\n \r\n \r\n {`-$${String(offersPointsDiscount.toFixed(2)).replace('-', '')}`}\r\n \r\n \r\n )}\r\n >\r\n );\r\n};\r\n\r\nDiscountCharges.propTypes = propTypes;\r\n\r\nDiscountCharges.defaultProps = {\r\n hasDiscountCharges: false,\r\n voyagerPointsDiscount: 0,\r\n offersPointsDiscount: 0\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { pluralize } from '../../../../../../components/utilities/copyFunctions';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nimport { GwDatesWrapper } from '../../../../../_internal_date_/gwDatesWrapper';\r\nimport { CheckInOutDate } from '../../../../../CheckInOutDates';\r\nimport { Flex, Text } from '../../../../../ui-kit';\r\nimport ArrowRightIcon from '../../../../../ui-kit/icons/ArrowRight';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { SummaryContent } from '../../../Content';\r\n\r\nconst propTypes = {\r\n /** Checkin Date in the MM/DD format */\r\n checkIn: PropTypes.string.isRequired,\r\n\r\n /** Checkout Date in the MM/DD format */\r\n checkOut: PropTypes.string.isRequired,\r\n\r\n /** Number of nights for the reservation */\r\n numberOfNights: PropTypes.number.isRequired\r\n};\r\n\r\nexport const Header = ({ checkIn, checkOut, numberOfNights, hasNewGuests, addGuestReservation }) => {\r\n const numberOfNightsLabel = nights => `${nights} ${pluralize('night', nights)}`;\r\n const newGuestsBold = {COPY.NEW_GUESTS_BOLD};\r\n return (\r\n <>\r\n {(hasNewGuests || addGuestReservation) && (\r\n \r\n )}\r\n \r\n \r\n \r\n {COPY.SUMMARY_CHECKIN}\r\n \r\n \r\n {addGuestReservation ? GwDatesWrapper.format(addGuestReservation.arrival, 'MM/DD') : checkIn}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_CHECKOUT}\r\n \r\n \r\n {addGuestReservation ? GwDatesWrapper.format(addGuestReservation.departure, 'MM/DD') : checkOut}\r\n \r\n \r\n \r\n \r\n \r\n \r\n {addGuestReservation\r\n ? numberOfNightsLabel(\r\n GwDatesWrapper.diff(addGuestReservation.departure, addGuestReservation.arrival, 'days')\r\n )\r\n : numberOfNightsLabel(numberOfNights)}\r\n \r\n \r\n \r\n >\r\n );\r\n};\r\n\r\nHeader.propTypes = propTypes;\r\n","import { useCallback, useState } from 'react';\r\nimport LodgeApiClient from '../../api/clients/LodgeApiClient';\r\n//import { waitFor } from '../../utilities/waitFor';\r\n/**\r\n * This hook is to get the user data for lead gen\r\n * @returns array with status, fetch function and reset function\r\n */\r\nconst useGetLodgeConfig = () => {\r\n // State Valeus on the hook\r\n const [isCalled, toggleCalled] = useState(false);\r\n const [hasError, toggleError] = useState(false);\r\n const [errorMessage, setErrorMessage] = useState('');\r\n\r\n // Reset funciton\r\n const reset = useCallback(() => {\r\n toggleCalled(false);\r\n toggleError(false);\r\n setErrorMessage('');\r\n }, []);\r\n\r\n const fetch = useCallback(\r\n async (property, application, { onSuccess = () => {}, toggleLoading = () => {}, onFailure = () => {} }) => {\r\n reset();\r\n toggleLoading(true);\r\n\r\n const apiClient = new LodgeApiClient();\r\n\r\n try {\r\n const result = await apiClient.getConfiguration(property, application);\r\n toggleCalled(true);\r\n toggleLoading(false);\r\n onSuccess(result.data);\r\n } catch (error) {\r\n toggleCalled(true);\r\n toggleLoading(false);\r\n toggleError(true);\r\n setErrorMessage(error);\r\n onFailure(error);\r\n }\r\n },\r\n [reset]\r\n );\r\n\r\n return [fetch, reset, { isCalled, hasError, errorMessage }];\r\n};\r\n\r\nexport default useGetLodgeConfig;\r\n","import { isString } from 'lodash-es';\r\nimport PropTypes from 'prop-types';\r\nimport React, { useCallback, useEffect, useRef } from 'react';\r\nimport useGetLodgeConfig from '../../../../../../hooks/api_hooks/useGetLodgeConfig';\r\nimport { getTheFirstElementOfArray } from '../../../../../../utilities/arraysUtils';\r\nimport {\r\n LATE_CHECKOUT_PREFIXES,\r\n PACKAGE_CHARGE_TYPE,\r\n PACKAGE_TYPE,\r\n PARKING_PACKAGE_CODE,\r\n ROOM_RATE_TYPE\r\n} from '../../../../../../utilities/constants';\r\nimport { addNewTag } from '../../../../../../utilities/packagesUtils';\r\nimport { Box, Text } from '../../../../../ui-kit';\r\nimport { editCopyByReplaceMultipleStrings, pluralize } from '../../../../../utilities/copyFunctions';\r\nimport { SummaryContent } from '../../../Content';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nconst propTypes = {\r\n /** Currently selected packages for the reservation */\r\n packages: PropTypes.arrayOf(\r\n PropTypes.shape({\r\n packageName: PropTypes.string.isRequired,\r\n packageCode: PropTypes.string.isRequired,\r\n amount: PropTypes.number.isRequired,\r\n quantity: PropTypes.number.isRequired\r\n }).isRequired\r\n ),\r\n\r\n /** Flag to indicate if there are selected packages for the reservation */\r\n hasSelectedPackages: PropTypes.bool,\r\n\r\n /** Newly added package code */\r\n newAddedPackageCode: PropTypes.string\r\n};\r\n\r\nconst PKGS_WITH_NO_QTY = [LATE_CHECKOUT_PREFIXES.code, PARKING_PACKAGE_CODE];\r\n\r\nexport const PackagesList = ({\r\n packages,\r\n hasSelectedPackages,\r\n newAddedPackageCode,\r\n totalBillAndNonBillGuest,\r\n numberOfNights,\r\n rateType,\r\n resortLocation,\r\n addGuestReservation\r\n}) => {\r\n const [fetchUFFPackageCode] = useGetLodgeConfig();\r\n\r\n const getUFFPackageCode = useCallback(async () => {\r\n const onSuccess = result => {\r\n const uffJSON = JSON.parse(result.uffPackageCodes);\r\n const UFF_CODES = Object.values(uffJSON);\r\n PKGS_WITH_NO_QTY.push(...UFF_CODES);\r\n };\r\n const onFailure = err => console.log(err);\r\n\r\n await fetchUFFPackageCode(resortLocation?.resortLocation, 'uff', { onSuccess, onFailure });\r\n }, [resortLocation, fetchUFFPackageCode]);\r\n\r\n const getUFFPackageCodeTriggered = useRef(false);\r\n useEffect(() => {\r\n if (!getUFFPackageCodeTriggered.current) {\r\n getUFFPackageCodeTriggered.current = true;\r\n getUFFPackageCode();\r\n }\r\n }, [getUFFPackageCode]);\r\n\r\n const objectForCopy = {\r\n '': totalBillAndNonBillGuest,\r\n '': numberOfNights,\r\n '': pluralize('guest', totalBillAndNonBillGuest),\r\n '': pluralize('night', numberOfNights)\r\n };\r\n\r\n const areWaterParkPassesIncluded = rateType !== ROOM_RATE_TYPE.roomOnlyWithoutWaterParkPass;\r\n\r\n return (\r\n <>\r\n {addGuestReservation ? : null}\r\n {addGuestReservation\r\n ? addGuestReservation.addOns.map((item, index) => {\r\n return (\r\n \r\n \r\n \r\n {item?.quantity ? (\r\n \r\n {item.quantity} {item.content.title}\r\n \r\n ) : (\r\n \r\n {item.content.title}\r\n \r\n )}\r\n {item?.splash && }\r\n \r\n \r\n \r\n \r\n {item.totalPrice === 0 ? COPY.SUMMARY_INCLUDED_REGULAR : `$${item.totalPrice.toFixed(2)}`}\r\n \r\n \r\n \r\n );\r\n })\r\n : null}\r\n {areWaterParkPassesIncluded && !addGuestReservation ? (\r\n <>\r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_WATER_PARK_PASSES}\r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_INCLUDED}\r\n \r\n \r\n \r\n >\r\n ) : null}\r\n\r\n {hasSelectedPackages &&\r\n !addGuestReservation &&\r\n packages.map((item, index) => {\r\n // This is for the Dining deals name to match with the rest of the app\r\n const copyObject = {\r\n '': isString(item.packageAllowance) ? item.packageAllowance : `$${item.packageAllowance}`,\r\n '': getTheFirstElementOfArray(item.packageName.split(' '))\r\n };\r\n const packageName =\r\n item.packageType === PACKAGE_TYPE.dining && item.packageAllowance !== 0\r\n ? editCopyByReplaceMultipleStrings(COPY.SUMMARY_DINING_CREDIT_PACKAGE_TITLE, copyObject)\r\n : item.packageName;\r\n\r\n return item.quantity === 0 ? null : (\r\n \r\n \r\n \r\n \r\n {`${\r\n PKGS_WITH_NO_QTY.some(code => item.packageCode.includes(code)) ||\r\n (item.packageType === PACKAGE_TYPE.dining &&\r\n (item.packageCharge === PACKAGE_CHARGE_TYPE.personPerDay || item.packageAllowance !== 0))\r\n ? ''\r\n : item.quantity\r\n } `}\r\n {packageName}\r\n \r\n {addNewTag(newAddedPackageCode, item.packageCode) && }\r\n \r\n {item.packageType === PACKAGE_TYPE.dining && item.packageCharge === PACKAGE_CHARGE_TYPE.personPerDay ? (\r\n \r\n \r\n {editCopyByReplaceMultipleStrings(COPY.DINING_DEALS_DETAILS, objectForCopy)}\r\n \r\n \r\n ) : null}\r\n \r\n \r\n {`$${item.amount.toFixed(2)}`}\r\n \r\n \r\n );\r\n })}\r\n >\r\n );\r\n};\r\n\r\nPackagesList.propTypes = propTypes;\r\n\r\nPackagesList.defaultProps = {\r\n hasSelectedPackages: false\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { Flex, Text } from '../../../../../ui-kit';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { Divider } from '../../../../../../pages/ReservationDetail/styles';\r\nimport AlertSuccessIcon from '../../../../../ui-kit/icons/AlertSuccessIcon';\r\nimport theme from '../../../../../ui-kit/themes/theme';\r\nimport { editCopyByReplaceString } from '../../../../../utilities/copyFunctions';\r\nimport { SummaryContent } from '../../../Content';\r\n\r\nconst propTypes = {\r\n /** Title of the suite */\r\n suiteTitle: PropTypes.string.isRequired,\r\n\r\n /** Total for the suite */\r\n suiteTotal: PropTypes.number.isRequired,\r\n\r\n /** Promo code used in the reservation */\r\n promoCode: PropTypes.string,\r\n\r\n /** Number of guests as `1 Adult, 0 Kid` or `2 Adults, 2 Kids` */\r\n guestCountText: PropTypes.string.isRequired,\r\n\r\n /** Flag for the suite that has new guests added from CMP */\r\n hasNewGuests: PropTypes.bool,\r\n\r\n /** Number of new guests added from CMP */\r\n newCMPGuestsCount: PropTypes.object\r\n};\r\n\r\nexport const SuiteDetails = ({\r\n suiteTitle,\r\n suiteName,\r\n suiteTotal,\r\n guestCountText,\r\n promoCode,\r\n hasNewGuests,\r\n newCMPGuestsCount,\r\n addGuestReservation\r\n}) => {\r\n const isMobile = useMediaQuery({\r\n query: `(max-width: ${theme.breakpoints.md})`\r\n });\r\n\r\n const newGuestsWithFeeTotal = () => {\r\n const total =\r\n newCMPGuestsCount?.feeGuests > 0\r\n ? `$${(newCMPGuestsCount?.feeGuests * newCMPGuestsCount?.extraPerGuestAmount).toFixed(2)}`\r\n : `$0.00`;\r\n return total;\r\n };\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n {addGuestReservation ? addGuestReservation?.product.name : suiteName ? suiteName : suiteTitle}\r\n \r\n \r\n \r\n \r\n {addGuestReservation\r\n ? `$${addGuestReservation?.product.totalPrice.toFixed(2)}`\r\n : `$${\r\n newCMPGuestsCount?.feeGuests > 0\r\n ? (suiteTotal - newCMPGuestsCount?.feeGuests * newCMPGuestsCount?.extraPerGuestAmount).toFixed(2)\r\n : suiteTotal.toFixed(2)\r\n }`}\r\n \r\n \r\n \r\n {isMobile ? null : !addGuestReservation ? : null}\r\n {hasNewGuests && !addGuestReservation && (\r\n <>\r\n {newCMPGuestsCount?.unbillableGuests > 0 ? (\r\n <>\r\n \r\n \r\n \r\n {editCopyByReplaceString(\r\n COPY.NEW_GUESTS_ADDED,\r\n String(newCMPGuestsCount?.unbillableGuests),\r\n ''\r\n )}\r\n \r\n \r\n \r\n {`$0.00`}\r\n \r\n \r\n \r\n \r\n \r\n {COPY.NEW_GUESTS_IN_BASE_OCUPANCY}\r\n \r\n \r\n \r\n >\r\n ) : null}\r\n {newCMPGuestsCount?.feeGuests > 0 ? (\r\n <>\r\n \r\n \r\n \r\n {editCopyByReplaceString(\r\n COPY.NEW_GUESTS_ADDED,\r\n String(newCMPGuestsCount?.feeGuests),\r\n ''\r\n )}\r\n \r\n \r\n \r\n \r\n {newGuestsWithFeeTotal()}\r\n \r\n \r\n \r\n \r\n \r\n \r\n {COPY.NEW_GUESTS_IN_MAX_OCUPANCY}\r\n \r\n \r\n \r\n >\r\n ) : null}\r\n >\r\n )}\r\n \r\n \r\n \r\n \r\n {guestCountText}\r\n {((addGuestReservation && addGuestReservation.guests?.splash) || hasNewGuests) && (\r\n \r\n )}\r\n \r\n \r\n \r\n \r\n {(promoCode || (addGuestReservation && addGuestReservation?.offerCode)) && (\r\n \r\n \r\n \r\n {`${COPY.SUMMARY_CODE}: ${addGuestReservation?.offerCode ? addGuestReservation?.offerCode : promoCode} ${\r\n COPY.SUMMARY_APPLIED\r\n }`}\r\n \r\n \r\n \r\n \r\n )}\r\n >\r\n );\r\n};\r\n\r\nSuiteDetails.propTypes = propTypes;\r\n\r\nSuiteDetails.defaultProps = {\r\n iconSize: 16\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React, { useEffect, useState } from 'react';\r\nimport ReactHtmlParser from 'react-html-parser';\r\nimport { NOTIFICATION_TYPE } from '../../../../../../utilities/constants';\r\nimport { ALERT_TYPES, Alert } from '../../../../../Alert';\r\nimport { Box, Text } from '../../../../../ui-kit';\r\nimport { SummaryContent } from '../../../Content';\r\n\r\nconst propTypes = {\r\n /** Flag to indicate if the alert is shown */\r\n showNotification: PropTypes.bool,\r\n\r\n /** Message for the notification */\r\n notificationMessage: PropTypes.string,\r\n\r\n /** Type for the notification */\r\n notificationType: PropTypes.string\r\n};\r\n\r\nexport const SummaryAlert = ({ showNotification, notificationMessage, notificationType }) => {\r\n const [renderAlert, setRenderAlert] = useState(showNotification);\r\n\r\n useEffect(() => {\r\n setRenderAlert(showNotification);\r\n }, [showNotification]);\r\n\r\n if (!renderAlert) return null;\r\n\r\n const variant = notificationType === NOTIFICATION_TYPE.failed ? ALERT_TYPES.warning : ALERT_TYPES.success;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n {ReactHtmlParser(notificationMessage)}\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nSummaryAlert.propTypes = propTypes;\r\nSummaryAlert.defaultProps = {\r\n showNotification: false,\r\n notificationType: NOTIFICATION_TYPE.success\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { Text } from '../../../../../ui-kit';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nimport { isValidPrice } from '../../../../../../utilities/cmpPackagesUtils';\r\nimport { SummaryContent } from '../../../Content';\r\n\r\nconst propTypes = {\r\n /** Summary total for the reservation */\r\n total: PropTypes.number.isRequired\r\n};\r\n\r\nexport const Total = ({ total, addGuestReservation }) => {\r\n if (!isValidPrice(Number(total))) return null;\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_TOTAL}\r\n \r\n \r\n \r\n {`$${\r\n addGuestReservation ? addGuestReservation?.costSummary?.total?.toFixed(2) : total.toFixed(2)\r\n }`}\r\n \r\n \r\n >\r\n );\r\n};\r\n\r\nTotal.propTypes = propTypes;\r\n","import React from 'react';\r\n\r\nimport { SummaryContent } from '../../../Content';\r\nimport { AdditionalCharges } from './AdditionalCharges';\r\nimport { Deposit } from './Deposit';\r\nimport { DiscountCharges } from './DiscountCharges';\r\nimport { Header } from './Header';\r\nimport { PackagesList } from './PackagesList';\r\nimport { SuiteDetails } from './SuiteDetails';\r\nimport { SummaryAlert } from './SummaryAlert';\r\nimport { Total } from './Total';\r\n\r\nexport const Content = ({ suppressRate, ...restProps }) => {\r\n return (\r\n \r\n \r\n \r\n {!suppressRate && }\r\n \r\n {!suppressRate && (\r\n <>\r\n \r\n \r\n \r\n \r\n >\r\n )}\r\n \r\n );\r\n};\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { SummaryModal } from '../../Modal';\r\nimport * as COPY from './utilities/copy';\r\n\r\nimport { Content } from './Content';\r\n\r\nconst propTypes = {\r\n /** Flag to indicate if the summary is visible or not */\r\n opened: PropTypes.bool,\r\n /** Function that executes when click on the Close Button */\r\n onClose: PropTypes.func\r\n};\r\n\r\nexport const Summary = ({ opened, onClose, ...restProps }) => {\r\n return (\r\n \r\n \r\n {COPY.SUMMARY_TITLE}\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nSummary.propTypes = propTypes;\r\nSummary.defaultProps = {\r\n opened: false\r\n};\r\n","import { connect } from 'react-redux';\r\nimport { Summary } from './Summary';\r\n\r\nimport {\r\n cmpDataSelector,\r\n getAddGuestReservationObj,\r\n getAdults,\r\n getArrivalDateObject,\r\n getBillableGuest,\r\n getCabanaDeposit,\r\n getDepartureDateObject,\r\n getDepositePaid,\r\n getKids,\r\n getNumberOfNights,\r\n getOffersDiscountApplied,\r\n getParkingFee,\r\n getPointsDiscountApplied,\r\n getPrivateLodgingFee,\r\n getRateType,\r\n getResortFee,\r\n getRoomDeposit,\r\n getSuiteDetails,\r\n getSuppressRate,\r\n getSustainabilityFee,\r\n getTaxesAndFeesForReservation,\r\n getTotalBillAndNonBillGuest,\r\n getTotalRoomRate\r\n} from '../../../../../store/componentStores/ReservationDetailsEntity/reservationDetailsEntity.selectors';\r\nimport {\r\n getAditionalPackagesFromAddApackage,\r\n getDueAtCheckinAmountWithAdditionalPackages,\r\n getSummaryTotalWithAdditionalPackages,\r\n getTaxesAmountWithAdditionalPackages,\r\n packagesWithAmountFromReservationData\r\n} from '../../../../../store/reducers';\r\n\r\nimport { isEmpty } from 'lodash-es';\r\nimport { getTaxAndFeesLabels } from '../../../../../store/componentStores/LodgeConfig/lodgeConfig.selectors';\r\nimport { isArrayEmpty } from '../../../../../utilities/arraysUtils';\r\nimport { getDateMonthDayFormat } from '../../../../../utilities/dates';\r\nimport { getGuestCountLabel } from '../../../../../utilities/guestsUtils';\r\nimport { getTaxesAndFees, getTaxesAndFeesDynamic } from '../../../../../utilities/taxes';\r\n\r\nconst mapStateToProps = state => {\r\n const reservationDetails = cmpDataSelector(state);\r\n const packages = packagesWithAmountFromReservationData(state) ?? [];\r\n const { offerCode } = getSuiteDetails(reservationDetails);\r\n const hasPackages = packages && !isArrayEmpty(packages);\r\n\r\n const taxAndFeeLabels = getTaxAndFeesLabels(state.lodgeConfig);\r\n\r\n const taxesAndFeesPrices = getTaxesAndFeesForReservation(state.entities.reservationDetails);\r\n\r\n const taxesAndFees =\r\n !isEmpty(taxAndFeeLabels) && !isEmpty(taxesAndFeesPrices)\r\n ? getTaxesAndFeesDynamic(taxAndFeeLabels, taxesAndFeesPrices)\r\n : getTaxesAndFees(\r\n getSustainabilityFee(reservationDetails),\r\n getTaxesAmountWithAdditionalPackages(state),\r\n getResortFee(reservationDetails),\r\n getParkingFee(reservationDetails),\r\n getPrivateLodgingFee(reservationDetails)\r\n );\r\n\r\n const addGuestReservation = getAddGuestReservationObj(reservationDetails);\r\n\r\n const voyagerPointsDiscount = getPointsDiscountApplied(reservationDetails);\r\n const offersPointsDiscount = getOffersDiscountApplied(reservationDetails);\r\n const hasDiscountCharges = voyagerPointsDiscount || offersPointsDiscount ? true : false;\r\n\r\n return {\r\n additionalPackages: getAditionalPackagesFromAddApackage(state, true),\r\n checkIn: getDateMonthDayFormat(getArrivalDateObject(reservationDetails)),\r\n checkOut: getDateMonthDayFormat(getDepartureDateObject(reservationDetails)),\r\n depositPaid: getDepositePaid(reservationDetails),\r\n dueAtCheckinAmount: getDueAtCheckinAmountWithAdditionalPackages(state),\r\n guestCountText: getGuestCountLabel(\r\n addGuestReservation ? addGuestReservation?.guests?.adults : getAdults(reservationDetails),\r\n addGuestReservation ? addGuestReservation?.guests?.children?.length : getKids(reservationDetails),\r\n null,\r\n true\r\n ),\r\n addGuestReservation: addGuestReservation,\r\n hasAdditionalCharges: taxesAndFees && taxesAndFees.length > 0,\r\n hasSelectedPackages: hasPackages,\r\n numberOfGuests: getBillableGuest(reservationDetails),\r\n numberOfNights: getNumberOfNights(reservationDetails),\r\n packages: packages,\r\n promoCode: offerCode,\r\n resortLocation: state.currentLodge,\r\n suiteTotal: getTotalRoomRate(reservationDetails),\r\n taxesAndFees: taxesAndFees,\r\n total: getSummaryTotalWithAdditionalPackages(state),\r\n suppressRate: getSuppressRate(reservationDetails),\r\n cabanaDeposit: getCabanaDeposit(reservationDetails),\r\n roomDeposit: getRoomDeposit(reservationDetails),\r\n hasDiscountCharges,\r\n voyagerPointsDiscount,\r\n offersPointsDiscount,\r\n totalBillAndNonBillGuest: getTotalBillAndNonBillGuest(reservationDetails),\r\n rateType: getRateType(reservationDetails)\r\n };\r\n};\r\n\r\nconst ReservationSummary = connect(mapStateToProps, null)(Summary);\r\n\r\nexport { ReservationSummary };\r\n\r\n","import { ASSETS_LOCATIONS, getAssetsUrl } from '../../../utilities/constants';\r\nexport const TIMER_MODAL_CONTENT_IMAGES = {\r\n CLOSE: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'close.svg'),\r\n BOOKING_EXPIRED: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'booking-expired.svg'),\r\n BOOKING_ABOUT_TO_EXPIRED: getAssetsUrl(ASSETS_LOCATIONS.SVG, 'booking-about-to-expires.svg')\r\n};\r\n","export function addMinutes(date, minutes) {\r\n return new Date(date.getTime() + Number(minutes) * 60000);\r\n}\r\nexport function getTimeRemaining(endtime) {\r\n const total = Date.parse(endtime) - Date.parse(new Date());\r\n const mins = Math.floor((total / 1000 / 60) % 60);\r\n const secs = Math.floor((total / 1000) % 60);\r\n const minutesT = mins < 10 ? '0' + mins : mins;\r\n const secondsT = secs < 10 ? '0' + secs : secs;\r\n return {\r\n total,\r\n minutesT,\r\n secondsT\r\n };\r\n}\r\n","import colors from '../themes/colors';\r\n\r\nexport const VARIANTS = {\r\n YELLOW: {\r\n color: colors.deepLakeBlue[100],\r\n background: colors.digitalYellowOrange[100],\r\n borderColor: colors.digitalYellowOrange[100]\r\n },\r\n DARK: {\r\n color: colors.snowMountainGrey[50],\r\n background: colors.deepLakeBlue[100],\r\n borderColor: colors.deepLakeBlue[100]\r\n },\r\n GREEN: {\r\n color: colors.snowMountainGrey[50],\r\n background: colors.deepForestGreen[100],\r\n borderColor: colors.deepForestGreen[100]\r\n },\r\n LIGHT: {\r\n color: colors.deepLakeBlue[100],\r\n background: colors.kiddiePoolBlue[50],\r\n borderColor: colors.kiddiePoolBlue[50]\r\n },\r\n BLACK: {\r\n color: colors.pureWhite[0],\r\n background: colors.nightSkyBlack[100],\r\n borderColor: colors.nightSkyBlack[100]\r\n },\r\n RED: {\r\n color: colors.pureWhite[0],\r\n background: colors.errorOrange,\r\n borderColor: colors.errorOrange\r\n },\r\n BLUE: {\r\n color: colors.pureWhite[0],\r\n background: colors.preciousStoneBlue[100],\r\n borderColor: colors.preciousStoneBlue[100]\r\n },\r\n LIGHT_BLUE: {\r\n color: colors.deepLakeBlue[100],\r\n background: colors.kiddiePoolBlue[100],\r\n borderColor: colors.kiddiePoolBlue[100]\r\n },\r\n FOCUS_BLUE: {\r\n color: colors.pureWhite[0],\r\n background: colors.focusBlue,\r\n borderColor: colors.focusBlue\r\n },\r\n DEEP_ORANGE_100: {\r\n color: colors.pureWhite[0],\r\n background: colors.deepOrange[100],\r\n borderColor: colors.deepOrange[100]\r\n },\r\n SUCCESS_GREEN: {\r\n color: colors.pureWhite[0],\r\n background: colors.successGreen,\r\n borderColor: colors.successGreen\r\n },\r\n YELLOW_WHITE_FONT: {\r\n color: colors.pureWhite[0],\r\n background: colors.digitalYellowOrange[100],\r\n borderColor: colors.digitalYellowOrange[100]\r\n },\r\n BLACK_WHITE_BORDER: {\r\n color: colors.pureWhite[0],\r\n background: colors.nightSkyBlack[100],\r\n borderColor: colors.pureWhite[0]\r\n }\r\n};\r\n","import styled, { css } from 'styled-components';\r\nimport Text from '../Text';\r\nimport theme from '../themes/theme';\r\n\r\nexport const StyledBadge = styled(Text)`\r\n border-radius: ${({ borderRadius }) => (borderRadius ? borderRadius : theme.radii[1] + 'px')};\r\n border: ${({ borderColor }) => `1px solid ${borderColor}`};\r\n text-align: center;\r\n ${({ width }) => (width ? width + ';' : null)}\r\n white-space: nowrap;\r\n font-family: ${theme.fonts.quaternary};\r\n font-weight: bold;\r\n\r\n display: inline-block;\r\n\r\n ${({ size }) => {\r\n switch (size) {\r\n case 'small':\r\n return css`\r\n font-size: ${theme.fontSizes[9]}px;\r\n line-height: 14px;\r\n padding: 1px 8px;\r\n `;\r\n case 'large':\r\n return css`\r\n font-size: ${theme.fontSizes[0]}px;\r\n line-height: 18px;\r\n padding: 1px 8px;\r\n `;\r\n default:\r\n return css`\r\n padding: 0 2px;\r\n font-size: ${theme.fontSizes[9]}px;\r\n line-height: 14px;\r\n `;\r\n }\r\n }}\r\n`;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { VARIANTS } from './constants';\r\nimport { StyledBadge } from './styles';\r\n\r\nconst SIZES = {\r\n SMALL: 'small',\r\n LARGE: 'large'\r\n};\r\n\r\n/** Default Badge/Tag component */\r\nconst Badge = ({\r\n children,\r\n variant,\r\n className,\r\n customColorBg,\r\n customColorText,\r\n borderRadius,\r\n width,\r\n customColorBorder,\r\n size,\r\n caps = true,\r\n // This component allows to pass any other prop to the styled component of Text\r\n ...restProps\r\n}) => {\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nBadge.defaultProps = {\r\n variant: VARIANTS.YELLOW,\r\n className: null\r\n};\r\n\r\nBadge.VARIANTS = VARIANTS;\r\nBadge.SIZES = SIZES;\r\n\r\nBadge.propTypes = {\r\n /** Variant defines a set of styling such as color, bg, border */\r\n variant: PropTypes.shape({\r\n color: PropTypes.string.isRequired,\r\n background: PropTypes.string.isRequired,\r\n borderColor: PropTypes.string.isRequired\r\n }),\r\n /** Children allows to render anything inside the Badge */\r\n children: PropTypes.node,\r\n /** ClassName property to allow styled components to apply styling */\r\n className: PropTypes.string,\r\n /** Custom color for the background */\r\n customColorBg: PropTypes.string,\r\n /** Custom color for the text */\r\n customColorText: PropTypes.string,\r\n /** Custom color for the border */\r\n customColorBorder: PropTypes.string,\r\n /** Boolean to define if the text is uppercase defaults to true */\r\n caps: PropTypes.bool\r\n};\r\n\r\nexport default Badge;\r\n","import Badge from './Badge';\r\n\r\nexport default Badge;\r\n","import { LocalStorageKeys } from '../utilities/storageUtils';\r\nimport { RECOMMENDED_FOR_YOU, IS_CLASSES } from './constants';\r\n\r\nexport const getInteractionsUserId = () => {\r\n const interactionsUserId = localStorage.getItem(LocalStorageKeys.InteractionsUserId);\r\n\r\n return interactionsUserId ? interactionsUserId : null;\r\n};\r\n\r\nexport const renderInteractionsAtributes = (suiteFlags, interactionsData) => {\r\n let attributes = {};\r\n\r\n const isRecommended = suiteFlags?.includes(RECOMMENDED_FOR_YOU);\r\n\r\n if (isRecommended && interactionsData) {\r\n attributes['data-sfis-recommended'] = true;\r\n attributes['data-is-campaignId'] = interactionsData.campaignId;\r\n attributes['data-is-experienceId'] = interactionsData.experienceId;\r\n attributes['data-is-userGroup'] = interactionsData.userGroup;\r\n }\r\n attributes['className'] = IS_CLASSES.suiteContainer;\r\n return attributes;\r\n};\r\n","import { initializeState } from '../../../utilities/storageUtils';\r\nimport preCheckInActionTypes from './preCheckIn.types';\r\n\r\nexport const PRE_CHECK_IN_STEP = {\r\n SUMMARY: 'SUMMARY',\r\n DINING: 'DINING',\r\n ATTRACTIONS: 'ATTRACTIONS',\r\n ADVENTURE_PASS: 'ADVENTURE_PASS',\r\n TRANSITION: 'TRANSITION'\r\n};\r\n\r\nconst INITIAL_STATE = {\r\n preCheckInStep: PRE_CHECK_IN_STEP.SUMMARY,\r\n addedPackagesFailed: 0,\r\n addedPackages: [],\r\n virdeeRedirectionFailed: 0\r\n};\r\n\r\nconst preCheckInReducer = (state, action) => {\r\n state = initializeState(state, INITIAL_STATE);\r\n\r\n switch (action.type) {\r\n // Get Resort Locations SUCCESS\r\n case preCheckInActionTypes.UPDATE_PRE_CHECK_IN_STEP:\r\n return {\r\n ...state,\r\n preCheckInStep: action.step\r\n };\r\n case preCheckInActionTypes.UPDATE_PRE_CHECK_IN_ADDED_PACKAGES_FAILED:\r\n return {\r\n ...state,\r\n addedPackagesFailed: ++state.addedPackagesFailed\r\n };\r\n case preCheckInActionTypes.RESET_PRE_CHECK_IN_ADDED_PACKAGES_FAILED:\r\n return {\r\n ...state,\r\n addedPackagesFailed: 0\r\n };\r\n case preCheckInActionTypes.UPDATE_PRE_CHECK_IN_NEW_PACKAGES:\r\n return {\r\n ...state,\r\n addedPackages: action.packages\r\n };\r\n case preCheckInActionTypes.UPDATE_PRE_CHECK_IN_VIRDEE_REDIRECTION_FAILED:\r\n return {\r\n ...state,\r\n virdeeRedirectionFailed: ++state.virdeeRedirectionFailed\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport default preCheckInReducer;\r\n","import React from 'react'\n\nconst CarouselChevronLeftThinIcon = ({\n size,\n color,\n ...props\n}) => (\n \n)\n\nCarouselChevronLeftThinIcon.displayName = 'CarouselChevronLeftThinIcon'\n\nCarouselChevronLeftThinIcon.defaultProps = {\n size: 24,\n color: 'currentcolor'\n}\n\nexport default CarouselChevronLeftThinIcon","import styled from 'styled-components';\r\n\r\nexport const CloseButton = styled.button`\r\n position: relative;\r\n left: -15px;\r\n top: 10px;\r\n cursor: pointer;\r\n border: none;\r\n background: transparent;\r\n margin-top: 12px;\r\n`;\r\n\r\nexport const BackButtonWrapper = styled.button`\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n border: none;\r\n margin-left: -6px;\r\n padding: 12px 6px;\r\n background: transparent;\r\n`;\r\n\r\nexport const SuiteDetailInfoCont = styled.div`\r\n max-height: 550px;\r\n overflow-y: auto;\r\n max-width: 50%;\r\n`;\r\n\r\nBackButtonWrapper.displayName = 'BackButtonWrapper';\r\n","export const BACK = 'Back';\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { Absolute, Box, Flex, Text } from '../../ui-kit';\r\nimport Scrollable from '../../ui-kit/Scrollable';\r\nimport CarouselChevronLeftThinIcon from '../../ui-kit/icons/CarouselChevronLeftThin';\r\nimport CloseIcon from '../../ui-kit/icons/Close';\r\nimport theme, { colors } from '../../ui-kit/themes/theme';\r\nimport Modal from '../Modal';\r\nimport { BackButtonWrapper, CloseButton, SuiteDetailInfoCont } from './styles';\r\nimport * as COPY from './utilities/copy';\r\n\r\nconst imgPropType = PropTypes.shape({\r\n alt: PropTypes.string.isRequired,\r\n url: PropTypes.string.isRequired\r\n});\r\n\r\nconst propTypes = {\r\n images: PropTypes.arrayOf(imgPropType),\r\n showModal: PropTypes.bool.isRequired,\r\n onCloseModal: PropTypes.func.isRequired,\r\n children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),\r\n modalHeight: PropTypes.number\r\n};\r\n\r\nconst defaultProps = {\r\n images: [],\r\n children: null,\r\n modalHeight: 440\r\n};\r\n\r\nconst OVERLAY_BACKGROUND_COLOR = 'rgba(251, 252, 249, 0.75)';\r\nconst IMAGE_GAP = 4;\r\n\r\nconst MediaGalleryModal = ({ isFullSize, images, showModal, onCloseModal, children, modalHeight }) => {\r\n const renderImages = () => {\r\n return images?.map((image, index) => (\r\n
0 ? IMAGE_GAP : '0px' }}\r\n />\r\n ));\r\n };\r\n\r\n const renderDefaultContent = () => {\r\n return (\r\n \r\n \r\n onCloseModal(false)} title=\"Close\">\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {renderImages()}\r\n \r\n \r\n {children}\r\n \r\n \r\n );\r\n };\r\n\r\n const renderFullSizeContent = () => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n {COPY.BACK}\r\n \r\n \r\n \r\n {renderImages()}\r\n \r\n \r\n );\r\n };\r\n\r\n const renderContent = () => {\r\n if (isFullSize) {\r\n return renderFullSizeContent();\r\n }\r\n\r\n return renderDefaultContent();\r\n };\r\n\r\n return (\r\n \r\n {renderContent()}\r\n \r\n );\r\n};\r\n\r\nMediaGalleryModal.propTypes = propTypes;\r\nMediaGalleryModal.defaultProps = defaultProps;\r\n\r\nexport default MediaGalleryModal;\r\n","// Profile reducer\r\n\r\nimport profileActionTypes from './profile.types';\r\n\r\nexport const INITIAL_STATE = {\r\n isLoading: false,\r\n isUpdateSuccess: false,\r\n user: {\r\n firstName: '',\r\n lastName: '',\r\n email: '',\r\n gender: '',\r\n street: '',\r\n city: '',\r\n stateProvince: '',\r\n country: '',\r\n zip: '',\r\n phoneNumber: '',\r\n streetLine1: '',\r\n streetLine2: '',\r\n birthdate: '',\r\n password: {\r\n currentPassword: '',\r\n newPassword: ''\r\n },\r\n family: [],\r\n isSocialAccountLogin: false,\r\n isConnectedToFacebook: false,\r\n isConnectedToGoogle: false\r\n }\r\n};\r\n\r\nconst profileReducer = (state = INITIAL_STATE, action) => {\r\n switch (action.type) {\r\n case profileActionTypes.IS_PROFILE_LOADING:\r\n return {\r\n ...state,\r\n isLoading: action.isLoading,\r\n isUpdated: action.isUpdateSuccess\r\n };\r\n case profileActionTypes.GET_PROFILE_USER:\r\n return {\r\n ...state,\r\n isLoading: action.isLoading,\r\n isUpdated: false\r\n };\r\n case profileActionTypes.GET_PROFILE_USER_SUCCESS:\r\n return {\r\n ...state,\r\n isLoading: action.isLoading,\r\n user: action.user,\r\n isUpdated: false\r\n };\r\n case profileActionTypes.GET_PROFILE_USER_ERROR:\r\n return {\r\n ...state,\r\n isLoading: action.isLoading,\r\n user: action.user,\r\n isUpdated: false\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport default profileReducer;\r\n","import React from 'react'\n\nconst PlusThinIcon = ({\n size,\n color,\n ...props\n}) => (\n \n)\n\nPlusThinIcon.displayName = 'PlusThinIcon'\n\nPlusThinIcon.defaultProps = {\n size: 24,\n color: 'currentcolor'\n}\n\nexport default PlusThinIcon","import styled, { css } from 'styled-components';\r\nimport Text from '../Text';\r\nimport theme from '../themes/theme';\r\n\r\nconst getColor = color => theme.colors[color] || color;\r\n\r\nconst spanStyle = ({ underline, color, hoverColor }) => {\r\n const colorFocus = getColor(color);\r\n const colorHover = hoverColor ? getColor(hoverColor) : colorFocus;\r\n\r\n if (!underline)\r\n return css`\r\n text-decoration: none;\r\n > span {\r\n :hover {\r\n background-size: 0 1px, 100% 1px;\r\n color: ${() => colorHover};\r\n }\r\n }\r\n `;\r\n\r\n return css`\r\n > span {\r\n background-size: 100% 1px, 0 1px;\r\n background-position: 100% 100%, 0 100%;\r\n background-repeat: no-repeat;\r\n transition: background-size 200ms linear;\r\n\r\n :hover {\r\n background-size: 0 1px, 100% 1px;\r\n\r\n background-image: linear-gradient(#0000, #0000), linear-gradient(${colorHover}, ${colorHover});\r\n color: ${colorHover};\r\n }\r\n }\r\n `;\r\n};\r\n\r\nexport const TextLikeLink = styled(Text)`\r\n display: inline-flex;\r\n gap: 10px;\r\n background: none;\r\n border: none;\r\n cursor: pointer;\r\n font-weight: ${({ fontWeight }) => fontWeight};\r\n align-items: center;\r\n\r\n ${spanStyle} :hover {\r\n color: ${({ underline, hoverColor, color }) => (hoverColor ? getColor(hoverColor) : getColor(color))};\r\n }\r\n :hover {\r\n text-decoration: none;\r\n }\r\n`;\r\n","export const SELECT_PLACEHOLDER = 'Included *';\r\nexport const SUBTITLE =\r\n 'Select your food and drinks for your special day! On the day of the party, order additional food and drinks through your dedicated server. Ask about options for all ages!';\r\nexport const TITLE = 'Food & Drinks';\r\nexport const MISSING_SELECTION_ERROR = 'At least one item must be selected';\r\nexport const EXTRA_PLACEHOLDER = 'Extra ';\r\nexport const REMOVE_EXTRA = 'Remove ';\r\nexport const FLOATING_MESSAGE_ERROR = 'To continue, please select your pizza and drinks for your party';\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport ReactHtmlParser from 'react-html-parser';\r\nimport { Box, TextLink } from '../../../ui-kit';\r\nimport Text from '../../../ui-kit/Text';\r\nimport AlertSuccessIcon from '../../../ui-kit/icons/AlertSuccessIcon';\r\nimport colors from '../../../ui-kit/themes/colors';\r\nimport { editCopyByReplaceString } from '../../../utilities/copyFunctions';\r\nimport { SummaryContent } from '../Content/SummaryContent';\r\nimport SummaryItem from '../SummaryItem';\r\nimport * as COPY from './utilities/copy';\r\n\r\nconst SimpleSummaryInfo = ({\r\n promoCode,\r\n description,\r\n fullWidthDescription,\r\n productTitle,\r\n price,\r\n navigationText,\r\n onNavigateLinkClick,\r\n includedList\r\n}) => {\r\n return (\r\n \r\n \r\n {productTitle}\r\n \r\n }\r\n rightColumn={\r\n \r\n ${price}\r\n \r\n }\r\n />\r\n {!fullWidthDescription ? (\r\n \r\n {description}\r\n \r\n }\r\n />\r\n ) : (\r\n \r\n {description}\r\n \r\n )}\r\n\r\n {includedList?.map((item, key) => (\r\n \r\n \r\n \r\n {ReactHtmlParser(item)}\r\n \r\n \r\n \r\n \r\n {COPY.SUMMARY_INCLUDED}\r\n \r\n \r\n \r\n ))}\r\n\r\n {navigationText ? (\r\n \r\n {navigationText}\r\n \r\n ) : null}\r\n\r\n {promoCode ? (\r\n \r\n \r\n \r\n {editCopyByReplaceString(COPY.PROMOCODE_APPLIED, promoCode, '')}\r\n \r\n \r\n \r\n \r\n ) : null}\r\n \r\n );\r\n};\r\n\r\nSimpleSummaryInfo.propTypes = {\r\n passTitle: PropTypes.string,\r\n rate: PropTypes.number,\r\n promoCode: PropTypes.string,\r\n dayPassPromoDescription: PropTypes.string,\r\n amountOfDayPasses: PropTypes.number\r\n};\r\n\r\nSimpleSummaryInfo.defaultProps = {\r\n rate: 0.0\r\n};\r\n\r\nexport default SimpleSummaryInfo;\r\n","import { useCallback } from 'react';\r\nimport { waitFor } from '../../utilities/waitFor';\r\n\r\n/**\r\n * This is a simple hook that returns 2 methods, one for simple scroll using scrollIntoView and\r\n * a custmon scroll based on the top.\r\n *\r\n * @param {options}\r\n * ref, behavior, block, inline, delay, custom.yOffset\r\n * @returns { simpleScrollTo, customScrollTo }\r\n *\r\n * Horizontal scroll is pending for more custom options\r\n */\r\nconst useScrollToItem = () => {\r\n const simpleScrollTo = useCallback(async options => {\r\n const { ref, behavior = 'auto', block = 'start', inline, delay } = options;\r\n if (delay) await waitFor(delay);\r\n\r\n ref.current.scrollIntoView({\r\n behavior,\r\n block,\r\n ...(inline && { inline })\r\n });\r\n }, []);\r\n\r\n const customScrollTo = useCallback(async options => {\r\n const { ref, behavior = 'auto', custom, delay } = options;\r\n const yOffset = custom.yOffset;\r\n const element = ref.current;\r\n const y =\r\n element.getBoundingClientRect().top + window.pageYOffset + yOffset;\r\n if (delay) await waitFor(delay);\r\n window.scrollTo({ top: y, behavior });\r\n }, []);\r\n\r\n return { simpleScrollTo, customScrollTo };\r\n};\r\n\r\nexport default useScrollToItem;\r\n","import { useLayoutEffect } from 'react';\r\n\r\nconst useLockBodyScroll = isOpen => {\r\n useLayoutEffect(() => {\r\n if (isOpen) {\r\n document.querySelector('#root')?.removeAttribute('aria-hidden');\r\n document.body.style.overflowY = 'hidden';\r\n }\r\n\r\n return () => (document.body.style.overflowY = 'visible');\r\n }, [isOpen]);\r\n};\r\n\r\nexport default useLockBodyScroll;\r\n","import PropTypes from 'prop-types';\r\nimport React, { useState } from 'react';\r\nimport {\r\n Accordion,\r\n AccordionItem,\r\n AccordionItemButton,\r\n AccordionItemHeading,\r\n AccordionItemState\r\n} from 'react-accessible-accordion';\r\nimport MediaQuery from 'react-responsive';\r\n\r\nimport Absolute from '../../ui-kit/Absolute';\r\nimport { Box, Flex } from '../../ui-kit/index';\r\nimport Relative from '../../ui-kit/Relative';\r\nimport Text from '../../ui-kit/Text';\r\nimport theme from '../../ui-kit/themes/theme';\r\nimport { Wrapper } from '../assets/styles';\r\nimport { SummaryAccordionIcon } from '../assets/SummaryStyles';\r\n\r\nconst SummaryAccordionIconWrapper = ({ size }) => (\r\n \r\n);\r\n\r\nconst DesktopLayout = ({ title, isExpanded }) => (\r\n \r\n \r\n {title}\r\n \r\n \r\n \r\n \r\n \r\n);\r\nconst isDayPass = window.location.pathname.includes('/daypass/');\r\n\r\nconst MobileLayout = ({ title, isOnPaymentPage, total }) => (\r\n \r\n \r\n \r\n {title}:\r\n \r\n \r\n \r\n ${total.toFixed(2)}\r\n \r\n \r\n {isOnPaymentPage || isDayPass ? '(Total)' : '(Subtotal)'}\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n);\r\n\r\nconst SummaryAccordion = ({ children, total, shouldStartCollapsed, onChange, isOnPaymentPage, title }) => {\r\n const [isExpanded, setIsExpanded] = useState(!shouldStartCollapsed);\r\n return (\r\n \r\n {isDesktop => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n {isDesktop ? (\r\n \r\n ) : (\r\n \r\n )}\r\n \r\n \r\n \r\n\r\n \r\n {({ expanded }) => {\r\n setIsExpanded(expanded);\r\n return children({ expanded, isDesktop });\r\n }}\r\n \r\n \r\n \r\n \r\n );\r\n }}\r\n \r\n );\r\n};\r\n\r\nSummaryAccordion.propTypes = {\r\n total: PropTypes.number,\r\n shouldStartCollapsed: PropTypes.bool,\r\n onChange: PropTypes.func,\r\n isOnPaymentPage: PropTypes.bool\r\n};\r\n\r\nSummaryAccordion.defaultProps = {\r\n total: 0,\r\n shouldStartCollapsed: true,\r\n onChange: () => {},\r\n isOnPaymentPage: false\r\n};\r\n\r\nexport default SummaryAccordion;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { COSTSUMMARY_TOOLTIP } from '../../../../../utilities/constants';\r\nimport { Box, Flex, Text, Tooltip } from '../../../../ui-kit';\r\nimport QuestionIcon from '../../../../ui-kit/icons/Question';\r\nimport theme from '../../../../ui-kit/themes/theme';\r\nimport { SummaryContent } from '../../Content';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nconst propTypes = {\r\n hasAdditionalCharges: PropTypes.bool.isRequired,\r\n taxes: PropTypes.number\r\n};\r\n\r\nexport const AdditionalCharges = ({ taxes, sustainabilityFee, parkingFee, resortFee, lodgeOperaCode }) => {\r\n const isExtraLargeScreen = useMediaQuery({\r\n minWidth: theme.breakpoints.xl\r\n });\r\n const sustainabilityToolTip = ['SCOTAZ'];\r\n return (\r\n <>\r\n \r\n {COPY.ADDITIONAL_CHARGES}\r\n \r\n\r\n \r\n {COPY.TAXES}\r\n {`$${taxes.toFixed(2)}`}\r\n \r\n\r\n {sustainabilityFee > 0 ? (\r\n \r\n \r\n {COPY.SUSTAINABILITY_FEE}\r\n {sustainabilityToolTip.includes(lodgeOperaCode) ? (\r\n \r\n (\r\n \r\n \r\n \r\n )}\r\n tooltipContent={() => {COSTSUMMARY_TOOLTIP.sustainabilityFee}}\r\n />\r\n \r\n ) : null}\r\n \r\n {`$${sustainabilityFee.toFixed(2)}`}\r\n \r\n ) : null}\r\n\r\n {parkingFee > 0 ? (\r\n \r\n {COPY.PARKING_FEE}\r\n {`$${parkingFee.toFixed(2)}`}\r\n \r\n ) : null}\r\n\r\n {resortFee > 0 ? (\r\n \r\n \r\n {COPY.AMENITY_FEE}\r\n \r\n (\r\n \r\n \r\n \r\n )}\r\n tooltipContent={() => {COPY.TOOLTIP_COPY}}\r\n />\r\n \r\n \r\n {`$${resortFee.toFixed(2)}`}\r\n \r\n ) : null}\r\n\r\n \r\n >\r\n );\r\n};\r\n\r\nAdditionalCharges.propTypes = propTypes;\r\n\r\nAdditionalCharges.defaultProps = {\r\n taxes: 0\r\n};\r\n","import styled, { css } from 'styled-components';\r\nimport { Box } from '../../../../ui-kit';\r\n\r\nexport const ItemListWrapper = styled(Box)`\r\n ${({ allowPackageUpdate }) => {\r\n if (!allowPackageUpdate) {\r\n return css`\r\n & > div {\r\n margin-top: 0;\r\n margin-bottom: 4px;\r\n }\r\n `;\r\n }\r\n }}\r\n`;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { FLOW_NAVIGATION_ACTIONS } from '../../../../../flows/DynamicFlow/utilities/constants';\r\nimport * as ADDONS_COPY from '../../../../../pages/BirthdayPartyAddOns/utilities/copy';\r\nimport * as FOOD_DRINKS_COPY from '../../../../../pages/BirthdayPartyFoodAndDrinks/utilities/copy';\r\nimport { isArrayEmpty } from '../../../../../utilities/arraysUtils';\r\nimport { getCurrencyCodeText } from '../../../../../utilities/planUtils';\r\nimport SelectPackageQuantity from '../../../../Packages/SelectPackageQuantity';\r\nimport { Box, Text, TextLink } from '../../../../ui-kit';\r\nimport { editCopyByReplaceString } from '../../../../utilities/copyFunctions';\r\nimport { SummaryContent } from '../../Content';\r\nimport { ItemListWrapper } from '../assets/styles';\r\nimport * as COPY from '../utilities/copy';\r\n\r\nconst propTypes = {\r\n /** String date object with the checkin date */\r\n checkinDateSelection: PropTypes.string.isRequired,\r\n\r\n /** String date object with the checkout date */\r\n checkoutDateSelection: PropTypes.string.isRequired,\r\n\r\n /** Currenty selected packages */\r\n currentSelectedPackages: PropTypes.arrayOf(\r\n PropTypes.shape({\r\n packageCode: PropTypes.string,\r\n packageName: PropTypes.string,\r\n currencyCode: PropTypes.string,\r\n quantity: PropTypes.number,\r\n amount: PropTypes.number,\r\n isAdjustment: PropTypes.bool,\r\n showQuantitySelect: PropTypes.bool\r\n })\r\n ),\r\n\r\n /** Number of guests for the reservation */\r\n numberOfGuests: PropTypes.number.isRequired,\r\n\r\n /** Flag to indicate the property is in Niagara */\r\n isNiagaraProperty: PropTypes.bool,\r\n\r\n /** Function to update the package quantity */\r\n upsertPackage: PropTypes.func,\r\n\r\n /** Funtion to delete a package */\r\n deletePackage: PropTypes.func,\r\n\r\n /** Flag to indicate if the reservation has selected packages */\r\n hasSelectedPackages: PropTypes.bool\r\n};\r\n\r\nconst getPackagePriceDisplay = packageItem =>\r\n `${(parseInt(packageItem.quantity || 1) * packageItem.amount).toFixed(2)}`;\r\n\r\nconst getBirthdayScreenSlug = summarySection => {\r\n switch (summarySection) {\r\n case ADDONS_COPY.PAGE_TITLE:\r\n return '/packages-addons';\r\n case FOOD_DRINKS_COPY.TITLE:\r\n return '/food-drinks';\r\n default:\r\n return null;\r\n }\r\n};\r\n\r\nconst ListOfPackages = ({\r\n currentSelectedPackages,\r\n deletePackage,\r\n isNiagaraProperty,\r\n checkinDateSelection,\r\n checkoutDateSelection,\r\n numberOfGuests,\r\n updatePackageQuantity,\r\n allowPackageUpdate,\r\n isBirthdayPackage,\r\n isFoodAndDrinks\r\n}) => {\r\n return (\r\n <>\r\n \r\n {currentSelectedPackages.map(item =>\r\n !item.isAdjustment ? (\r\n \r\n \r\n {item.quantity ? `${item.quantity} ` : ''} {item.packageTitle || item.title}\r\n \r\n {allowPackageUpdate && item.quantity && !item.packageType?.includes('dining') ? (\r\n \r\n \r\n \r\n ) : null}\r\n {allowPackageUpdate ? (\r\n deletePackage(item)}>{COPY.REMOVE}\r\n ) : null}\r\n\r\n \r\n {isBirthdayPackage && isFoodAndDrinks && !item.isExtra\r\n ? COPY.SUMMARY_INCLUDED\r\n : `$${getPackagePriceDisplay(item)} ${getCurrencyCodeText(item.currencyCode) || ''}`}\r\n \r\n \r\n ) : null\r\n )}\r\n \r\n >\r\n );\r\n};\r\n\r\nconst PackagesList = ({\r\n checkinDateSelection,\r\n checkoutDateSelection,\r\n currentSelectedPackages,\r\n numberOfGuests,\r\n isNiagaraProperty,\r\n upsertPackage,\r\n deletePackage,\r\n splitPackagesByTabName,\r\n allowPackageUpdate,\r\n triggerDynamicStepNavigation,\r\n allowPackagesListLink\r\n}) => {\r\n function updatePackageQuantity(e, packageItem) {\r\n upsertPackage({ ...packageItem, quantity: e.target.value });\r\n }\r\n\r\n let groupedPackagesByTabName = null;\r\n\r\n if (splitPackagesByTabName) {\r\n let groupedPackagesBySectionAndType = Object.groupBy(\r\n currentSelectedPackages,\r\n ({ summarySection }) => summarySection\r\n );\r\n\r\n Object.keys(groupedPackagesBySectionAndType).forEach(summarySectionKey => {\r\n groupedPackagesBySectionAndType[summarySectionKey] = Object.groupBy(\r\n groupedPackagesBySectionAndType[summarySectionKey],\r\n ({ summarySectionType }) => summarySectionType\r\n );\r\n });\r\n\r\n groupedPackagesByTabName = groupedPackagesBySectionAndType;\r\n }\r\n\r\n if (currentSelectedPackages && isArrayEmpty(currentSelectedPackages)) return null;\r\n\r\n return (\r\n <>\r\n {splitPackagesByTabName && groupedPackagesByTabName ? (\r\n <>\r\n {Object.entries(groupedPackagesByTabName).map(([summarySection, pkgsList]) => {\r\n return (\r\n <>\r\n \r\n {summarySection}\r\n \r\n {Object.keys(pkgsList).map(list => (\r\n \r\n ))}\r\n\r\n {allowPackagesListLink ? (\r\n {\r\n !window.location.pathname.includes(getBirthdayScreenSlug(summarySection)) &&\r\n triggerDynamicStepNavigation(\r\n FLOW_NAVIGATION_ACTIONS.FLOW_TRIGGER_STEP_BY_SLUG,\r\n getBirthdayScreenSlug(summarySection)\r\n );\r\n }}\r\n mt={2}>\r\n {editCopyByReplaceString(COPY.BIRTHDAY_LINK_TEXT, summarySection, '')}\r\n \r\n ) : null}\r\n \r\n >\r\n );\r\n })}\r\n >\r\n ) : (\r\n <>\r\n \r\n \r\n >\r\n )}\r\n >\r\n );\r\n};\r\n\r\nPackagesList.propTypes = propTypes;\r\n\r\nPackagesList.defaultProps = {\r\n isNiagaraProperty: false,\r\n hasSelectedPackages: false\r\n};\r\n\r\nexport default PackagesList;\r\n","import React from 'react';\r\nimport { Box, Text } from '../../../ui-kit';\r\nimport { editCopyByReplaceString } from '../../../utilities/copyFunctions';\r\nimport { Divider } from '../Content/styles';\r\nimport SummaryItem from '../SummaryItem';\r\nimport * as COPY from './utilities/copy';\r\n\r\nconst TextWrapperDueToday = ({ children }) => {\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nconst TextWrapperDueBeforeParty = ({ children }) => {\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nconst SimpleSummaryDue = ({ dueToday, dueBeforeParty, remainingBalanceDueDate }) => {\r\n if (!dueToday && !dueBeforeParty) return null;\r\n return (\r\n \r\n \r\n {COPY.PARTY_DUE_TODAY}}\r\n rightColumn={${dueToday.toFixed(2)}}\r\n />\r\n \r\n {dueBeforeParty ? COPY.PARTY_72_REFUND_PARTY_DISCLAIMER : COPY.PARTY_NON_REFUND_DISCLAIMER}\r\n \r\n {dueBeforeParty ? (\r\n <>\r\n \r\n {editCopyByReplaceString(COPY.PARTY_DUE_BEFORE_PARTY, remainingBalanceDueDate, '')}\r\n \r\n }\r\n rightColumn={${dueBeforeParty.toFixed(2)}}\r\n />\r\n \r\n {dueBeforeParty ? COPY.PARTY_REFUND_DISCLAIMER : COPY.PARTY_NON_REFUND_DISCLAIMER}\r\n \r\n >\r\n ) : null}\r\n \r\n );\r\n};\r\n\r\nexport default SimpleSummaryDue;\r\n","import React from 'react';\r\nimport { Box, Text } from '../../../ui-kit';\r\nimport theme from '../../../ui-kit/themes/theme';\r\n\r\nconst SimpleSummaryParkingFeeWarning = ({ bookingSummaryParkingFee }) => {\r\n return (\r\n <>\r\n {bookingSummaryParkingFee ? (\r\n \r\n \r\n {bookingSummaryParkingFee}\r\n \r\n \r\n ) : null}\r\n >\r\n );\r\n};\r\n\r\nexport default SimpleSummaryParkingFeeWarning;\r\n","import React from 'react';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { useHistory } from 'react-router-dom';\r\nimport { FLOW_NAVIGATION_ACTIONS } from '../../../../flows/DynamicFlow/utilities/constants';\r\nimport theme from '../../../ui-kit/themes/theme';\r\nimport { SummaryContent } from '../Content';\r\nimport { Divider } from '../Content/styles';\r\nimport SummaryAccordion from '../SummaryAccordion';\r\nimport { AdditionalCharges } from './Content/AdditionalCharges';\r\nimport PackagesList from './Content/PackagesList';\r\nimport SimpleSummaryDue from './SimpleSummaryDue';\r\nimport SimpleSummaryFooter from './SimpleSummaryFooter';\r\nimport SimpleSummaryHeader from './SimpleSummaryHeader';\r\nimport SimpleSummaryInfo from './SimpleSummaryInfo';\r\nimport SimpleSummaryParkingFeeWarning from './SimpleSummaryParkingFeeWarning';\r\n\r\nexport const SimpleSummary = ({\r\n bookingSummaryParkingFee,\r\n operaCode,\r\n onChange,\r\n title,\r\n shouldStartCollapsed,\r\n deletePackage,\r\n upsertPackage,\r\n total,\r\n productTitle,\r\n promoCode,\r\n fullWidthDescription,\r\n description,\r\n price,\r\n navigationText,\r\n packagesList,\r\n taxes,\r\n showDueToday,\r\n dueToday,\r\n dueBeforeParty,\r\n sustainabilityFee,\r\n parkingFee,\r\n resortFee,\r\n leftTitle,\r\n leftContent,\r\n rightTitle,\r\n rightContent,\r\n onPaymentPage,\r\n includedList,\r\n remainingBalanceDueDate,\r\n splitPackagesByTabName,\r\n allowPackageUpdate,\r\n triggerDynamicStepNavigation,\r\n allowPackagesListLink\r\n}) => {\r\n const isMobile = useMediaQuery({\r\n query: `(max-width: ${theme.breakpoints.md})`\r\n });\r\n const history = useHistory();\r\n const onInfoLinkClick = () => {\r\n triggerDynamicStepNavigation(FLOW_NAVIGATION_ACTIONS.FLOW_TRIGGER_FIRST_STEP);\r\n if (isMobile) {\r\n history.push({\r\n search: '?openEditMobile=true'\r\n });\r\n }\r\n };\r\n\r\n return (\r\n \r\n {({ expanded, isDesktop }) => {\r\n return (\r\n <>\r\n {expanded ? (\r\n \r\n \r\n \r\n \r\n \r\n {onPaymentPage ? (\r\n \r\n ) : null}\r\n \r\n ) : null}\r\n {expanded || isDesktop ? : null}\r\n {expanded && bookingSummaryParkingFee ? (\r\n \r\n ) : null}\r\n {expanded && showDueToday ? (\r\n \r\n ) : null}\r\n >\r\n );\r\n }}\r\n \r\n );\r\n};\r\n\r\nexport default SimpleSummary;\r\n","import { useState, useEffect } from 'react';\r\nimport useWindowEventListener from './useWindowEventListener';\r\n\r\n// Correct sizing (viewport) on mobile view\r\nconst useCorrectedHeight = height => {\r\n const [correctedHeight, setHeight] = useState();\r\n\r\n const handleViewportUnitsMobile = () => {\r\n const vh = window.innerHeight * 0.01;\r\n setHeight(height * vh);\r\n };\r\n\r\n useEffect(handleViewportUnitsMobile, [height]);\r\n\r\n useWindowEventListener('resize', handleViewportUnitsMobile);\r\n\r\n return correctedHeight;\r\n};\r\n\r\nexport default useCorrectedHeight;\r\n","import { useEffect } from 'react';\r\n\r\nexport default function useWindowEventListener(\r\n event,\r\n handler,\r\n passive = false\r\n) {\r\n useEffect(() => {\r\n // initiate the event handler\r\n window.addEventListener(event, handler, passive);\r\n\r\n // this will clean up the event every time the component is re-rendered\r\n return function cleanup() {\r\n window.removeEventListener(event, handler);\r\n };\r\n });\r\n}\r\n","import React from 'react'\n\nconst ArrowCaretLeftIcon = ({\n size,\n color,\n ...props\n}) => (\n \n)\n\nArrowCaretLeftIcon.displayName = 'ArrowCaretLeftIcon'\n\nArrowCaretLeftIcon.defaultProps = {\n size: 24,\n color: 'currentcolor'\n}\n\nexport default ArrowCaretLeftIcon","import BlockUi from 'react-block-ui';\r\nimport styled from 'styled-components';\r\nimport { themeGet } from 'styled-system';\r\n\r\nimport Box from '../../ui-kit/Box';\r\nimport Flex from '../../ui-kit/Flex';\r\n\r\nexport const ModalContainer = styled(Box)`\r\n padding: ${({ innerPadding }) => `${innerPadding}px`};\r\n ${({ hasTopPadding }) => !hasTopPadding && `padding-top: 0px`};\r\n`;\r\n\r\nexport const OutsideContainer = styled(Flex)`\r\n width: 100%;\r\n`;\r\n\r\nexport const CloseButton = styled.button`\r\n cursor: pointer;\r\n color: inherit;\r\n border: none;\r\n background: transparent;\r\n position: absolute;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n ${({ closeBtnHorizonPosValue }) => 'top:' + closeBtnHorizonPosValue};\r\n ${({ closeBtnPosition, closeBtnVertPosValue }) =>\r\n closeBtnPosition === 'left' ? 'left:' + closeBtnVertPosValue : 'right:' + closeBtnVertPosValue};\r\n\r\n svg {\r\n ${({ closeBtnColor }) => closeBtnColor && 'fill:' + closeBtnColor};\r\n }\r\n\r\n &:hover {\r\n text-decoration: underline;\r\n }\r\n`;\r\n\r\nexport const BackButton = styled(CloseButton)`\r\n position: absolute;\r\n ${({ backButtonVertPosValue }) => 'top:' + backButtonVertPosValue + '!important;'}\r\n left: ${themeGet('space.4')}px;\r\n right: unset;\r\n`;\r\n\r\nexport const HeadingContainer = styled(Flex)`\r\n background-color: ${props => props.backgroundColor};\r\n justify-content: center;\r\n position: relative;\r\n padding: ${props => (props.topPadding ? '32px 0 0' : '0')};\r\n\r\n ${({ hasTitle, theme }) =>\r\n hasTitle &&\r\n `\r\n border: 0 solid ${theme.colors.snowMountainGrey[100]};\r\n border-bottom-width: 0.5px;\r\n `}\r\n`;\r\n\r\nexport const CustomBlockUi = styled(BlockUi)`\r\n overflow: hidden;\r\n border-radius: ${props => props.containerBorderRadius || `${themeGet('radii.5')}px}`};\r\n`;\r\n","import PropTypes from 'prop-types';\r\n\r\nimport Heading from '../../ui-kit/Heading';\r\nimport Text from '../../ui-kit/Text';\r\nimport ArrowCaretLeft from '../../ui-kit/icons/ArrowCaretLeft';\r\nimport CloseIcon from '../../ui-kit/icons/Close';\r\nimport theme from '../../ui-kit/themes/theme';\r\n\r\nimport { BackButton, CloseButton, HeadingContainer } from './styles';\r\n\r\nconst ModalHeader = ({\r\n title,\r\n fontSize,\r\n lineHeight,\r\n onCloseModal,\r\n backButton,\r\n backButtonSize,\r\n backButtonVertPosValue,\r\n onBackButtonClick,\r\n closeButton,\r\n titleColor,\r\n closeBtnPosition,\r\n closeBtnSize,\r\n closeBtnVertPosValue,\r\n closeBtnHorizonPosValue,\r\n closeBtnColor,\r\n topPadding,\r\n headerBackgroundColor,\r\n width\r\n}) => {\r\n return (\r\n \r\n {title && (\r\n \r\n \r\n {title}\r\n \r\n \r\n )}\r\n {closeButton && (\r\n \r\n \r\n \r\n )}\r\n {backButton && (\r\n \r\n \r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\nModalHeader.defaultProps = {\r\n title: '',\r\n onCloseModal: null,\r\n backButton: false,\r\n onBackButtonClick: null,\r\n titleColor: 'preciousStoneBlue.100',\r\n backgroundColor: 'pureWhite.0'\r\n};\r\n\r\nModalHeader.propTypes = {\r\n title: PropTypes.string,\r\n onCloseModal: PropTypes.func,\r\n backButton: PropTypes.bool,\r\n onBackButtonClick: PropTypes.func,\r\n titleColor: PropTypes.string\r\n};\r\n\r\nexport default ModalHeader;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport Modal from 'react-modal';\r\nimport styled from 'styled-components';\r\n\r\nimport Scrollable from '../../ui-kit/Scrollable';\r\nimport theme from '../../ui-kit/themes/theme';\r\nimport useCorrectedHeight from '../../utilities/useCorrectedHeight';\r\n\r\nimport { isInIframe } from '../../../utilities/customEventsHelpers';\r\nimport ModalHeader from './ModalHeader';\r\nimport { CustomBlockUi, ModalContainer, OutsideContainer } from './styles';\r\n\r\nconst DrawerModal = props => {\r\n const {\r\n children,\r\n isOpen,\r\n closeButton,\r\n onRequestClose,\r\n backButton,\r\n backButtonSize,\r\n backButtonVertPosValue,\r\n onBackButtonClick,\r\n title,\r\n isBlocking,\r\n width,\r\n fontSize,\r\n lineHeight,\r\n className,\r\n innerPadding,\r\n titleColor,\r\n closeBtnPosition,\r\n closeBtnSize,\r\n closeBtnVertPosValue,\r\n closeBtnHorizonPosValue,\r\n closeBtnColor,\r\n borderRadius,\r\n hasTopPadding,\r\n headerBackgroundColor,\r\n titleWidth,\r\n containerBorderRadius,\r\n ...otherProps\r\n } = props;\r\n\r\n const contentClassName = `${className}__content`;\r\n const overlayClassName = `${className}__overlay`;\r\n\r\n const maxHeight = useCorrectedHeight(98);\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n {React.cloneElement(children, otherProps)}\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst StyledDrawerModal = styled(DrawerModal).attrs({\r\n className: 'DrawerModal'\r\n})`\r\n .DrawerModal__overlay {\r\n z-index: ${({ zIndex }) => {\r\n if (zIndex) return zIndex;\r\n\r\n return theme.zIndex.auth;\r\n }};\r\n display: flex;\r\n justify-content: center;\r\n align-items: flex-end;\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n ${isInIframe ? '' : 'background-color: rgba(57, 84, 118, 0.35);'};\r\n opacity: 0;\r\n transition: opacity 0.25s ease-in-out;\r\n }\r\n\r\n .ReactModal__Overlay--after-open {\r\n opacity: 1;\r\n z-index: ${theme.zIndex.modal};\r\n transition: all 0.25s ease-in-out;\r\n }\r\n\r\n .ReactModal__Overlay--before-close {\r\n opacity: 0;\r\n }\r\n\r\n .DrawerModal__content {\r\n border-top-right-radius: ${theme.radii[5]}px;\r\n border-top-left-radius: ${theme.radii[5]}px;\r\n ${({ borderRadius }) =>\r\n 'border-top-right-radius:' + borderRadius + '; border-top-left-radius:' + borderRadius + ';'};\r\n border-bottom-right-radius: 0;\r\n border-bottom-left-radius: 0;\r\n background-color: ${({ backGroundColor }) => (backGroundColor ? backGroundColor : theme.colors.pureWhite[0])};\r\n max-height: 100%;\r\n overflow: hidden;\r\n padding: 0;\r\n transform: translateY(100vh);\r\n transition: transform 0.25s ease-in-out;\r\n width: 100%;\r\n\r\n ${theme.mediaQueries.md} {\r\n > div {\r\n padding-right: 0px !important;\r\n }\r\n }\r\n }\r\n\r\n .ReactModal__Content--after-open {\r\n transform: translateY(0);\r\n }\r\n\r\n .ReactModal__Content--before-close {\r\n transform: translateY(100vh);\r\n }\r\n\r\n ${theme.mediaQueries.md} {\r\n .DrawerModal__overlay {\r\n align-items: center;\r\n }\r\n\r\n .DrawerModal__content {\r\n ${({ borderRadius }) => 'border-radius:' + borderRadius};\r\n transform: scale(0.8);\r\n transition: transform 0.25s ease-in-out;\r\n width: ${({ width }) => `${width}px`};\r\n }\r\n\r\n .ReactModal__Content--after-open {\r\n transform: scale(1);\r\n }\r\n\r\n .ReactModal__Content--before-close {\r\n transform: scale(0.8);\r\n }\r\n }\r\n`;\r\n\r\nStyledDrawerModal.defaultProps = {\r\n closeBtnPosition: 'right',\r\n closeBtnSize: 16,\r\n closeBtnVertPosValue: '32px',\r\n closeBtnHorizonPosValue: '0px',\r\n closeBtnColor: 'inherit',\r\n borderRadius: `${theme.radii[5]}px`,\r\n hasTopPadding: true,\r\n children: null,\r\n isVisible: false,\r\n onCloseComplete: null,\r\n backButton: false,\r\n onBackButtonClick: null,\r\n title: '',\r\n fontSize: null,\r\n lineHeight: null,\r\n isBlocking: false,\r\n width: 480,\r\n closeButton: true,\r\n innerPadding: theme.space[4]\r\n};\r\n\r\nStyledDrawerModal.propTypes = {\r\n closeBtnPosition: PropTypes.string,\r\n closeBtnSize: PropTypes.number,\r\n closeBtnVertPosValue: PropTypes.string,\r\n closeBtnHorizonPosValue: PropTypes.string,\r\n closeBtnColor: PropTypes.string,\r\n borderRadius: PropTypes.string,\r\n hasTopPadding: PropTypes.bool,\r\n children: PropTypes.node,\r\n isVisible: PropTypes.bool,\r\n onCloseModal: PropTypes.func,\r\n backButton: PropTypes.bool,\r\n onBackButtonClick: PropTypes.func,\r\n title: PropTypes.string,\r\n lineHeight: PropTypes.string,\r\n fontSize: PropTypes.string,\r\n isBlocking: PropTypes.bool,\r\n width: PropTypes.number,\r\n closeButton: PropTypes.bool,\r\n innerPadding: PropTypes.oneOfType([PropTypes.number, PropTypes.string])\r\n};\r\n\r\nexport default StyledDrawerModal;\r\n","import styled, { css } from 'styled-components';\r\nimport { themeGet } from 'styled-system';\r\nimport { Accordion, AccordionItemButton } from 'react-accessible-accordion';\r\nimport { Flex } from '../index';\r\nimport { Link } from 'react-router-dom';\r\nimport { Text } from '../../ui-kit';\r\n\r\nconst itemStyles = css`\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n text-decoration: none;\r\n padding: ${themeGet('space.8')}px ${themeGet('space.2')}px;\r\n font-size: ${themeGet('fontSizes.1')}px;\r\n font-weight: ${themeGet('fontWeights.medium')};\r\n margin-bottom: ${themeGet('space.3')}px;\r\n border-radius: 0 100px 100px 0;\r\n transition: background-color 0.2s;\r\n\r\n :after {\r\n width: 0;\r\n }\r\n`;\r\n\r\nconst accordionItemStyles = css`\r\n border-radius: 0;\r\n margin-bottom: ${themeGet('space.2')}px;\r\n`;\r\n\r\nconst accordionNotActive = css`\r\n background-color: ${themeGet('colors.snowMountainGrey.50')};\r\n color: ${themeGet('colors.deepLakeBlue.50')};\r\n\r\n :before {\r\n background-color: ${themeGet('colors.deepLakeBlue.100')};\r\n }\r\n`;\r\n\r\nconst beforeDecorationStyles = css`\r\n :before {\r\n content: '';\r\n display: inline-block;\r\n width: ${themeGet('space.1')}px;\r\n min-width: ${themeGet('space.1')}px;\r\n height: 12px;\r\n margin-right: ${themeGet('space.2')}px;\r\n border-radius: 2px;\r\n }\r\n`;\r\n\r\nconst activeItem = css`\r\n background-color: ${themeGet('colors.deepLakeBlue.100')};\r\n color: ${themeGet('colors.snowMountainGrey.50')};\r\n\r\n :before {\r\n background-color: ${themeGet('colors.snowMountainGrey.50')};\r\n }\r\n`;\r\n\r\nconst notActiveItem = css`\r\n color: ${themeGet('colors.deepLakeBlue.50')};\r\n\r\n :before {\r\n background-color: ${themeGet('colors.deepLakeBlue.20')};\r\n }\r\n\r\n :hover {\r\n background-color: ${themeGet('colors.snowMountainGrey.50')};\r\n }\r\n`;\r\n\r\nexport const NavigationMenuWrapper = styled(Flex)`\r\n flex-direction: column;\r\n\r\n .accordion__panel {\r\n padding: 20px;\r\n animation: fadein 0.35s ease-in;\r\n }\r\n\r\n @keyframes fadein {\r\n 0% {\r\n opacity: 0;\r\n }\r\n\r\n 100% {\r\n opacity: 1;\r\n }\r\n }\r\n`;\r\n\r\nexport const NavigationItemWrapper = styled(({ isActive, isAccordion, ...rest }) => )`\r\n ${itemStyles}\r\n ${beforeDecorationStyles}\r\n ${({ isActive }) => (isActive ? activeItem : notActiveItem)}\r\n ${({ isAccordion }) => isAccordion && accordionItemStyles}\r\n ${({ isActive, isAccordion }) => isActive && isAccordion && accordionNotActive}\r\n`;\r\n\r\nexport const StyledAccordionItemButton = styled(AccordionItemButton)`\r\n ${itemStyles}\r\n ${activeItem}\r\n ${accordionItemStyles}\r\n ${beforeDecorationStyles}\r\n position: relative;\r\n\r\n &[aria-expanded=true]::after {\r\n transform: rotate(-135deg);\r\n margin-bottom: -4px;\r\n }\r\n\r\n :after {\r\n display: inline-block;\r\n position: absolute;\r\n right: 20px;\r\n content: '';\r\n height: 10px;\r\n width: 10px;\r\n margin-bottom: 4px;\r\n border-bottom: 2px solid currentColor;\r\n border-right: 2px solid currentColor;\r\n transform: rotate(45deg);\r\n transition: transform 0.2s, margin 0.2s;\r\n }\r\n`;\r\n\r\nexport const StyledAccordion = styled(({ optionsNumber, ...rest }) => )`\r\n .accordion__panel {\r\n transition: all 0.3s ease-in-out;\r\n overflow: hidden;\r\n ${({ optionsNumber }) => `max-height: ${optionsNumber * 60}px`}\r\n\r\n &[hidden] {\r\n display: block;\r\n max-height: 0;\r\n }\r\n }\r\n`;\r\n\r\nexport const SelectedOption = styled(Text)`\r\n font-size: ${themeGet('fontSizes.7')}px;\r\n font-weight: ${themeGet('fontWeights.bold')};\r\n\r\n @media screen and (max-width: 32em) {\r\n font-size: ${themeGet('fontSizes.1')}px;\r\n color: ${themeGet('colors.pureWhite.0')};\r\n }\r\n`;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { AccordionItem, AccordionItemHeading, AccordionItemPanel } from 'react-accessible-accordion';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { useLocation } from 'react-router-dom';\r\nimport { propTypes as StyledSystemPropTypes } from 'styled-system';\r\nimport routes from '../../../routes';\r\nimport { compareUrlPathnames } from '../../../utilities/navigationUtils';\r\nimport Text from '../Text';\r\nimport theme from '../themes/theme';\r\nimport {\r\n NavigationItemWrapper,\r\n NavigationMenuWrapper,\r\n SelectedOption,\r\n StyledAccordion,\r\n StyledAccordionItemButton\r\n} from './styles';\r\n\r\nconst MODES = {\r\n ACCORDION: 'accordion',\r\n LIST: 'list'\r\n};\r\n\r\nconst propTypes = {\r\n ...StyledSystemPropTypes.space,\r\n /** Array of available routes objects*/\r\n options: PropTypes.arrayOf(\r\n PropTypes.shape({\r\n route: PropTypes.string.isRequired,\r\n title: PropTypes.string.isRequired\r\n }).isRequired\r\n ).isRequired,\r\n /** Callback function triggered when the user selects an option */\r\n onChange: PropTypes.func,\r\n /** Display mode, by default it shows an accordion for mobile res and list for desktop */\r\n mode: PropTypes.oneOf(Object.values(MODES)),\r\n showLoyalty: PropTypes.bool,\r\n isReferralEnabled: PropTypes.bool\r\n};\r\n\r\nconst defaultProps = {\r\n width: '',\r\n onChange: () => {},\r\n mode: null,\r\n showLoyalty: false,\r\n isReferralEnabled: false\r\n};\r\n\r\nconst NavigationMenu = ({ width, options, onChange, mode, showLoyalty, isReferralEnabled }) => {\r\n const location = useLocation();\r\n\r\n if (showLoyalty && isReferralEnabled) {\r\n //RAF=Refer A Friend\r\n let hasRAF = options.find(option => option.title === 'Refer a Friend');\r\n !hasRAF && options.splice(1, 0, { route: routes.referAFriend, title: 'Refer a Friend' });\r\n }\r\n\r\n const activeOption = options.find(option => compareUrlPathnames(option.route, location.pathname)) || options[0];\r\n\r\n const isDesktop = useMediaQuery({ minWidth: theme.breakpoints.xl });\r\n\r\n const isAccordion = mode ? mode === MODES.ACCORDION : !isDesktop;\r\n\r\n const isActive = option => compareUrlPathnames(option.route, activeOption.route);\r\n\r\n const handleSelect = option => {\r\n if (activeOption !== option) {\r\n onChange(option);\r\n }\r\n };\r\n\r\n const renderOptionsList = () => (\r\n \r\n {options.map(option => (\r\n handleSelect(option)}\r\n isActive={isActive(option)}\r\n isAccordion={isAccordion}\r\n to={option.route}\r\n key={option.route}>\r\n {option.title}\r\n \r\n ))}\r\n \r\n );\r\n\r\n if (!isAccordion) {\r\n return renderOptionsList();\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n {activeOption.title}\r\n \r\n \r\n {renderOptionsList()}\r\n \r\n \r\n );\r\n};\r\n\r\nNavigationMenu.MODES = MODES;\r\nNavigationMenu.propTypes = propTypes;\r\nNavigationMenu.defaultProps = defaultProps;\r\n\r\nexport default NavigationMenu;\r\n","import NavigationMenu from './NavigationMenu';\r\n\r\nexport default NavigationMenu;\r\n","import Box from '../ui-kit/Box';\r\nimport Text from '../ui-kit/Text';\r\nimport styled from 'styled-components';\r\nimport theme from '../ui-kit/themes/theme';\r\n\r\nexport const NotificationMessage = styled(Text)`\r\n display: flex;\r\n align-items: center;\r\n font-family: ${theme.fontSecondary};\r\n font-size: 10px;\r\n font-weight: 500;\r\n padding: 8px 16px;\r\n min-height: 40px;\r\n line-height: 16px;\r\n color: ${theme.colors.nightSkyBlack[80]};\r\n margin: 0;\r\n\r\n svg {\r\n margin-right: 10px;\r\n }\r\n}\r\n`;\r\n\r\nexport const NotificationBox = styled(Box)`\r\n position: absolute;\r\n top: 16px;\r\n width: calc(100% - 40px);\r\n margin-left: 20px;\r\n border-radius: 10px;\r\n min-height: 40px;\r\n background: ${theme.colors.deepForestGreen[10]};\r\n`;\r\n\r\nexport const BoxIcon = styled(Box)`\r\n height: 20px;\r\n`;\r\n","import { PropTypes } from 'prop-types';\r\nimport React from 'react';\r\nimport ReactHtmlParser from 'react-html-parser';\r\nimport AlertSuccessIcon from '../../components/ui-kit/icons/AlertSuccessIcon';\r\nimport { Box } from '../ui-kit';\r\nimport colors from '../ui-kit/themes/colors';\r\nimport theme from '../ui-kit/themes/theme';\r\nimport { BoxIcon, NotificationBox, NotificationMessage } from './style';\r\n\r\n/**\r\n * Notification banner to show error or success messages.\r\n * @param {Object} props\r\n * @param {boolean} props.type - type of notification to be shown.\r\n * @param {function} props.message - Message to be shown on banner.\r\n */\r\n\r\nconst NOTIFICATION_COLORS = {\r\n default: theme.colors.nightSkyBlack[60],\r\n warning: theme.colors.digitalYellowOrange,\r\n success: theme.colors.successGreen,\r\n error: theme.colors.errorOrange\r\n};\r\n\r\nconst getColor = color => NOTIFICATION_COLORS[color] || NOTIFICATION_COLORS.default;\r\n\r\nconst NotificationBanner = ({ type, message }) => {\r\n return (\r\n \r\n \r\n {type === 'success' ? (\r\n \r\n \r\n \r\n ) : null}\r\n {ReactHtmlParser(message)}\r\n \r\n \r\n );\r\n};\r\n\r\nNotificationBanner.propTypes = {\r\n type: PropTypes.string,\r\n message: PropTypes.string\r\n};\r\n\r\nexport default NotificationBanner;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport NotificationBanner from '../../../NotificationBanner';\r\nimport Flex from '../../../ui-kit/Flex';\r\nimport Text from '../../../ui-kit/Text';\r\nimport { DayPassContainer } from '../../assets/styles';\r\n\r\nconst SimpleSummaryHeader = ({\r\n notificationType,\r\n notificationMessage,\r\n showNotification,\r\n leftTitle = 'LT',\r\n leftContent = 'LC',\r\n rightTitle = 'RT',\r\n rightContent = 'RC'\r\n}) => {\r\n return (\r\n \r\n {showNotification ? (\r\n \r\n ) : null}\r\n\r\n \r\n \r\n {leftTitle}\r\n \r\n \r\n {leftContent}\r\n \r\n \r\n \r\n \r\n {rightTitle}\r\n \r\n \r\n {rightContent}\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nSimpleSummaryHeader.propTypes = {\r\n validOn: PropTypes.string,\r\n amountOfDayPasses: PropTypes.number\r\n};\r\n\r\nexport default SimpleSummaryHeader;\r\n","import axios from 'axios';\r\nimport Lottie from 'lottie-web';\r\nimport PropTypes from 'prop-types';\r\nimport React, { useCallback, useEffect, useRef } from 'react';\r\n\r\nimport Box from '../Box';\r\n\r\nconst propTypes = {\r\n /** Animation path */\r\n src: PropTypes.string,\r\n /** Object with the exported animation data. Use this when file is hosted locally */\r\n animationData: PropTypes.object,\r\n /** If the animation should loop or not */\r\n loop: PropTypes.bool,\r\n /** Play the animation as soon it is ready */\r\n autoplay: PropTypes.bool,\r\n /** Animation name for future reference */\r\n name: PropTypes.string,\r\n /** Called when the animation finishes loading */\r\n onLoad: PropTypes.func,\r\n /** Aria label to improve accessibility */\r\n label: PropTypes.string\r\n};\r\n\r\nconst defaultProps = {\r\n src: null,\r\n animationData: null,\r\n loop: true,\r\n autoplay: true,\r\n name: null,\r\n onLoad: null,\r\n label: null\r\n};\r\n\r\n/**\r\n `Animation` component is used to render `JSON`animations and still have control\r\n over them. It is a `lottie-web` wrapper, for more details check their documentation \r\n https://github.com/airbnb/lottie-web\r\n*/\r\nconst Animation = ({ src, onLoad, animationData, loop, autoplay, name, label, ...otherProps }) => {\r\n const container = useRef();\r\n\r\n const getJSON = useCallback(async () => {\r\n const res = await axios.get(src).catch(function(error) {\r\n console.log('ANIMATION ERROR - failed to load animation content from', src);\r\n if (error.response) {\r\n // The request was made and the server responded with a status code\r\n // that falls out of the range of 2xx\r\n console.log('Data', error.response.data);\r\n console.log('Status', error.response.status);\r\n console.log('Headers', error.response.headers);\r\n } else if (error.request) {\r\n // The request was made but no response was received\r\n // `error.request` is an instance of XMLHttpRequest in the browser and an instance of\r\n // http.ClientRequest in node.js\r\n console.log('Request', error.request);\r\n } else {\r\n // Something happened in setting up the request that triggered an Error\r\n console.log('Message', error.message);\r\n }\r\n return false;\r\n });\r\n\r\n return await res.data;\r\n }, [src]);\r\n\r\n const loadAnimation = useCallback(async () => {\r\n try {\r\n const data = src ? (await getJSON()) || animationData : animationData;\r\n\r\n const animation = Lottie.loadAnimation({\r\n container: container.current,\r\n animationData: data,\r\n loop,\r\n autoplay,\r\n name\r\n });\r\n\r\n if (onLoad) {\r\n onLoad(animation);\r\n }\r\n\r\n return animation;\r\n } catch (error) {\r\n console.error('[Error] Animation - Failed to load animation', error);\r\n }\r\n }, [animationData, loop, autoplay, name, onLoad, getJSON, src]);\r\n\r\n useEffect(() => {\r\n loadAnimation();\r\n }, [loadAnimation]);\r\n\r\n return ;\r\n};\r\n\r\nAnimation.defaultProps = defaultProps;\r\n\r\nAnimation.propTypes = propTypes;\r\n\r\nexport default Animation;\r\n","import Animation from './Animation';\r\n\r\nexport default Animation;\r\n","import React from 'react';\r\nimport Flex from '../../ui-kit/Flex';\r\n\r\nconst SummaryItem = ({ leftColumn, centerColumn, rightColumn, bold, highlight, ...props }) => (\r\n \r\n {leftColumn}\r\n \r\n {centerColumn}\r\n \r\n \r\n {rightColumn}\r\n \r\n \r\n);\r\n\r\nexport default SummaryItem;\r\n","import PropTypes from 'prop-types';\r\nimport React from 'react';\r\nimport { Box } from '../../../ui-kit';\r\nimport { BoldText } from '../../assets/SummaryStyles';\r\nimport SummaryItem from '../SummaryItemPackage';\r\nimport * as COPY from './utilities/copy';\r\n\r\nconst SimpleSummaryFooter = ({ total, onPaymentPage }) => {\r\n return (\r\n \r\n \r\n {onPaymentPage ? COPY.TOTAL : COPY.SUBTOTAL}\r\n \r\n }\r\n rightColumn={\r\n \r\n ${isNaN(total) ? 0.0 : total.toFixed(2)}\r\n \r\n }\r\n />\r\n \r\n );\r\n};\r\n\r\nSimpleSummaryFooter.propTypes = {\r\n total: PropTypes.number\r\n};\r\n\r\nSimpleSummaryFooter.defaultProps = {\r\n total: 0.0\r\n};\r\n\r\nexport default SimpleSummaryFooter;\r\n","export const specialRequestOptions = [\r\n {\r\n label: 'Close to elevator',\r\n value: 'EC'\r\n },\r\n {\r\n label: 'Close to the Waterpark',\r\n value: 'CWP'\r\n },\r\n {\r\n label: 'Far from Elevator',\r\n value: 'EF'\r\n },\r\n {\r\n label: 'Lobby Level',\r\n value: 'LL'\r\n },\r\n {\r\n label: \"Pack 'n Play\",\r\n value: 'CRB'\r\n },\r\n {\r\n label: 'Top Floor',\r\n value: 'TF'\r\n },\r\n {\r\n label: 'Other',\r\n value: 'OTHR'\r\n }\r\n];\r\n","// Reservations Reducer\r\n\r\nimport { initializeState } from '../../../utilities/storageUtils';\r\nimport reservationsActionTypes from './reservations.types';\r\n\r\nconst INITIAL_STATE = {\r\n tempUserInfo: {},\r\n confirmedReservation: {},\r\n createdReservation: {},\r\n reservationList: [],\r\n upcomingReservationList: [],\r\n pastReservationList: [],\r\n canceledReservationList: [],\r\n isLoading: false,\r\n isInitialLoading: false,\r\n requestFailed: false,\r\n requestHasFinished: false,\r\n reservationUser: undefined,\r\n errorMessage: null,\r\n errorType: '',\r\n status: '',\r\n cancellationHasFailed: false,\r\n lastNameFindReservationById: '',\r\n reservationKeyFindReservationById: { key: '', reservationId: '' }\r\n};\r\n\r\n/**\r\n *\r\n * IMPORTANT!!!\r\n * The validation of reservation.isCabana is required to avoid showing cabanas reservations\r\n * this was implemented by story 30448, this is just a FE fix, the fix needs to be completed\r\n * on the BE and will be implemented on another story\r\n */\r\nexport function reservationListHandler(reservationData) {\r\n const reservedReservations = reservationData['RESERVED'] ? reservationData['RESERVED'] : [];\r\n const changedReservations = reservationData['CHANGED'] ? reservationData['CHANGED'] : [];\r\n const noShowReservations = reservationData['NO_SHOW'] ? reservationData['NO_SHOW'] : [];\r\n const checkedOutReservations = reservationData['CHECKEDOUT'] ? reservationData['CHECKEDOUT'] : [];\r\n const filteredReservations = {\r\n upcomingReservationList: [...reservedReservations, ...changedReservations] ?? [],\r\n pastReservationList: [...noShowReservations, ...checkedOutReservations] ?? [],\r\n canceledReservationList: reservationData['CANCELED'] ?? []\r\n };\r\n return filteredReservations;\r\n}\r\n\r\nconst reservationsReducer = (state, action) => {\r\n state = initializeState(state, INITIAL_STATE);\r\n\r\n // Get Book information reducers\r\n switch (action.type) {\r\n case reservationsActionTypes.SET_RESERVATION_LAST_NAME_FIND_BY_ID:\r\n return {\r\n ...state,\r\n lastNameFindReservationById: action.lastName\r\n };\r\n case reservationsActionTypes.CREATE_RESERVATION_SUCCESS:\r\n return {\r\n ...state,\r\n tempUserInfo: {\r\n ...state.tempUserInfo,\r\n customer: {\r\n ...state.tempUserInfo.customer\r\n },\r\n details: {\r\n ...state.tempUserInfo.details\r\n },\r\n address: {\r\n ...state.tempUserInfo.address\r\n },\r\n payment: {\r\n ...state.tempUserInfo.payment\r\n }\r\n },\r\n confirmedReservation: {\r\n ...state.confirmedReservation\r\n },\r\n createdReservation: action.createdReservation,\r\n reservationList: [...state.reservationList],\r\n upcomingReservationList: [...state.upcomingReservationList],\r\n pastReservationList: [...state.pastReservationList],\r\n canceledReservationList: [...state.canceledReservationList]\r\n };\r\n case reservationsActionTypes.CREATE_RESERVATION_LOADING:\r\n return {\r\n ...state,\r\n tempUserInfo: {\r\n ...state.tempUserInfo,\r\n customer: {\r\n ...state.tempUserInfo.customer\r\n },\r\n details: {\r\n ...state.tempUserInfo.details\r\n },\r\n address: {\r\n ...state.tempUserInfo.address\r\n },\r\n payment: {\r\n ...state.tempUserInfo.payment\r\n }\r\n },\r\n confirmedReservation: {\r\n ...state.confirmedReservation\r\n },\r\n createdReservation: {\r\n ...state.createdReservation,\r\n reservation: {\r\n ...state.createdReservation.reservation\r\n }\r\n },\r\n reservationList: [...state.reservationList],\r\n upcomingReservationList: [...state.upcomingReservationList],\r\n pastReservationList: [...state.pastReservationList],\r\n canceledReservationList: [...state.canceledReservationList],\r\n isLoading: action.isLoading\r\n };\r\n case reservationsActionTypes.CREATE_RESERVATION_ERROR:\r\n return {\r\n ...state,\r\n tempUserInfo: {\r\n ...state.tempUserInfo,\r\n customer: {\r\n ...state.tempUserInfo.customer\r\n },\r\n details: {\r\n ...state.tempUserInfo.details\r\n },\r\n address: {\r\n ...state.tempUserInfo.address\r\n },\r\n payment: {\r\n ...state.tempUserInfo.payment\r\n }\r\n },\r\n confirmedReservation: {\r\n ...state.confirmedReservation\r\n },\r\n createdReservation: {\r\n ...state.createdReservation,\r\n reservation: {\r\n ...state.createdReservation.reservation\r\n }\r\n },\r\n reservationList: [...state.reservationList],\r\n upcomingReservationList: [...state.upcomingReservationList],\r\n pastReservationList: [...state.pastReservationList],\r\n canceledReservationList: [...state.canceledReservationList],\r\n errorMessage: action.errorMessage,\r\n errorType: action.errorType\r\n };\r\n case reservationsActionTypes.GET_RESERVATION_BY_ID_SUCCESS:\r\n return {\r\n ...state,\r\n tempUserInfo: {\r\n ...state.tempUserInfo,\r\n customer: {\r\n ...state.tempUserInfo.customer\r\n },\r\n details: {\r\n ...state.tempUserInfo.details\r\n },\r\n address: {\r\n ...state.tempUserInfo.address\r\n },\r\n payment: {\r\n ...state.tempUserInfo.payment\r\n }\r\n },\r\n confirmedReservation: action.confirmedReservation,\r\n createdReservation: {\r\n ...state.createdReservation,\r\n reservation: {\r\n ...state.createdReservation.reservation\r\n }\r\n },\r\n reservationList: [...state.reservationList],\r\n upcomingReservationList: [...state.upcomingReservationList],\r\n pastReservationList: [...state.pastReservationList],\r\n canceledReservationList: [...state.canceledReservationList],\r\n requestFailed: false,\r\n isLoading: false,\r\n errorMessage: null\r\n };\r\n\r\n case reservationsActionTypes.GET_RESERVATION_BY_ID_ERROR:\r\n return {\r\n ...state,\r\n tempUserInfo: {\r\n ...state.tempUserInfo,\r\n customer: {\r\n ...state.tempUserInfo.customer\r\n },\r\n details: {\r\n ...state.tempUserInfo.details\r\n },\r\n address: {\r\n ...state.tempUserInfo.address\r\n },\r\n payment: {\r\n ...state.tempUserInfo.payment\r\n }\r\n },\r\n confirmedReservation: {\r\n ...INITIAL_STATE.confirmedReservation\r\n },\r\n createdReservation: {\r\n ...state.createdReservation,\r\n reservation: {\r\n ...state.createdReservation.reservation\r\n }\r\n },\r\n reservationList: [...state.reservationList],\r\n upcomingReservationList: [...state.upcomingReservationList],\r\n pastReservationList: [...state.pastReservationList],\r\n canceledReservationList: [...state.canceledReservationList],\r\n isLoading: false\r\n };\r\n\r\n case reservationsActionTypes.GET_RESERVATION_BY_ID_FINISH:\r\n return {\r\n ...state,\r\n tempUserInfo: {\r\n ...state.tempUserInfo,\r\n customer: {\r\n ...state.tempUserInfo.customer\r\n },\r\n details: {\r\n ...state.tempUserInfo.details\r\n },\r\n address: {\r\n ...state.tempUserInfo.address\r\n },\r\n payment: {\r\n ...state.tempUserInfo.payment\r\n }\r\n },\r\n confirmedReservation: {\r\n ...state.confirmedReservation\r\n },\r\n createdReservation: {\r\n ...state.createdReservation\r\n },\r\n reservationList: [...state.reservationList],\r\n upcomingReservationList: [...state.upcomingReservationList],\r\n pastReservationList: [...state.pastReservationList],\r\n canceledReservationList: [...state.canceledReservationList],\r\n requestHasFinished: action.requestHasFinished\r\n };\r\n\r\n // Reservation item request succeded\r\n case reservationsActionTypes.GET_RESERVATION_INFO_SUCCESS:\r\n return {\r\n ...state,\r\n confirmedReservation: action.confirmedReservation,\r\n reservationList: action.reservationList,\r\n upcomingReservationList: action.upcomingReservationList,\r\n pastReservationList: action.pastReservationList,\r\n canceledReservationList: action.canceledReservationList,\r\n reservationUser: action.reservationUser,\r\n requestFailed: false,\r\n isLoading: false,\r\n isInitialLoading: false,\r\n errorMessage: null\r\n };\r\n // The request is currently running\r\n case reservationsActionTypes.GET_RESERVATION_INFO_LOADING:\r\n return {\r\n ...state,\r\n isLoading: action.isLoading\r\n };\r\n // Reservation item request failed\r\n case reservationsActionTypes.GET_RESERVATION_INFO_ERROR:\r\n return {\r\n ...state,\r\n reservationList: action.reservationList,\r\n upcomingReservationList: [],\r\n pastReservationList: [],\r\n canceledReservationList: [],\r\n reservationUser: action.reservationUser,\r\n requestFailed: action.requestFailed,\r\n errorMessage: action.errorMessage,\r\n isLoading: false,\r\n isInitialLoading: false\r\n };\r\n // Reservation item request finished\r\n case reservationsActionTypes.GET_RESERVATION_INFO_FINISH:\r\n const getValidValue = (value, key) => (value !== undefined ? value : state[key]);\r\n\r\n const newIsLoadingValue = getValidValue(action.isLoading, 'isLoading');\r\n const newErrorMessageValue = getValidValue(action.errorMessage, 'errorMessage');\r\n const newRequestFailedValue = getValidValue(action.requestFailed, 'requestFailed');\r\n\r\n return {\r\n ...state,\r\n requestHasFinished: action.requestHasFinished,\r\n isLoading: newIsLoadingValue,\r\n errorMessage: newErrorMessageValue,\r\n requestFailed: newRequestFailedValue\r\n };\r\n\r\n case reservationsActionTypes.CREATE_RESERVATION_TEMP_USER:\r\n return {\r\n ...state,\r\n tempUserInfo: {\r\n ...action.tempUserInfo\r\n },\r\n confirmedReservation: {\r\n ...state.confirmedReservation\r\n },\r\n createdReservation: {\r\n ...state.createdReservation\r\n },\r\n reservationList: [...state.reservationList],\r\n upcomingReservationList: [...state.upcomingReservationList],\r\n pastReservationList: [...state.pastReservationList],\r\n canceledReservationList: [...state.canceledReservationList]\r\n };\r\n // Action to clear the errors\r\n case reservationsActionTypes.CLEAR_RESERVATION_ERROR:\r\n return {\r\n ...state,\r\n requestFailed: false,\r\n errorMessage: null,\r\n errorType: ''\r\n };\r\n\r\n // Action to set initial loading.\r\n case reservationsActionTypes.GET_RESERVATION_INITIAL_INFO_LOADING:\r\n return {\r\n ...state,\r\n isInitialLoading: action.isInitialLoading\r\n };\r\n\r\n case reservationsActionTypes.SET_RESERVATION_KEY_FIND_RESERVATION_BY_ID:\r\n return {\r\n ...state,\r\n reservationKeyFindReservationById: action.reservationIdKey\r\n };\r\n\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport default reservationsReducer;\r\n","export const PAGE_TITLE = 'add-ons';\r\n","import React from 'react'\n\nconst CloseCircleIcon = ({\n size,\n color,\n ...props\n}) => (\n \n)\n\nCloseCircleIcon.displayName = 'CloseCircleIcon'\n\nCloseCircleIcon.defaultProps = {\n size: 24,\n color: 'currentcolor'\n}\n\nexport default CloseCircleIcon","const isAuthorMode = () => {\r\n const bodyClassList = document.body.classList;\r\n return bodyClassList.contains('edit') || bodyClassList.contains('preview');\r\n};\r\nexport default isAuthorMode;\r\n","// Default location used by LocationPicker when no location is mentioned on URL\r\nexport const defaultLocation = {\r\n location: 'WILLVA',\r\n url: 'williamsburg'\r\n};\r\n","var map = {\n\t\"./OfferNotFound.svg\": 1085,\n\t\"./OffersNormal.svg\": 1086,\n\t\"./OffersNormalWhite.svg\": 1087,\n\t\"./OffersOpen.svg\": 1088,\n\t\"./ac.svg\": 1089,\n\t\"./accessible.svg\": 1090,\n\t\"./accessibleIcon.svg\": 1091,\n\t\"./airplane.svg\": 1092,\n\t\"./alertErrorIcon.svg\": 1093,\n\t\"./alertInfoIcon.svg\": 1094,\n\t\"./alertOfferIcon.svg\": 1095,\n\t\"./alertSuccessIcon.svg\": 1096,\n\t\"./arrival.svg\": 1097,\n\t\"./arrowCaretLeft.svg\": 1098,\n\t\"./arrowDown.svg\": 1099,\n\t\"./arrowDownRounded.svg\": 1100,\n\t\"./arrowDownThin.svg\": 1101,\n\t\"./arrowLeft.svg\": 1102,\n\t\"./arrowRight.svg\": 1103,\n\t\"./arrowRightThin.svg\": 1104,\n\t\"./arrowUp.svg\": 1105,\n\t\"./attention.svg\": 1106,\n\t\"./attentionWarning.svg\": 1107,\n\t\"./attractionsBlue.svg\": 1108,\n\t\"./attractionsIcon.svg\": 1109,\n\t\"./attractionsWhite.svg\": 1110,\n\t\"./automatic.svg\": 1111,\n\t\"./bag.svg\": 1112,\n\t\"./beach.svg\": 1113,\n\t\"./bed.svg\": 1114,\n\t\"./bedAkela.svg\": 1115,\n\t\"./birthdayBlue.svg\": 1116,\n\t\"./birthdayIcon.svg\": 1117,\n\t\"./birthdayWhite.svg\": 1118,\n\t\"./blueQuestion.svg\": 1119,\n\t\"./boxChecked.svg\": 1120,\n\t\"./boxEmpty.svg\": 1121,\n\t\"./boxMinus.svg\": 1122,\n\t\"./boxPlus.svg\": 1123,\n\t\"./breakfast.svg\": 1124,\n\t\"./build.svg\": 1125,\n\t\"./business.svg\": 1126,\n\t\"./cabin.svg\": 1127,\n\t\"./cake.svg\": 1128,\n\t\"./calendar-icon.svg\": 1129,\n\t\"./calendar-outline.svg\": 1130,\n\t\"./calendar.svg\": 1131,\n\t\"./calendarPicker.svg\": 1132,\n\t\"./carCircle.svg\": 1133,\n\t\"./carDoor.svg\": 1134,\n\t\"./carouselChevronLeft.svg\": 1135,\n\t\"./carouselChevronLeftThin.svg\": 1136,\n\t\"./carouselChevronRight.svg\": 1137,\n\t\"./carouselChevronRigthThin.svg\": 1138,\n\t\"./carriage.svg\": 1139,\n\t\"./cars.svg\": 1140,\n\t\"./casino.svg\": 1141,\n\t\"./chairs.svg\": 1142,\n\t\"./chart.svg\": 1143,\n\t\"./chat.svg\": 1144,\n\t\"./check.svg\": 1145,\n\t\"./checkedIcon.svg\": 1146,\n\t\"./chevron-thin-right.svg\": 1147,\n\t\"./chevronDown.svg\": 1148,\n\t\"./chevronLeft.svg\": 1149,\n\t\"./chevronRight.svg\": 1150,\n\t\"./chevronThinLeft.svg\": 1151,\n\t\"./chevronUp.svg\": 1152,\n\t\"./chevronUpThin.svg\": 1153,\n\t\"./circleMinus.svg\": 1154,\n\t\"./circlePlus.svg\": 1155,\n\t\"./cityView.svg\": 1156,\n\t\"./clock.svg\": 1157,\n\t\"./close-icon.svg\": 1158,\n\t\"./close.svg\": 1159,\n\t\"./closeCircle.svg\": 1160,\n\t\"./closeIcon.svg\": 1161,\n\t\"./closeThin.svg\": 1162,\n\t\"./closedEye.svg\": 1163,\n\t\"./cloud.svg\": 1164,\n\t\"./collisionCoverage.svg\": 1165,\n\t\"./condoIcon.svg\": 1166,\n\t\"./coupon.svg\": 1167,\n\t\"./credit-card-outline.svg\": 1168,\n\t\"./creditCard.svg\": 1169,\n\t\"./cruises.svg\": 1170,\n\t\"./delete.svg\": 1171,\n\t\"./departure.svg\": 1172,\n\t\"./devices.svg\": 1173,\n\t\"./directions.svg\": 1174,\n\t\"./discount.svg\": 1175,\n\t\"./document.svg\": 1176,\n\t\"./dollar.svg\": 1177,\n\t\"./dollarCircle.svg\": 1178,\n\t\"./doubleArrowUpIcon.svg\": 1179,\n\t\"./doubleOccupancy.svg\": 1180,\n\t\"./earlyBird.svg\": 1181,\n\t\"./edit.svg\": 1182,\n\t\"./electric.svg\": 1183,\n\t\"./email.svg\": 1184,\n\t\"./emoticon.svg\": 1185,\n\t\"./event.svg\": 1186,\n\t\"./eventAvailable.svg\": 1187,\n\t\"./eventBusy.svg\": 1188,\n\t\"./facebook.svg\": 1189,\n\t\"./facebookBtn.svg\": 1190,\n\t\"./facebookIcon.svg\": 1191,\n\t\"./familyBlue.svg\": 1192,\n\t\"./familyIcon.svg\": 1193,\n\t\"./familyWhite.svg\": 1194,\n\t\"./fan.svg\": 1195,\n\t\"./favoriteHotel.svg\": 1196,\n\t\"./filter.svg\": 1197,\n\t\"./fitness.svg\": 1198,\n\t\"./flame.svg\": 1199,\n\t\"./flightCircle.svg\": 1200,\n\t\"./flightCoverage.svg\": 1201,\n\t\"./flights.svg\": 1202,\n\t\"./forbidden.svg\": 1203,\n\t\"./freeCancellation.svg\": 1204,\n\t\"./fridge.svg\": 1205,\n\t\"./front-desk.svg\": 1206,\n\t\"./fullSofaBed.svg\": 1207,\n\t\"./gallery.svg\": 1208,\n\t\"./gas.svg\": 1209,\n\t\"./globe.svg\": 1210,\n\t\"./golf.svg\": 1211,\n\t\"./googleBtn.svg\": 1212,\n\t\"./gps.svg\": 1213,\n\t\"./graph.svg\": 1214,\n\t\"./grid-gallery.svg\": 1215,\n\t\"./grid.svg\": 1216,\n\t\"./guestScore.svg\": 1217,\n\t\"./guests.svg\": 1218,\n\t\"./hd Tv.svg\": 1219,\n\t\"./help.svg\": 1220,\n\t\"./history.svg\": 1221,\n\t\"./home.svg\": 1222,\n\t\"./hotelCircle.svg\": 1223,\n\t\"./hotels.svg\": 1224,\n\t\"./house.svg\": 1225,\n\t\"./hybrid.svg\": 1226,\n\t\"./icons-32-bottles-water.svg\": 1227,\n\t\"./icons-32-deck-cards.svg\": 1228,\n\t\"./icons-32-mini-fridge.svg\": 1229,\n\t\"./inclusive.svg\": 1230,\n\t\"./information.svg\": 1231,\n\t\"./informationOutline.svg\": 1232,\n\t\"./instagram.svg\": 1233,\n\t\"./key.svg\": 1234,\n\t\"./kitchenette.svg\": 1235,\n\t\"./laptop.svg\": 1236,\n\t\"./lateNight.svg\": 1237,\n\t\"./list.svg\": 1238,\n\t\"./localBar.svg\": 1239,\n\t\"./location-pointer.svg\": 1240,\n\t\"./location_icon.svg\": 1241,\n\t\"./lock.svg\": 1242,\n\t\"./lodge-news.svg\": 1243,\n\t\"./loyalty.svg\": 1244,\n\t\"./luggage.svg\": 1245,\n\t\"./manual.svg\": 1246,\n\t\"./map.svg\": 1247,\n\t\"./menu.svg\": 1248,\n\t\"./microwave.svg\": 1249,\n\t\"./mileage.svg\": 1250,\n\t\"./minus-thin.svg\": 1251,\n\t\"./minus.svg\": 1252,\n\t\"./mobilePhone.svg\": 1253,\n\t\"./multiOccupancy.svg\": 1254,\n\t\"./notification.svg\": 1255,\n\t\"./offer.svg\": 1256,\n\t\"./openEye.svg\": 1257,\n\t\"./open_modal_link.svg\": 1258,\n\t\"./ottoman.svg\": 1259,\n\t\"./overage.svg\": 1260,\n\t\"./overage21.svg\": 1261,\n\t\"./overnight.svg\": 1262,\n\t\"./parking.svg\": 1263,\n\t\"./personAdd.svg\": 1264,\n\t\"./pets.svg\": 1265,\n\t\"./phone.svg\": 1266,\n\t\"./phone_icon.svg\": 1267,\n\t\"./picture.svg\": 1268,\n\t\"./pin.svg\": 1269,\n\t\"./plus-thin.svg\": 1270,\n\t\"./plus.svg\": 1271,\n\t\"./pool.svg\": 1272,\n\t\"./printer.svg\": 1273,\n\t\"./question.svg\": 1274,\n\t\"./quilt.svg\": 1275,\n\t\"./radioChecked.svg\": 1276,\n\t\"./radioEmpty.svg\": 1277,\n\t\"./radioMinus.svg\": 1278,\n\t\"./radioPlus.svg\": 1279,\n\t\"./rateCalendar.svg\": 1280,\n\t\"./refresh.svg\": 1281,\n\t\"./restaurant.svg\": 1282,\n\t\"./ribbon.svg\": 1283,\n\t\"./roomSize.svg\": 1284,\n\t\"./rowing.svg\": 1285,\n\t\"./sales-alert-solid.svg\": 1286,\n\t\"./search.svg\": 1287,\n\t\"./searchRecent.svg\": 1288,\n\t\"./seat.svg\": 1289,\n\t\"./seatBusiness.svg\": 1290,\n\t\"./seatEconomy.svg\": 1291,\n\t\"./security.svg\": 1292,\n\t\"./shuttle.svg\": 1293,\n\t\"./singleOccupancy.svg\": 1294,\n\t\"./smoking.svg\": 1295,\n\t\"./spa.svg\": 1296,\n\t\"./spaIcon.svg\": 1297,\n\t\"./splitTicket.svg\": 1298,\n\t\"./star.svg\": 1299,\n\t\"./starHalf.svg\": 1300,\n\t\"./steeringWheel.svg\": 1301,\n\t\"./success-check.svg\": 1302,\n\t\"./success-icon.svg\": 1303,\n\t\"./success.svg\": 1304,\n\t\"./successDuotone.svg\": 1305,\n\t\"./successOutline.svg\": 1306,\n\t\"./swap.svg\": 1307,\n\t\"./thumbsDown.svg\": 1308,\n\t\"./thumbsUp.svg\": 1309,\n\t\"./timer.svg\": 1310,\n\t\"./trashCan.svg\": 1311,\n\t\"./trendingUp.svg\": 1312,\n\t\"./trophy.svg\": 1313,\n\t\"./tune.svg\": 1314,\n\t\"./twitter.svg\": 1315,\n\t\"./ui-icon-birthdays.svg\": 1316,\n\t\"./ui-icon-cabana.svg\": 1317,\n\t\"./ui-icon-dining.svg\": 1318,\n\t\"./ui-icon-pass.svg\": 1319,\n\t\"./unlock.svg\": 1320,\n\t\"./user-new-ui.svg\": 1321,\n\t\"./user.svg\": 1322,\n\t\"./verified.svg\": 1323,\n\t\"./viewDetails.svg\": 1324,\n\t\"./virtual-events.svg\": 1325,\n\t\"./warning.svg\": 1326,\n\t\"./warningOutline.svg\": 1327,\n\t\"./web.svg\": 1328,\n\t\"./whirlpool.svg\": 1329,\n\t\"./white-check-mark.svg\": 1330,\n\t\"./wifi.svg\": 1331,\n\t\"./wiley.svg\": 1332,\n\t\"./wolf.svg\": 1333,\n\t\"./youtube.svg\": 1334,\n\t\"./zoomOut.svg\": 1335\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 1084;","export default __webpack_public_path__ + \"static/media/OfferNotFound.0bb4a78e.svg\";","export default __webpack_public_path__ + \"static/media/OffersNormal.1472c5a9.svg\";","export default __webpack_public_path__ + \"static/media/OffersNormalWhite.6a893531.svg\";","export default __webpack_public_path__ + \"static/media/OffersOpen.a3c4605a.svg\";","export default __webpack_public_path__ + \"static/media/ac.a67a8cad.svg\";","export default __webpack_public_path__ + \"static/media/accessible.bb24c0a8.svg\";","export default __webpack_public_path__ + \"static/media/accessibleIcon.3ca1de13.svg\";","export default __webpack_public_path__ + \"static/media/airplane.650ef7e1.svg\";","export default __webpack_public_path__ + \"static/media/alertErrorIcon.9956fb8e.svg\";","export default __webpack_public_path__ + \"static/media/alertInfoIcon.cbf9190c.svg\";","export default __webpack_public_path__ + \"static/media/alertOfferIcon.56d20947.svg\";","export default __webpack_public_path__ + \"static/media/alertSuccessIcon.2edfba0a.svg\";","export default __webpack_public_path__ + \"static/media/arrival.6d6ffc60.svg\";","export default __webpack_public_path__ + \"static/media/arrowCaretLeft.99e9f56c.svg\";","export default __webpack_public_path__ + \"static/media/arrowDown.9dfcf66a.svg\";","export default __webpack_public_path__ + \"static/media/arrowDownRounded.7c26cef5.svg\";","export default __webpack_public_path__ + \"static/media/arrowDownThin.259850f1.svg\";","export default __webpack_public_path__ + \"static/media/arrowLeft.36692eca.svg\";","export default __webpack_public_path__ + \"static/media/arrowRight.8fd38d13.svg\";","export default __webpack_public_path__ + \"static/media/arrowRightThin.f398bf18.svg\";","export default __webpack_public_path__ + \"static/media/arrowUp.84db7ea2.svg\";","export default __webpack_public_path__ + \"static/media/attention.583d583a.svg\";","export default __webpack_public_path__ + \"static/media/attentionWarning.d2e6d9b8.svg\";","export default __webpack_public_path__ + \"static/media/attractionsBlue.13cd92ff.svg\";","export default __webpack_public_path__ + \"static/media/attractionsIcon.3e81d8ba.svg\";","export default __webpack_public_path__ + \"static/media/attractionsWhite.2da8845b.svg\";","export default __webpack_public_path__ + \"static/media/automatic.6a284b85.svg\";","export default __webpack_public_path__ + \"static/media/bag.a7bf5567.svg\";","export default __webpack_public_path__ + \"static/media/beach.83363029.svg\";","export default __webpack_public_path__ + \"static/media/bed.2946a131.svg\";","export default __webpack_public_path__ + \"static/media/bedAkela.67d5d07d.svg\";","export default __webpack_public_path__ + \"static/media/birthdayBlue.47d635d7.svg\";","export default __webpack_public_path__ + \"static/media/birthdayIcon.9eca36ce.svg\";","export default __webpack_public_path__ + \"static/media/birthdayWhite.13d4b43a.svg\";","export default __webpack_public_path__ + \"static/media/blueQuestion.3c5aa776.svg\";","export default __webpack_public_path__ + \"static/media/boxChecked.c343ce14.svg\";","export default __webpack_public_path__ + \"static/media/boxEmpty.b2e8209c.svg\";","export default __webpack_public_path__ + \"static/media/boxMinus.6312cfec.svg\";","export default __webpack_public_path__ + \"static/media/boxPlus.cfb124cd.svg\";","export default __webpack_public_path__ + \"static/media/breakfast.bb33017c.svg\";","export default __webpack_public_path__ + \"static/media/build.29604c44.svg\";","export default __webpack_public_path__ + \"static/media/business.04dd2c17.svg\";","export default __webpack_public_path__ + \"static/media/cabin.1538682f.svg\";","export default __webpack_public_path__ + \"static/media/cake.bf84b8b1.svg\";","export default __webpack_public_path__ + \"static/media/calendar-icon.c4b7b12b.svg\";","export default __webpack_public_path__ + \"static/media/calendar-outline.be0e1e3c.svg\";","export default __webpack_public_path__ + \"static/media/calendar.0e7aa3a7.svg\";","export default __webpack_public_path__ + \"static/media/calendarPicker.24def4ce.svg\";","export default __webpack_public_path__ + \"static/media/carCircle.2b62cf24.svg\";","export default __webpack_public_path__ + \"static/media/carDoor.745b5a72.svg\";","export default __webpack_public_path__ + \"static/media/carouselChevronLeft.233f9a44.svg\";","export default __webpack_public_path__ + \"static/media/carouselChevronLeftThin.e36f3994.svg\";","export default __webpack_public_path__ + \"static/media/carouselChevronRight.02521b76.svg\";","export default __webpack_public_path__ + \"static/media/carouselChevronRigthThin.fe62df3a.svg\";","export default __webpack_public_path__ + \"static/media/carriage.3399f6e1.svg\";","export default __webpack_public_path__ + \"static/media/cars.7a11f725.svg\";","export default __webpack_public_path__ + \"static/media/casino.ba1b7722.svg\";","export default __webpack_public_path__ + \"static/media/chairs.6209dbea.svg\";","export default __webpack_public_path__ + \"static/media/chart.9dcb2b0b.svg\";","export default __webpack_public_path__ + \"static/media/chat.268a6e8d.svg\";","export default __webpack_public_path__ + \"static/media/check.2cfe8bc2.svg\";","export default __webpack_public_path__ + \"static/media/checkedIcon.2eb662e5.svg\";","export default __webpack_public_path__ + \"static/media/chevron-thin-right.92263cc6.svg\";","export default __webpack_public_path__ + \"static/media/chevronDown.4d3c14e5.svg\";","export default __webpack_public_path__ + \"static/media/chevronLeft.a6f865aa.svg\";","export default __webpack_public_path__ + \"static/media/chevronRight.dbc221a7.svg\";","export default __webpack_public_path__ + \"static/media/chevronThinLeft.99e9f56c.svg\";","export default __webpack_public_path__ + \"static/media/chevronUp.0778875d.svg\";","export default __webpack_public_path__ + \"static/media/chevronUpThin.95119969.svg\";","export default __webpack_public_path__ + \"static/media/circleMinus.505c8fc6.svg\";","export default __webpack_public_path__ + \"static/media/circlePlus.093701a8.svg\";","export default __webpack_public_path__ + \"static/media/cityView.20705328.svg\";","export default __webpack_public_path__ + \"static/media/clock.8342530a.svg\";","export default __webpack_public_path__ + \"static/media/close-icon.8d19338e.svg\";","export default __webpack_public_path__ + \"static/media/close.941ea749.svg\";","export default __webpack_public_path__ + \"static/media/closeCircle.36675afa.svg\";","export default __webpack_public_path__ + \"static/media/closeIcon.ea7c95d7.svg\";","export default __webpack_public_path__ + \"static/media/closeThin.f38c5096.svg\";","export default __webpack_public_path__ + \"static/media/closedEye.0ee7fa56.svg\";","export default __webpack_public_path__ + \"static/media/cloud.19ef8aa4.svg\";","export default __webpack_public_path__ + \"static/media/collisionCoverage.a368af57.svg\";","export default __webpack_public_path__ + \"static/media/condoIcon.74258ee5.svg\";","export default __webpack_public_path__ + \"static/media/coupon.9a45035e.svg\";","export default __webpack_public_path__ + \"static/media/credit-card-outline.2b6835b6.svg\";","export default __webpack_public_path__ + \"static/media/creditCard.98a6a928.svg\";","export default __webpack_public_path__ + \"static/media/cruises.ab67f123.svg\";","export default __webpack_public_path__ + \"static/media/delete.151774f4.svg\";","export default __webpack_public_path__ + \"static/media/departure.1357e882.svg\";","export default __webpack_public_path__ + \"static/media/devices.c58b98c0.svg\";","export default __webpack_public_path__ + \"static/media/directions.079c7bcb.svg\";","export default __webpack_public_path__ + \"static/media/discount.e2d07667.svg\";","export default __webpack_public_path__ + \"static/media/document.b85763cf.svg\";","export default __webpack_public_path__ + \"static/media/dollar.0358da97.svg\";","export default __webpack_public_path__ + \"static/media/dollarCircle.b3f60821.svg\";","export default __webpack_public_path__ + \"static/media/doubleArrowUpIcon.42a9329b.svg\";","export default __webpack_public_path__ + \"static/media/doubleOccupancy.5edb3c44.svg\";","export default __webpack_public_path__ + \"static/media/earlyBird.0e6f1bd2.svg\";","export default __webpack_public_path__ + \"static/media/edit.7b40250b.svg\";","export default __webpack_public_path__ + \"static/media/electric.868bdea2.svg\";","export default __webpack_public_path__ + \"static/media/email.9b0a2978.svg\";","export default __webpack_public_path__ + \"static/media/emoticon.27961774.svg\";","export default __webpack_public_path__ + \"static/media/event.b45c0c96.svg\";","export default __webpack_public_path__ + \"static/media/eventAvailable.6cef03d7.svg\";","export default __webpack_public_path__ + \"static/media/eventBusy.2d0a2f2b.svg\";","export default __webpack_public_path__ + \"static/media/facebook.60a030fa.svg\";","export default __webpack_public_path__ + \"static/media/facebookBtn.5264afc5.svg\";","export default __webpack_public_path__ + \"static/media/facebookIcon.f71c8177.svg\";","export default __webpack_public_path__ + \"static/media/familyBlue.8e3a0c40.svg\";","export default __webpack_public_path__ + \"static/media/familyIcon.ff294ed0.svg\";","export default __webpack_public_path__ + \"static/media/familyWhite.3e96c19f.svg\";","export default __webpack_public_path__ + \"static/media/fan.9b85c651.svg\";","export default __webpack_public_path__ + \"static/media/favoriteHotel.38b0bdfb.svg\";","export default __webpack_public_path__ + \"static/media/filter.d6c1d511.svg\";","export default __webpack_public_path__ + \"static/media/fitness.b437d92a.svg\";","export default __webpack_public_path__ + \"static/media/flame.67e1977c.svg\";","export default __webpack_public_path__ + \"static/media/flightCircle.bb23ca46.svg\";","export default __webpack_public_path__ + \"static/media/flightCoverage.a3ca6398.svg\";","export default __webpack_public_path__ + \"static/media/flights.4cf6ff81.svg\";","export default __webpack_public_path__ + \"static/media/forbidden.b6546cc7.svg\";","export default __webpack_public_path__ + \"static/media/freeCancellation.28215d78.svg\";","export default __webpack_public_path__ + \"static/media/fridge.93a454b0.svg\";","export default __webpack_public_path__ + \"static/media/front-desk.9917bfba.svg\";","export default __webpack_public_path__ + \"static/media/fullSofaBed.ee6d4817.svg\";","export default __webpack_public_path__ + \"static/media/gallery.d16c4c14.svg\";","export default __webpack_public_path__ + \"static/media/gas.eb69c73c.svg\";","export default __webpack_public_path__ + \"static/media/globe.9b36c42a.svg\";","export default __webpack_public_path__ + \"static/media/golf.9d099937.svg\";","export default __webpack_public_path__ + \"static/media/googleBtn.a4ee1211.svg\";","export default __webpack_public_path__ + \"static/media/gps.8abb0b0c.svg\";","export default __webpack_public_path__ + \"static/media/graph.a4458fae.svg\";","export default __webpack_public_path__ + \"static/media/grid-gallery.c95a47b5.svg\";","export default __webpack_public_path__ + \"static/media/grid.adc89035.svg\";","export default __webpack_public_path__ + \"static/media/guestScore.cfeba791.svg\";","export default __webpack_public_path__ + \"static/media/guests.c356d7b1.svg\";","export default __webpack_public_path__ + \"static/media/hd Tv.1af8749c.svg\";","export default __webpack_public_path__ + \"static/media/help.59b1268d.svg\";","export default __webpack_public_path__ + \"static/media/history.faa40da4.svg\";","export default __webpack_public_path__ + \"static/media/home.4e75e1b8.svg\";","export default __webpack_public_path__ + \"static/media/hotelCircle.6c6a130f.svg\";","export default __webpack_public_path__ + \"static/media/hotels.acabde4f.svg\";","export default __webpack_public_path__ + \"static/media/house.2ee6ff10.svg\";","export default __webpack_public_path__ + \"static/media/hybrid.45927adc.svg\";","export default __webpack_public_path__ + \"static/media/icons-32-bottles-water.d2853c6d.svg\";","export default __webpack_public_path__ + \"static/media/icons-32-deck-cards.7c3736ad.svg\";","export default __webpack_public_path__ + \"static/media/icons-32-mini-fridge.5afc2fc3.svg\";","export default __webpack_public_path__ + \"static/media/inclusive.b616e583.svg\";","export default __webpack_public_path__ + \"static/media/information.c4889bbc.svg\";","export default __webpack_public_path__ + \"static/media/informationOutline.9b6c323e.svg\";","export default __webpack_public_path__ + \"static/media/instagram.5a70c3bc.svg\";","export default __webpack_public_path__ + \"static/media/key.8270b0ad.svg\";","export default __webpack_public_path__ + \"static/media/kitchenette.69648fe4.svg\";","export default __webpack_public_path__ + \"static/media/laptop.a72162d5.svg\";","export default __webpack_public_path__ + \"static/media/lateNight.cbcd9fc2.svg\";","export default __webpack_public_path__ + \"static/media/list.5d09ef30.svg\";","export default __webpack_public_path__ + \"static/media/localBar.7849a341.svg\";","export default __webpack_public_path__ + \"static/media/location-pointer.17b9d403.svg\";","export default __webpack_public_path__ + \"static/media/location_icon.5d11a79a.svg\";","export default __webpack_public_path__ + \"static/media/lock.eef1a017.svg\";","export default __webpack_public_path__ + \"static/media/lodge-news.b3d7aa46.svg\";","export default __webpack_public_path__ + \"static/media/loyalty.beaf26a7.svg\";","export default __webpack_public_path__ + \"static/media/luggage.2d66c72d.svg\";","export default __webpack_public_path__ + \"static/media/manual.9f138946.svg\";","export default __webpack_public_path__ + \"static/media/map.3488ab8b.svg\";","export default __webpack_public_path__ + \"static/media/menu.d17985fc.svg\";","export default __webpack_public_path__ + \"static/media/microwave.3cd17075.svg\";","export default __webpack_public_path__ + \"static/media/mileage.eb8cf302.svg\";","export default __webpack_public_path__ + \"static/media/minus-thin.205856de.svg\";","export default __webpack_public_path__ + \"static/media/minus.97620447.svg\";","export default __webpack_public_path__ + \"static/media/mobilePhone.a680af5d.svg\";","export default __webpack_public_path__ + \"static/media/multiOccupancy.216b4aa0.svg\";","export default __webpack_public_path__ + \"static/media/notification.9f749575.svg\";","export default __webpack_public_path__ + \"static/media/offer.7ffae217.svg\";","export default __webpack_public_path__ + \"static/media/openEye.e0459549.svg\";","export default __webpack_public_path__ + \"static/media/open_modal_link.eada0345.svg\";","export default __webpack_public_path__ + \"static/media/ottoman.a6b33247.svg\";","export default __webpack_public_path__ + \"static/media/overage.7ff492ef.svg\";","export default __webpack_public_path__ + \"static/media/overage21.705bd9b6.svg\";","export default __webpack_public_path__ + \"static/media/overnight.bac5a0c7.svg\";","export default __webpack_public_path__ + \"static/media/parking.d0fd63c1.svg\";","export default __webpack_public_path__ + \"static/media/personAdd.ae7ce60b.svg\";","export default __webpack_public_path__ + \"static/media/pets.357eecd8.svg\";","export default __webpack_public_path__ + \"static/media/phone.49f002e3.svg\";","export default __webpack_public_path__ + \"static/media/phone_icon.a680af5d.svg\";","export default __webpack_public_path__ + \"static/media/picture.5027cc7e.svg\";","export default __webpack_public_path__ + \"static/media/pin.adac1b49.svg\";","export default __webpack_public_path__ + \"static/media/plus-thin.3bf90891.svg\";","export default __webpack_public_path__ + \"static/media/plus.5fb2ccd5.svg\";","export default __webpack_public_path__ + \"static/media/pool.faea1a4b.svg\";","export default __webpack_public_path__ + \"static/media/printer.79179e1e.svg\";","export default __webpack_public_path__ + \"static/media/question.f9256074.svg\";","export default __webpack_public_path__ + \"static/media/quilt.b7823921.svg\";","export default __webpack_public_path__ + \"static/media/radioChecked.dcf47cc3.svg\";","export default __webpack_public_path__ + \"static/media/radioEmpty.37990fb9.svg\";","export default __webpack_public_path__ + \"static/media/radioMinus.1998915e.svg\";","export default __webpack_public_path__ + \"static/media/radioPlus.766098c5.svg\";","export default __webpack_public_path__ + \"static/media/rateCalendar.2b00bebe.svg\";","export default __webpack_public_path__ + \"static/media/refresh.a94233b3.svg\";","export default __webpack_public_path__ + \"static/media/restaurant.33335246.svg\";","export default __webpack_public_path__ + \"static/media/ribbon.9d747aab.svg\";","export default __webpack_public_path__ + \"static/media/roomSize.7dbfa862.svg\";","export default __webpack_public_path__ + \"static/media/rowing.b77980e8.svg\";","export default __webpack_public_path__ + \"static/media/sales-alert-solid.1d93fb2f.svg\";","export default __webpack_public_path__ + \"static/media/search.781b4274.svg\";","export default __webpack_public_path__ + \"static/media/searchRecent.56c35b44.svg\";","export default __webpack_public_path__ + \"static/media/seat.994764e0.svg\";","export default __webpack_public_path__ + \"static/media/seatBusiness.ddeed677.svg\";","export default __webpack_public_path__ + \"static/media/seatEconomy.d7bc526c.svg\";","export default __webpack_public_path__ + \"static/media/security.18df480b.svg\";","export default __webpack_public_path__ + \"static/media/shuttle.de2ec4ff.svg\";","export default __webpack_public_path__ + \"static/media/singleOccupancy.628d19b6.svg\";","export default __webpack_public_path__ + \"static/media/smoking.ddfb3656.svg\";","export default __webpack_public_path__ + \"static/media/spa.efced4cf.svg\";","export default __webpack_public_path__ + \"static/media/spaIcon.bdc583ca.svg\";","export default __webpack_public_path__ + \"static/media/splitTicket.cd246869.svg\";","export default __webpack_public_path__ + \"static/media/star.a3530845.svg\";","export default __webpack_public_path__ + \"static/media/starHalf.0f75bec3.svg\";","export default __webpack_public_path__ + \"static/media/steeringWheel.a07eaa4e.svg\";","export default __webpack_public_path__ + \"static/media/success-check.0f9ea56e.svg\";","export default __webpack_public_path__ + \"static/media/success-icon.779957e4.svg\";","export default __webpack_public_path__ + \"static/media/success.8e725dc6.svg\";","export default __webpack_public_path__ + \"static/media/successDuotone.f01724b5.svg\";","export default __webpack_public_path__ + \"static/media/successOutline.4b41ebf1.svg\";","export default __webpack_public_path__ + \"static/media/swap.c5c9f6d5.svg\";","export default __webpack_public_path__ + \"static/media/thumbsDown.eff2eb6e.svg\";","export default __webpack_public_path__ + \"static/media/thumbsUp.b37343c4.svg\";","export default __webpack_public_path__ + \"static/media/timer.b6cf5f39.svg\";","export default __webpack_public_path__ + \"static/media/trashCan.a2ee66e0.svg\";","export default __webpack_public_path__ + \"static/media/trendingUp.76eea75c.svg\";","export default __webpack_public_path__ + \"static/media/trophy.c80a3730.svg\";","export default __webpack_public_path__ + \"static/media/tune.35d5ad8e.svg\";","export default __webpack_public_path__ + \"static/media/twitter.c98997bf.svg\";","export default __webpack_public_path__ + \"static/media/ui-icon-birthdays.f6bf5dbe.svg\";","export default __webpack_public_path__ + \"static/media/ui-icon-cabana.d33e14bb.svg\";","export default __webpack_public_path__ + \"static/media/ui-icon-dining.9d2573ee.svg\";","export default __webpack_public_path__ + \"static/media/ui-icon-pass.4f359e64.svg\";","export default __webpack_public_path__ + \"static/media/unlock.32efae50.svg\";","export default __webpack_public_path__ + \"static/media/user-new-ui.c0e5a0e2.svg\";","export default __webpack_public_path__ + \"static/media/user.930c3900.svg\";","export default __webpack_public_path__ + \"static/media/verified.cdc383e6.svg\";","export default __webpack_public_path__ + \"static/media/viewDetails.b0ef891b.svg\";","export default __webpack_public_path__ + \"static/media/virtual-events.87885e0c.svg\";","export default __webpack_public_path__ + \"static/media/warning.9e32c874.svg\";","export default __webpack_public_path__ + \"static/media/warningOutline.d9cbe4d7.svg\";","export default __webpack_public_path__ + \"static/media/web.e4d4dcd4.svg\";","export default __webpack_public_path__ + \"static/media/whirlpool.83f9a4b2.svg\";","export default __webpack_public_path__ + \"static/media/white-check-mark.8160513d.svg\";","export default __webpack_public_path__ + \"static/media/wifi.f5dc3630.svg\";","export default __webpack_public_path__ + \"static/media/wiley.23e26099.svg\";","export default __webpack_public_path__ + \"static/media/wolf.a2cfd326.svg\";","export default __webpack_public_path__ + \"static/media/youtube.035850fc.svg\";","export default __webpack_public_path__ + \"static/media/zoomOut.f836678b.svg\";","import { isDevEnvironment } from '../utilities/env';\r\n\r\n// const birthdayPartyTimesAndLocationsJson = [\r\n// {\r\n// property: 'ATLAGA',\r\n// timesAndLocations: [\r\n// {\r\n// value: 0,\r\n// name: '11:30 am to 1:00 pm in a reserved area outside of the water park'\r\n// },\r\n// {\r\n// value: 1,\r\n// name: '1:30 pm to 3:00 pm in a reserved area outside of the water park'\r\n// },\r\n// {\r\n// value: 2,\r\n// name: '3:30 pm to 5:00 pm in a reserved area outside of the water park'\r\n// }\r\n// ]\r\n// },\r\n// {\r\n// property: 'BLOOMN',\r\n// timesAndLocations: [\r\n// { value: 0, name: '12:30 to 1:30 pm at Campfire Kitchen' },\r\n// { value: 1, name: '2:00 to 3:00 pm at Campfire Kitchen' },\r\n// { value: 2, name: '3:30 to 4:30 pm at Campfire Kitchen' },\r\n// {\r\n// value: 3,\r\n// name: '4:00 to 5:00 pm at Buckets Incredible Craveables'\r\n// },\r\n// {\r\n// value: 4,\r\n// name: '6:00 to 7:00 pm at Buckets Incredible Craveables'\r\n// },\r\n// {\r\n// value: 5,\r\n// name: '7:30 to 8:30 pm at Buckets Incredible Craveables'\r\n// }\r\n// ]\r\n// },\r\n// {\r\n// property: 'COLOCO',\r\n// timesAndLocations: [\r\n// { value: 0, name: '11:30 am at Hungry As A Wolf' },\r\n// { value: 1, name: '1:30 pm at Hungry As A Wolf' },\r\n// { value: 2, name: '3:30 pm at Hungry As A Wolf' },\r\n// { value: 3, name: '5:30 pm at Hungry As A Wolf' }\r\n// ]\r\n// },\r\n// {\r\n// property: 'CONCNC',\r\n// timesAndLocations: [\r\n// {\r\n// value: 0,\r\n// name: '12:30 pm to 2:00 pm at The Loose Moose Cottage'\r\n// },\r\n// { value: 1, name: '2:30 pm to 4:00 pm at The Loose Moose Cottage' }\r\n// ]\r\n// },\r\n// {\r\n// property: 'DELLWI',\r\n// timesAndLocations: [\r\n// { value: 0, name: '11 a.m. to 12:30 pm in the water park' },\r\n// { value: 1, name: '1 to 2:30 pm in the water park' },\r\n// { value: 2, name: '3 to 4:30 pm in the water park' },\r\n// { value: 3, name: '5 to 6:30 pm in the water park' },\r\n// { value: 4, name: '7 to 8:30 pm in the water park' }\r\n// ]\r\n// },\r\n// {\r\n// property: 'GRANWA',\r\n// timesAndLocations: [\r\n// { value: 0, name: '1 to 2:30 pm at The Water Park Mezzanine' },\r\n// { value: 1, name: '2 to 3:30 pm at The Water Park Mezzanine' },\r\n// { value: 2, name: '3 to 4:30 pm at The Water Park Mezzanine' }\r\n// ]\r\n// },\r\n// {\r\n// property: 'GRAPTX',\r\n// timesAndLocations: [\r\n// { value: 0, name: '12:30 to 1:30 pm at The Loose Moose Cottage' },\r\n// { value: 1, name: '2:30 to 4:00 pm at The Loose Moose Cottage' }\r\n// ]\r\n// },\r\n// {\r\n// property: 'GURNIL',\r\n// timesAndLocations: [\r\n// { value: 0, name: '11:00 am to 12:30 pm in Campfire Kitchen' },\r\n// { value: 1, name: '1:00 pm to 2:30 pm in Campfire Kitchen' },\r\n// { value: 2, name: '3:00 pm to 4:30 pm in Campfire Kitchen' },\r\n// { value: 3, name: '5:00 pm to 6:30 pm in Campfire Kitchen' },\r\n// { value: 4, name: '7:00 pm to 8:30 pm in Campfire Kitchen' }\r\n// ]\r\n// },\r\n// {\r\n// property: 'KANSKS',\r\n// timesAndLocations: [\r\n// {\r\n// value: 0,\r\n// name: '12:00 pm to 1:30 pm at Camp Critter Bar & Grille'\r\n// },\r\n// {\r\n// value: 1,\r\n// name: '2:00 pm to 3:30 pm at Camp Critter Bar & Grille'\r\n// },\r\n// {\r\n// value: 2,\r\n// name: '4:00 pm to 5:30 pm at Camp Critter Bar & Grille'\r\n// }\r\n// ]\r\n// },\r\n// {\r\n// property: 'MASOOH',\r\n// timesAndLocations: [\r\n// { value: 0, name: '12:00 pm at Loose Moose' },\r\n// { value: 1, name: '1:00 pm at Loose Moose' },\r\n// { value: 2, name: '2:00 pm at Loose Moose' },\r\n// { value: 3, name: '3:00 pm at Loose Moose' },\r\n// { value: 4, name: '4:00 pm at Loose Moose' }\r\n// ]\r\n// },\r\n// {\r\n// property: 'NEWEMA',\r\n// timesAndLocations: [\r\n// { value: 0, name: '12:30 to 2:00 pm at Lodge Wood Fired Grill' },\r\n// { value: 1, name: '2:30 to 4:00 pm at Lodge Wood Fired Grill' }\r\n// ]\r\n// },\r\n// {\r\n// property: 'NIAGON',\r\n// timesAndLocations: [{ value: 0, name: 'Unknown' }]\r\n// },\r\n// {\r\n// property: 'POCOPA',\r\n// timesAndLocations: [\r\n// {\r\n// value: 0,\r\n// name:\r\n// '1:00 to 2:00 pm Bear Den (located inside The Loose Moose Cottage) or Northwest Territory'\r\n// },\r\n// {\r\n// value: 1,\r\n// name:\r\n// '2:00 to 3:00 pm Bear Den (located inside The Loose Moose Cottage) or Northwest Territory'\r\n// },\r\n// {\r\n// value: 2,\r\n// name:\r\n// '3:00 to 4:00 pm Bear Den (located inside The Loose Moose Cottage) or Northwest Territory'\r\n// }\r\n// ]\r\n// },\r\n// {\r\n// property: 'SANDOH',\r\n// timesAndLocations: [\r\n// { value: 0, name: '12:00 to 1:00 pm at Gitchigoomie Grill' },\r\n// { value: 1, name: '1:00 to 2:00 pm at Gitchigoomie Grill' },\r\n// { value: 2, name: '2:00 to 3:00 pm at Gitchigoomie Grill' },\r\n// { value: 3, name: '4:00 to 5:00 pm at Gitchigoomie Grill' }\r\n// ]\r\n// },\r\n// {\r\n// property: 'SCOTAZ',\r\n// timesAndLocations: [{ value: 0, name: 'Unknown' }]\r\n// },\r\n// {\r\n// property: 'SOUTCA',\r\n// timesAndLocations: [{ value: 0, name: 'Unknown' }]\r\n// },\r\n// {\r\n// property: 'TRAVMI',\r\n// timesAndLocations: [\r\n// {\r\n// value: 0,\r\n// name: '11:00 am to 12:30 pm in the Water Park Birthday Party Area'\r\n// },\r\n// {\r\n// value: 1,\r\n// name: '1:00 pm to 2:30 pm in the Water Park Birthday Party Area'\r\n// },\r\n// {\r\n// value: 2,\r\n// name: '3:00 pm to 4:30 pm in the Water Park Birthday Party Area'\r\n// },\r\n// {\r\n// value: 3,\r\n// name: '5:00 pm to 6:30 pm in the Water Park Birthday Party Area'\r\n// }\r\n// ]\r\n// },\r\n// {\r\n// property: 'WILLVA',\r\n// timesAndLocations: [\r\n// { value: 0, name: '12:00 pm to 1:30 pm in the restaurant' },\r\n// { value: 1, name: '12:30 pm to 2:00 pm in the restaurant' },\r\n// { value: 2, name: '1:00 pm to 2:30 pm in the restaurant' },\r\n// { value: 3, name: '1:30 pm to 3:00 pm in the restaurant' },\r\n// { value: 4, name: '2:00 pm to 3:30 pm in the restaurant' },\r\n// { value: 5, name: '2:30 pm to 4:00 pm in the restaurant' },\r\n// { value: 6, name: '3:00 pm to 4:30 pm in the restaurant' }\r\n// ]\r\n// }\r\n// ];\r\n\r\nconst birthdayPartyTimesAndLocationsJson = [\r\n {\r\n name: '04:00 PM to 05:30 PM at Campfire Kitchen',\r\n value: 0\r\n },\r\n {\r\n name: '06:00 PM to 07:30 PM at Campfire Kitchen',\r\n value: 1\r\n },\r\n {\r\n name: '08:00 PM to 09:30 PM at Campfire Kitchen',\r\n value: 2\r\n },\r\n {\r\n name: '10:00 PM to 11:30 PM at Campfire Kitchen',\r\n value: 3\r\n },\r\n {\r\n name: '12:00 AM to 01:30 AM at Campfire Kitchen',\r\n value: 4\r\n }\r\n];\r\n\r\nif (isDevEnvironment) {\r\n window.birthdayPartyTimesAndLocationsJson = JSON.stringify(\r\n birthdayPartyTimesAndLocationsJson\r\n );\r\n}\r\n","import { isDevEnvironment } from '../utilities/env';\r\n\r\nconst bookingEngineAlert = [\r\n {\r\n enableBookingAlert: true,\r\n startNotificationDate: '01/09/2020',\r\n endNotificationDate: '30/09/2020',\r\n startSearchDate: '01/09/2020',\r\n endSearchDate: '30/09/2020',\r\n iconImage: '/content/dam/greatwolf/sites/www/global/en/story-time-icon.svg',\r\n iconAlt: '(1) Booking Engine Alert Icon',\r\n message:\r\n \"(1) Heads Up! This alert needs your attention, but it's not super important. Learn more.\\r\\n\"\r\n },\r\n {\r\n enableBookingAlert: true,\r\n startNotificationDate: '01/08/2020',\r\n endNotificationDate: '30/08/2020',\r\n startSearchDate: '01/08/2020',\r\n endSearchDate: '30/08/2020',\r\n iconImage: '/content/dam/greatwolf/sites/www/global/en/story-time-icon.svg',\r\n iconAlt: '(2) Booking Engine Alert Icon',\r\n message:\r\n \"
(2) Heads Up! This alert needs your attention, but it's not super important. Learn more.\\r\\n\"\r\n },\r\n {\r\n enableBookingAlert: true,\r\n startNotificationDate: '01/08/2020',\r\n endNotificationDate: '30/08/2020',\r\n startSearchDate: '01/08/2020',\r\n endSearchDate: '30/08/2020',\r\n iconImage: '/content/dam/greatwolf/sites/www/global/en/story-time-icon.svg',\r\n iconAlt: '(3) Booking Engine Alert Icon',\r\n message:\r\n \"
(3) Heads Up! This alert needs your attention, but it's not super important. Learn more.\\r\\n\"\r\n }\r\n];\r\n\r\nif (isDevEnvironment) {\r\n window.bookingEngineAlert = JSON.stringify(bookingEngineAlert);\r\n}\r\n","import { isDevEnvironment } from '../utilities/env';\r\n\r\nconst mysteryDealPromoList = {\r\n data: [\r\n {\r\n offerCode: 'PROMO10',\r\n rateCode: 'PROMO10',\r\n percentage: 10\r\n },\r\n {\r\n offerCode: 'PROMO20',\r\n rateCode: 'PROMO20',\r\n percentage: 20\r\n },\r\n {\r\n offerCode: 'ESAVE',\r\n rateCode: 'ESAVE',\r\n percentage: 25\r\n },\r\n {\r\n offerCode: 'MOREFUN',\r\n rateCode: 'MOREFUN',\r\n percentage: 40\r\n }\r\n ]\r\n};\r\n\r\nif (isDevEnvironment) {\r\n window.mysteryDealPromoList = JSON.stringify(mysteryDealPromoList);\r\n}\r\n","import { isDevEnvironment } from '../utilities/env';\r\n\r\nconst promoCodeListJson = [\r\n { promoCode: 'EMDDIN', isExclusive: 'true' },\r\n { promoCode: 'YEAREND', isExclusive: 'true' },\r\n { promoCode: 'HOWL', isExclusive: 'false' },\r\n { promoCode: 'SNOWLAND', isExclusive: 'false' },\r\n { promoCode: 'MOREFUN', isExclusive: 'false' },\r\n { promoCode: 'ESAVE', isExclusive: 'true' },\r\n { promoCode: 'ESAVER', isExclusive: 'true' },\r\n { promoCode: 'HEROES', isExclusive: 'false' },\r\n { promoCode: 'TRIPLEFUN', isExclusive: 'false' },\r\n { promoCode: 'FINAL', isExclusive: 'true' },\r\n { promoCode: 'COUNTDOWN', isExclusive: 'true' },\r\n { promoCode: 'SUMMERFN', isExclusive: 'true' },\r\n { promoCode: 'SCHOOL', isExclusive: 'true' }\r\n];\r\n\r\nif (isDevEnvironment) {\r\n window.promoCodeList = JSON.stringify(promoCodeListJson);\r\n}\r\n","import { Component } from 'react';\r\nimport { withRouter } from 'react-router-dom';\r\nclass ScrollToTop extends Component {\r\n componentDidUpdate(prevProps) {\r\n if (this.props.location.pathname !== prevProps.location.pathname) {\r\n window.scrollTo(0, 0);\r\n }\r\n }\r\n\r\n render() {\r\n return this.props.children;\r\n }\r\n}\r\n\r\nexport default withRouter(ScrollToTop);\r\n","import axios from 'axios';\r\nimport { MODAL_KEYS } from '../../components/GlobalModal/modalSource';\r\nimport { openModal } from '../../store/componentStores/GlobalModal/globalModal.actions';\r\n\r\naxios.interceptors.response.use(undefined, async err => {\r\n if (err.response?.status === 401 || err.response?.data?.message === '401 Unauthorized') {\r\n localStorage.removeItem('user');\r\n openModal(\r\n {\r\n keyContentComponent: MODAL_KEYS.AUTH_MODAL,\r\n params: {\r\n shouldOpenCreateForm: false\r\n }\r\n },\r\n false,\r\n true\r\n );\r\n }\r\n return Promise.reject(err);\r\n});\r\n","// This optional code is used to register a service worker.\r\n// register() is not called by default.\r\n\r\n// This lets the app load faster on subsequent visits in production, and gives\r\n// it offline capabilities. However, it also means that developers (and users)\r\n// will only see deployed updates on subsequent visits to a page, after all the\r\n// existing tabs open on the page have been closed, since previously cached\r\n// resources are updated in the background.\r\n\r\n// To learn more about the benefits of this model and instructions on how to\r\n// opt-in, read http://bit.ly/CRA-PWA\r\n\r\nconst isLocalhost = Boolean(\r\n window.location.hostname === 'localhost' ||\r\n // [::1] is the IPv6 localhost address.\r\n window.location.hostname === '[::1]' ||\r\n // 127.0.0.1/8 is considered localhost for IPv4.\r\n window.location.hostname.match(/^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)\r\n);\r\n\r\nexport function register(config) {\r\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\r\n // The URL constructor is available in all browsers that support SW.\r\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\r\n if (publicUrl.origin !== window.location.origin) {\r\n // Our service worker won't work if PUBLIC_URL is on a different origin\r\n // from what our page is served on. This might happen if a CDN is used to\r\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\r\n return;\r\n }\r\n\r\n window.addEventListener('load', () => {\r\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\r\n\r\n if (isLocalhost) {\r\n // This is running on localhost. Let's check if a service worker still exists or not.\r\n checkValidServiceWorker(swUrl, config);\r\n\r\n // Add some additional logging to localhost, pointing developers to the\r\n // service worker/PWA documentation.\r\n navigator.serviceWorker.ready.then(() => {\r\n console.log(\r\n 'This web app is being served cache-first by a service ' +\r\n 'worker. To learn more, visit http://bit.ly/CRA-PWA'\r\n );\r\n });\r\n } else {\r\n // Is not localhost. Just register service worker\r\n registerValidSW(swUrl, config);\r\n }\r\n });\r\n }\r\n}\r\n\r\nfunction registerValidSW(swUrl, config) {\r\n navigator.serviceWorker\r\n .register(swUrl)\r\n .then(registration => {\r\n registration.onupdatefound = () => {\r\n const installingWorker = registration.installing;\r\n if (installingWorker == null) {\r\n return;\r\n }\r\n installingWorker.onstatechange = () => {\r\n if (installingWorker.state === 'installed') {\r\n if (navigator.serviceWorker.controller) {\r\n // At this point, the updated precached content has been fetched,\r\n // but the previous service worker will still serve the older\r\n // content until all client tabs are closed.\r\n console.log(\r\n 'New content is available and will be used when all ' +\r\n 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'\r\n );\r\n\r\n // Execute callback\r\n if (config && config.onUpdate) {\r\n config.onUpdate(registration);\r\n }\r\n } else {\r\n // At this point, everything has been precached.\r\n // It's the perfect time to display a\r\n // \"Content is cached for offline use.\" message.\r\n console.log('Content is cached for offline use.');\r\n\r\n // Execute callback\r\n if (config && config.onSuccess) {\r\n config.onSuccess(registration);\r\n }\r\n }\r\n }\r\n };\r\n };\r\n })\r\n .catch(error => {\r\n console.error('Error during service worker registration:', error);\r\n });\r\n}\r\n\r\nfunction checkValidServiceWorker(swUrl, config) {\r\n // Check if the service worker can be found. If it can't reload the page.\r\n fetch(swUrl)\r\n .then(response => {\r\n // Ensure service worker exists, and that we really are getting a JS file.\r\n const contentType = response.headers.get('content-type');\r\n if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) {\r\n // No service worker found. Probably a different app. Reload the page.\r\n navigator.serviceWorker.ready.then(registration => {\r\n registration.unregister().then(() => {\r\n window.location.reload();\r\n });\r\n });\r\n } else {\r\n // Service worker found. Proceed as normal.\r\n registerValidSW(swUrl, config);\r\n }\r\n })\r\n .catch(() => {\r\n console.log('No internet connection found. App is running in offline mode.');\r\n });\r\n}\r\n\r\nexport function unregister() {\r\n if ('serviceWorker' in navigator) {\r\n navigator.serviceWorker.ready.then(registration => {\r\n registration.unregister();\r\n });\r\n }\r\n}\r\n","import { getGeolocationUrl } from '../Utils/apiURLConfiguration';\r\nimport GWRApiClient from './GWRApiClient';\r\n\r\n/**\r\n * Concrete implementation for the Geolocation endpoints\r\n *\r\n * @class GeolocationApiClient\r\n * @extends {GWRApiClient}\r\n */\r\nexport default class GeolocationApiClient extends GWRApiClient {\r\n /**\r\n * @constructor\r\n * Calls parent constructor.\r\n * If there isn't any url provided, then we use the default from the environment variable\r\n * fills the url and token information\r\n * @param {string} url\r\n * The url where the service endpoints are\r\n * @param {string} token\r\n * The token of the logged user\r\n */\r\n constructor(token = '') {\r\n const urlAux = getGeolocationUrl();\r\n\r\n super(urlAux, token);\r\n }\r\n\r\n /**\r\n * function to get geolocation data\r\n *\r\n * @function\r\n */\r\n async getGeolocationData() {\r\n const urlRequest = `${this.url}`;\r\n let request = await super.getApiCall(urlRequest);\r\n\r\n return request;\r\n }\r\n}\r\n","import { store } from '../../../store/configureStore';\r\nimport { getResortLocationUrl } from '../../../utilities/resortLocation';\r\nimport { LocalStorageKeys, SessionStorageKeys } from '../../../utilities/storageUtils';\r\n\r\nexport const LODGE_LOCATION_DATA_TTL = 15; // minutes\r\nexport const LODGE_CONFIG_DATA_TTL = 30; // minutes\r\nexport const GEO_DATA_TTL = 60; // minutes\r\n\r\n// get data from sessionStorage\r\nlet endpointTTLData = JSON.parse(sessionStorage.getItem(SessionStorageKeys.ENDPOINT_TTL_KEY)) || {};\r\n\r\nconst urlList = {\r\n planConfigByResort: ['plan', 'daypass'],\r\n creditPackageConfigByResort: ['check-in', 'packages-dining', /my-reservations\\/[\\w\\d]+/],\r\n cmpConfigByResort: ['confirmation', /my-reservations\\/[\\w\\d]+/],\r\n paymentConfigByResort: ['payment', 'packages-', /my-reservations\\/[\\w\\d]+/],\r\n partyBookingWidgetConfigByResort: ['birthday-parties']\r\n};\r\n\r\n// function to validate if the endpoint can be called\r\nexport const canCallEndpoint = (endpoint, minTTL = 3, validateUrl = false) => {\r\n const now = Date.now();\r\n const msTTL = minTTL * 60 * 1000;\r\n\r\n const { lodgeLocations } = store?.getState() || '';\r\n\r\n if (\r\n endpointTTLData[endpoint] &&\r\n now - endpointTTLData[endpoint] < msTTL &&\r\n Object.keys(lodgeLocations.locationList).length > 0\r\n ) {\r\n return false; // the endpoint has been called during TTL value in minutes\r\n }\r\n return validateUrl ? checkURLAgainstList(endpoint) : true; // the endpoint can be called\r\n};\r\n\r\n// function to mark the endpoint as called\r\nexport const markEndpointAsCalled = endpoint => {\r\n endpointTTLData[endpoint] = Date.now();\r\n sessionStorage.setItem(SessionStorageKeys.ENDPOINT_TTL_KEY, JSON.stringify(endpointTTLData));\r\n};\r\n\r\n// check if the current url contains any of the keywords for the endpoint\r\nexport const checkURLAgainstList = endpoint => {\r\n const currentURL = window.location.href;\r\n\r\n const keywordCheck =\r\n urlList[endpoint] &&\r\n urlList[endpoint].some(keyword => {\r\n if (keyword instanceof RegExp) {\r\n return keyword.test(currentURL);\r\n }\r\n return currentURL.includes(keyword);\r\n });\r\n\r\n if (keywordCheck) {\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nexport const clearEndpointTTLData = endpointList => {\r\n // remove TTL for endpoints - keep the ones where 'keepTTL' flag is set\r\n endpointList.forEach(enddpoint => {\r\n delete endpointTTLData[enddpoint.name];\r\n });\r\n\r\n sessionStorage.setItem(SessionStorageKeys.ENDPOINT_TTL_KEY, JSON.stringify(endpointTTLData));\r\n};\r\n\r\nexport const getLocationFromUrl = () => {\r\n const locationData = localStorage.getItem(LocalStorageKeys.URL_LOCATION);\r\n return locationData ? JSON.parse(locationData) : null;\r\n};\r\n\r\nexport const setLocationFromUrl = () => {\r\n const locationData = getResortLocationUrl();\r\n if (locationData) {\r\n localStorage.setItem(LocalStorageKeys.URL_LOCATION, JSON.stringify(locationData.replace(/\\//g, '')));\r\n }\r\n};\r\n","import { useEffect, useRef } from 'react';\r\nimport {\r\n canCallEndpoint,\r\n clearEndpointTTLData,\r\n getLocationFromUrl,\r\n markEndpointAsCalled,\r\n setLocationFromUrl\r\n} from '../../../store/componentStores/utilities/endpointTtlValidation';\r\n\r\nconst MAX_ENDPOINT_CALL_ATTEMPTS = 2;\r\n\r\nconst useEndpointValidation = (maxOccupancy, endpointList, resetCallback, resortLocation) => {\r\n const endpointCallAttemps = useRef(0);\r\n const url = window.location.href;\r\n\r\n //Removing the geolocation call when the user is on CA lodges\r\n //===============================================================================\r\n if (url.includes('southern-california') || url.includes('northern-california')) {\r\n endpointList = endpointList.filter(ep => ep.name !== 'geolocation');\r\n }\r\n\r\n useEffect(() => {\r\n const locationFromUrl = getLocationFromUrl();\r\n\r\n if (!url.includes(locationFromUrl)) {\r\n if (typeof resetCallback === 'function') {\r\n clearEndpointTTLData(endpointList);\r\n resetCallback();\r\n setLocationFromUrl();\r\n }\r\n }\r\n\r\n // Iterate over endpointList\r\n for (const endpoint of endpointList) {\r\n const { name, TTL, validateUrl, isLodgeSpecific } = endpoint;\r\n\r\n if (!isLodgeSpecific || resortLocation) {\r\n if (canCallEndpoint(name, TTL, validateUrl)) {\r\n // call validated endpoint\r\n if (typeof endpoint.call === 'function') {\r\n endpoint.call();\r\n }\r\n markEndpointAsCalled(name);\r\n }\r\n } else {\r\n // Left following log as commented code to assist in future debugging in case if LodgeConfig data is not\r\n // getting loaded properly during initial load of application\r\n // console.log('endpoint', name, 'is lodge specific but no resort location provided. Skipping call');\r\n }\r\n }\r\n endpointCallAttemps.current += 1;\r\n const shouldClearEndpointTTLData = !maxOccupancy && endpointCallAttemps.current < MAX_ENDPOINT_CALL_ATTEMPTS;\r\n if (shouldClearEndpointTTLData) clearEndpointTTLData(endpointList);\r\n }, [endpointList, resetCallback, resortLocation, url, maxOccupancy]);\r\n};\r\n\r\nexport default useEndpointValidation;\r\n","// THIS FILE WILL RUN ANY CONFIGURATION THAT WILL LOAD BEFORE RENDER APP\r\nimport React, { Fragment, useEffect } from 'react';\r\nimport ReactGA from 'react-ga';\r\nimport { connect } from 'react-redux';\r\nimport {\r\n getBookingWidgetConfigByResort,\r\n getCartConfigByResort,\r\n getCmpConfigByResort,\r\n getCreditPackageConfigByResort,\r\n getLeadGenConfigByResort,\r\n getLoyaltyConfigByResort,\r\n getPartyBookingWidgetConfigByResort,\r\n getPaymentConfigByResort,\r\n getPlanConfigByResort,\r\n resetLodgeConfig\r\n} from '../../store/componentStores/LodgeConfig/lodgeConfig.actions';\r\nimport {\r\n getMaxOccupancy,\r\n getReferralEnabledLocation\r\n} from '../../store/componentStores/LodgeConfig/lodgeConfig.selectors';\r\nimport { getAllLodgesLocation } from '../../store/componentStores/LodgeLocations/lodgeLocations.actions';\r\nimport { getLocationList } from '../../store/componentStores/LodgeLocations/lodgeLocations.selectors';\r\n\r\nimport { updateCurrentLodge } from '../../store/componentStores/CurrentLodge/currentLodge.actions';\r\nimport { getResortLocation } from '../../store/componentStores/CurrentLodge/currentLodge.selectors';\r\n\r\nimport { getGeolocationData } from '../../store/componentStores/Geolocation/geolocation.actions';\r\nimport {\r\n GEO_DATA_TTL,\r\n LODGE_CONFIG_DATA_TTL,\r\n LODGE_LOCATION_DATA_TTL\r\n} from '../../store/componentStores/utilities/endpointTtlValidation';\r\nimport { setLocation } from '../../utilities/analytics';\r\nimport { SITE_NIAGON } from '../../utilities/constants';\r\nimport duettoTracking from '../../utilities/duetto';\r\nimport {\r\n LocalStorageKeys,\r\n isReferAfriendSessionCreatedAlready,\r\n sessionStorage_transfer\r\n} from '../../utilities/storageUtils';\r\nimport useEndpointValidation from '../utilities/hooks/useEndpointValidation';\r\n\r\nconst AppConfiguration = ({\r\n children,\r\n getLoyaltyConfigByResort,\r\n getPlanConfigByResort,\r\n getGeolocationData,\r\n getLodgeLocations,\r\n isInPrimerState,\r\n isLoyaltyEnabled,\r\n isReferralEnabledLocation,\r\n getCreditPackageConfigByResort,\r\n getPaymentConfigByResort,\r\n getLeadGenConfigByResort,\r\n getCmpConfigByResort,\r\n resetLodgeConfig,\r\n resortLocation,\r\n locationList,\r\n updateCurrentLodge,\r\n getCartConfigByResort,\r\n getBookingWidgetConfigByResort,\r\n getPartyBookingWidgetConfigByResort,\r\n maxOccupancy\r\n}) => {\r\n const endpointList = [\r\n {\r\n name: 'geolocation',\r\n TTL: GEO_DATA_TTL,\r\n call: getGeolocationData,\r\n isLodgeSpecific: false\r\n },\r\n {\r\n name: 'lodgeLocations',\r\n TTL: LODGE_LOCATION_DATA_TTL,\r\n call: getLodgeLocations,\r\n isLodgeSpecific: false\r\n },\r\n {\r\n name: 'loyaltyConfigByResort',\r\n TTL: LODGE_CONFIG_DATA_TTL,\r\n call: getLoyaltyConfigByResort,\r\n isLodgeSpecific: true\r\n },\r\n {\r\n name: 'planConfigByResort',\r\n TTL: LODGE_CONFIG_DATA_TTL,\r\n call: getPlanConfigByResort,\r\n validateUrl: true,\r\n isLodgeSpecific: true\r\n },\r\n {\r\n name: 'creditPackageConfigByResort',\r\n TTL: LODGE_CONFIG_DATA_TTL,\r\n call: getCreditPackageConfigByResort,\r\n validateUrl: true,\r\n isLodgeSpecific: true\r\n },\r\n {\r\n name: 'leadGenConfigByResort',\r\n TTL: LODGE_CONFIG_DATA_TTL,\r\n call: getLeadGenConfigByResort,\r\n isLodgeSpecific: true\r\n },\r\n {\r\n name: 'cmpConfigByResort',\r\n TTL: LODGE_CONFIG_DATA_TTL,\r\n call: getCmpConfigByResort,\r\n validateUrl: true,\r\n isLodgeSpecific: true\r\n },\r\n {\r\n name: 'paymentConfigByResort',\r\n TTL: LODGE_CONFIG_DATA_TTL,\r\n call: getPaymentConfigByResort,\r\n validateUrl: true,\r\n isLodgeSpecific: true\r\n },\r\n {\r\n name: 'cartConfigByResort',\r\n TTL: LODGE_CONFIG_DATA_TTL,\r\n call: getCartConfigByResort,\r\n isLodgeSpecific: true\r\n },\r\n {\r\n name: 'bookingWidgetConfigByResort',\r\n TTL: LODGE_CONFIG_DATA_TTL,\r\n call: getBookingWidgetConfigByResort,\r\n isLodgeSpecific: true\r\n },\r\n {\r\n name: 'partyBookingWidgetConfigByResort',\r\n TTL: LODGE_CONFIG_DATA_TTL,\r\n call: getPartyBookingWidgetConfigByResort,\r\n validateUrl: true,\r\n isLodgeSpecific: true\r\n }\r\n ];\r\n\r\n useEndpointValidation(maxOccupancy, endpointList, resetLodgeConfig, resortLocation);\r\n\r\n useEffect(() => {\r\n if (!isReferralEnabledLocation) return;\r\n // Ask other tabs for session storage\r\n if (!isReferAfriendSessionCreatedAlready()) {\r\n localStorage.setItem(LocalStorageKeys.GET_SESSION_STORAGE, Date.now());\r\n }\r\n\r\n // Run transfer\r\n window.addEventListener('storage', sessionStorage_transfer);\r\n\r\n // Clean events\r\n return function cleanupListener() {\r\n window.removeEventListener('storage', sessionStorage_transfer, false);\r\n };\r\n }, [isReferralEnabledLocation]);\r\n\r\n useEffect(() => {\r\n const voyagersClubPhase = !isLoyaltyEnabled ? 'VO' : isInPrimerState ? 'V1' : 'V2';\r\n ReactGA.set({ dimension58: voyagersClubPhase });\r\n }, [isInPrimerState, isLoyaltyEnabled]);\r\n\r\n useEffect(() => {\r\n if (resortLocation) {\r\n duettoTracking.initialize(\r\n resortLocation === SITE_NIAGON\r\n ? process.env.REACT_APP_DUETTO_ID_NIAGARA\r\n : process.env.REACT_APP_DUETTO_ID_UNIVERAL\r\n );\r\n setLocation(resortLocation);\r\n }\r\n }, [resortLocation]);\r\n\r\n useEffect(() => {\r\n updateCurrentLodge(locationList);\r\n }, [locationList, updateCurrentLodge]);\r\n\r\n return resortLocation ? {children} : null;\r\n};\r\n\r\nconst mapStateToProps = state => ({\r\n maxOccupancy: getMaxOccupancy(state.lodgeConfig),\r\n isInPrimerState: state.lodgeConfig.isInPrimerState,\r\n isLoyaltyEnabled: state.lodgeConfig.isLoyaltyEnabled,\r\n isReferralEnabledLocation: getReferralEnabledLocation(state.lodgeConfig),\r\n resortLocation: getResortLocation(state.currentLodge),\r\n locationList: getLocationList(state.lodgeLocations)\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n getLoyaltyConfigByResort,\r\n getPlanConfigByResort,\r\n getCreditPackageConfigByResort,\r\n getLodgeLocations: getAllLodgesLocation,\r\n getPaymentConfigByResort,\r\n getLeadGenConfigByResort,\r\n getCmpConfigByResort,\r\n resetLodgeConfig,\r\n updateCurrentLodge,\r\n getCartConfigByResort,\r\n getBookingWidgetConfigByResort,\r\n getGeolocationData: getGeolocationData,\r\n getPartyBookingWidgetConfigByResort\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(AppConfiguration);\r\n","// Lodge Locations Actions\r\n\r\nimport lodgeLocationsActionTypes from './lodgeLocations.types';\r\nimport LodgeApiClient from '../../../api/clients/LodgeApiClient';\r\n\r\nexport const getAllLodgesLocation = () => async dispatch => {\r\n dispatch({ type: lodgeLocationsActionTypes.CLEAR_LODGE_LOCATIONS_LOADING_CONFIG });\r\n dispatch({ type: lodgeLocationsActionTypes.GET_LODGE_LOCATIONS_LOADING, isLoading: true });\r\n\r\n try {\r\n const configurationClient = new LodgeApiClient();\r\n const result = await configurationClient.getLodgesLocations();\r\n const lodges = result.data.reduce((prev, current) => {\r\n return {\r\n ...prev,\r\n [current.id]: {\r\n address: current.Address,\r\n booking_phone: current.PhoneNumber,\r\n display: current.Name,\r\n shortDisplayName: current.Name,\r\n mobile_booking_phone: current.MobileBookingPhone,\r\n phone: current.PhoneNumber,\r\n operaCode: current.id,\r\n url: current.ShortName,\r\n region: current.Region,\r\n birthdayEmail: current.BirthdayEmail,\r\n maxOccupancy: current.MaxOccupancy\r\n }\r\n };\r\n }, {});\r\n\r\n dispatch({\r\n type: lodgeLocationsActionTypes.GET_LODGE_LOCATIONS_SUCCESS,\r\n locationList: lodges\r\n });\r\n dispatch({ type: lodgeLocationsActionTypes.GET_LODGE_LOCATIONS_LOADING, isLoading: false });\r\n } catch (error) {\r\n dispatch({\r\n type: lodgeLocationsActionTypes.GET_LODGE_LOCATIONS_ERROR,\r\n locationList: {},\r\n requestFailed: true,\r\n errorMessage: `Oops, ${error.message}`\r\n });\r\n dispatch({ type: lodgeLocationsActionTypes.GET_LODGE_LOCATIONS_LOADING, isLoading: false });\r\n }\r\n};\r\n","// Import types\r\nimport geolocationActionTypes from './geolocation.types';\r\n\r\n// Import API client\r\nimport GeolocationApiClient from '../../../api/clients/GeolocationApiClient';\r\n\r\nexport const getGeolocationData = () => async dispatch => {\r\n try {\r\n const apiClient = new GeolocationApiClient();\r\n const configurationData = await apiClient.getGeolocationData();\r\n dispatch({\r\n type: geolocationActionTypes.GET_GEOLOCATION,\r\n geolocationData: configurationData.data\r\n });\r\n } catch (error) {\r\n console.log(error);\r\n dispatch({\r\n type: geolocationActionTypes.GET_GEOLOCATION_ERROR,\r\n geolocationData: error\r\n });\r\n }\r\n};\r\n","import styled from 'styled-components';\r\nimport { Box } from '../../ui-kit';\r\nimport theme from '../../ui-kit/themes/theme';\r\n\r\n// Cart Container\r\nexport const CartCustomContainer = styled(Box)`\r\n position: relative;\r\n max-width: 24px;\r\n max-height: 24px;\r\n margin: 0 auto;\r\n ${theme.mediaQueries.md} {\r\n max-width: 32px;\r\n max-height: 32px;\r\n }\r\n`;\r\n","export const CART_ID_DESKTOP = 'cart-container-desktop';\r\nexport const CART_ID_MOBILE = 'cart-container-mobile';\r\n","import PropTypes from 'prop-types';\r\nimport React, { useEffect } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { connect } from 'react-redux';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { getIsCartActive } from '../../store/componentStores/LodgeConfig/lodgeConfig.selectors';\r\nimport { TESTS_DICTIONARY, getTestValueAB } from '../../utilities/ABTesting';\r\nimport { PlanSummary } from '../Summary';\r\nimport { SUMMARY_CART_VARIATIONS } from '../Summary/components/Suite/utilities/constants';\r\nimport theme from '../ui-kit/themes/theme';\r\nimport { CartCustomContainer } from './assets/styles';\r\nimport { CART_ID_DESKTOP, CART_ID_MOBILE } from './utilities/constants';\r\n// Portal Component\r\nconst CartPortal = ({ children }) => {\r\n const isMobile = useMediaQuery({\r\n query: `(max-width: ${theme.breakpoints.xl})`\r\n });\r\n const cartContainer = document.getElementById(isMobile ? CART_ID_MOBILE : CART_ID_DESKTOP);\r\n if (!cartContainer) return null;\r\n\r\n return <>{createPortal(children, cartContainer)}>;\r\n};\r\n\r\n// Main Component\r\n// Rules:\r\n// 1. This component can be connected to the store.\r\n// 2. Will load the summary on cart variant and will be displayed on the cart portal.\r\n\r\nconst propTypes = {\r\n location: PropTypes.object,\r\n isCartActive: PropTypes.bool\r\n};\r\n\r\nconst defaultProps = {\r\n location: null,\r\n isCartActive: false\r\n};\r\n\r\nconst CartContainer = ({ location, isCartActive }) => {\r\n useEffect(() => {\r\n const mobileIcon = document.getElementById(CART_ID_MOBILE);\r\n if (mobileIcon && isCartActive) {\r\n document.getElementById(CART_ID_MOBILE).style.width = '24px';\r\n document.getElementById(CART_ID_MOBILE).style.height = '24px';\r\n }\r\n }, [isCartActive]);\r\n\r\n // return null if cart is not active and avoid portal rendering\r\n if (!isCartActive || !location) return null;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nCartContainer.propTypes = propTypes;\r\nCartContainer.defaultProps = defaultProps;\r\n\r\nconst mapStateToProps = state => ({\r\n location: state.router.location,\r\n isCartActive: getIsCartActive(state.lodgeConfig) && getTestValueAB(TESTS_DICTIONARY.optimizelyCartFlow, false)\r\n});\r\n\r\nexport default connect(mapStateToProps, null)(CartContainer);\r\n","export const FLOATING_MESSAGE_IMAGES = {\r\n WARNING: 'warning.svg',\r\n SUCCESS_BLUE: 'success-blue.svg'\r\n};\r\n","import styled, { keyframes, css } from 'styled-components';\r\n\r\nimport { Flex, Text, Box } from '../../ui-kit';\r\nimport theme from '../../ui-kit/themes/theme';\r\n\r\nconst breatheAnimationDesk = keyframes`\r\n 0% { top: 0px; opacity: 0}\r\n\r\n 100% { top: 117px; opacity: 1; }\r\n`;\r\n\r\nconst breatheAnimationDMobile = keyframes`\r\n 0% { top: 0px; opacity: 0}\r\n\r\n 100% { top: 80px; opacity: 1; }\r\n`;\r\n\r\nexport const FloatingMessageContainer = styled(Flex)`\r\n z-index: 9999;\r\n position: fixed;\r\n flex-direction: row;\r\n max-width: 791px;\r\n min-height: 56px;\r\n padding: ${theme.space[3]}px;\r\n border-radius: 8px;\r\n\r\n ${({ variant }) => {\r\n switch (variant) {\r\n case 'error':\r\n return css`\r\n border: solid 1px ${theme.colors.digitalBrightRed[100]};\r\n background-color: ${theme.colors.digitalBrightRed[10]};\r\n `;\r\n default:\r\n return css`\r\n border: solid 1px ${theme.colors.kiddiePoolBlue[100]};\r\n background-color: ${theme.colors.kiddiePoolBlue[10]};\r\n `;\r\n }\r\n }};\r\n\r\n width: 90%;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n top: 80px;\r\n justify-content: space-between;\r\n align-items: flex-start;\r\n animation-name: ${breatheAnimationDMobile};\r\n animation-duration: 2s;\r\n\r\n ${theme.mediaQueries.md} {\r\n top: 117px;\r\n animation-name: ${breatheAnimationDesk};\r\n width: 100%;\r\n align-items: center;\r\n }\r\n`;\r\n\r\nexport const FloatingMessageImg = styled.img`\r\n margin-right: ${theme.space[3]}px;\r\n`;\r\n\r\nexport const FloatingInnerMessageContainer = styled(Flex)`\r\n align-items: flex-start;\r\n\r\n ${theme.mediaQueries.md} {\r\n align-items: center;\r\n }\r\n`;\r\n\r\nexport const InnerMessage = styled(Text)`\r\n font-family: Montserrat;\r\n font-size: 14px;\r\n font-weight: 500;\r\n font-stretch: normal;\r\n font-style: normal;\r\n line-height: 1.43;\r\n letter-spacing: normal;\r\n color: #333;\r\n`;\r\n\r\nexport const CloseFloatingMessage = styled(Box)`\r\n width: 16px;\r\n height: 16px;\r\n cursor: pointer;\r\n & > svg {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n ${theme.mediaQueries.md} {\r\n width: 24px;\r\n height: 24px;\r\n & > svg {\r\n width: 24px;\r\n height: 24px;\r\n }\r\n }\r\n`;\r\n","import React, { useCallback, useEffect, useState } from 'react';\r\nimport { ASSETS_LOCATIONS, getAssetsUrl } from '../../utilities/constants';\r\nimport CloseIcon from '../ui-kit/icons/Close';\r\nimport { FLOATING_MESSAGE_IMAGES } from './assets/images';\r\nimport {\r\n CloseFloatingMessage,\r\n FloatingInnerMessageContainer,\r\n FloatingMessageContainer,\r\n FloatingMessageImg,\r\n InnerMessage\r\n} from './assets/styles';\r\nimport * as COPY from './utilities/copy';\r\n\r\nconst FloatingMessage = () => {\r\n const [innerMessage, setInnerMessage] = useState('');\r\n const [messageVariant, setMessageVariant] = useState('success');\r\n const [onCloseFunction, setOnCloseFunction] = useState(null);\r\n const [visible, setVisible] = useState(false);\r\n\r\n const showFloatingMessage = e => {\r\n if (e.detail) {\r\n const { message, variant, onCloseFunction } = e.detail;\r\n if (message) setInnerMessage(message);\r\n if (variant) setMessageVariant(variant);\r\n if (onCloseFunction) setOnCloseFunction(() => () => onCloseFunction());\r\n }\r\n setVisible(true);\r\n };\r\n\r\n const closeFloatingMessage = useCallback(() => {\r\n setVisible(false);\r\n if (onCloseFunction) onCloseFunction();\r\n }, [onCloseFunction]);\r\n\r\n useEffect(() => {\r\n window.addEventListener('floating-message', showFloatingMessage);\r\n return function cleanupListener() {\r\n window.removeEventListener('floating-message', showFloatingMessage, false);\r\n };\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!visible) return;\r\n const timer = setTimeout(() => {\r\n closeFloatingMessage();\r\n }, 10000);\r\n return () => clearTimeout(timer);\r\n }, [visible, closeFloatingMessage]);\r\n\r\n return (\r\n <>\r\n {visible && (\r\n \r\n \r\n \r\n\r\n {innerMessage}\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n >\r\n );\r\n};\r\n\r\nexport default FloatingMessage;\r\n","export const SUCCESS_ICON = 'success icon';\r\nexport const ERROR_ICON = 'error icon';\r\n","// TODO - revisit this component to fix how hooks are working\r\n/* eslint-disable react-hooks/exhaustive-deps */\r\nimport { useEffect } from 'react';\r\nimport { connect } from 'react-redux';\r\nimport { setIEModalAlreadyShown } from '../../store/componentStores/IEModal/ieModal.actions';\r\nimport { MODAL_KEYS } from '../GlobalModal/modalSource';\r\nimport withGlobalModal from '../GlobalModal/withGlobalModal';\r\n\r\nconst IEModal = ({ isAlreadyShown, setIEModalAlreadyShown, openModal }) => {\r\n useEffect(() => {\r\n const userAgent = window.navigator.userAgent;\r\n const isIEBrowser = userAgent.indexOf('MSIE ') > -1 || userAgent.indexOf('Trident/') > -1;\r\n\r\n if (isIEBrowser && !isAlreadyShown) {\r\n openModal(\r\n {\r\n keyContentComponent: MODAL_KEYS.IE_MODAL,\r\n params: {}\r\n },\r\n true\r\n );\r\n setIEModalAlreadyShown(true);\r\n }\r\n }, []);\r\n\r\n return null;\r\n};\r\n\r\nconst mapStateToProps = state => ({\r\n ...state.ieModal\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n setIEModalAlreadyShown\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(withGlobalModal(IEModal));\r\n","// IEModal actions\r\n\r\nimport ieModalActionTypes from './ieModal.types';\r\n\r\nexport const setIEModalAlreadyShown = params => dispatch => {\r\n dispatch({\r\n type: ieModalActionTypes.SET_IEMODAL_IS_ALREADY_SHOWN,\r\n isAlreadyShown: params\r\n });\r\n};\r\n","import { createGlobalStyle } from 'styled-components';\r\nimport { colors, fontWeights } from './components/ui-kit/themes/theme';\r\nconst GlobalStyle = createGlobalStyle`\r\n *,\r\n *:after,\r\n *:before {\r\n box-sizing: border-box;\r\n }\r\n *[data-accordion-component='AccordionItemButton']:focus {\r\n outline: 0;\r\n }\r\n\r\n .sticky-bottom {\r\n transform: translateX(calc(50vw - 110px)) !important;\r\n z-index: 700 !important;\r\n top: unset !important;\r\n left: unset !important;\r\n bottom: 90px !important;\r\n }\r\n\r\n .gpay-card-info-container {\r\n border-radius: 35px!important;\r\n }\r\n\r\n .DateRangePicker, .DayPicker {\r\n font-family: Montserrat;\r\n border-radius: 5px;\r\n }\r\n .DateRangePicker_picker {\r\n z-index: 7000;\r\n border-radius: 5px;\r\n }\r\n\r\n .DateRangePicker_picker__fullScreenPortal {\r\n z-index: 9000;\r\n }\r\n\r\n .DateInput_fang {\r\n z-index: 8000;\r\n margin-top: 2px;\r\n top: -28px;\r\n }\r\n table.CalendarMonth_table {\r\n border-collapse: unset;\r\n }\r\n td.CalendarDay__default {\r\n font-weight: bold;\r\n border: 2px solid transparent;\r\n color: ${colors.nightSkyBlack[80]};\r\n border-collapse: unset;\r\n border-radius: 4px;\r\n\r\n &:hover {\r\n background: transparent;\r\n border: none;\r\n }\r\n }\r\n\r\n td.CalendarDay__selected {\r\n &,\r\n &:active,\r\n &:hover {\r\n background: ${colors.deepLakeBlue[100]};\r\n border: 2px solid transparent;\r\n color: ${colors.pureWhite[0]} !important;\r\n }\r\n }\r\n\r\n td.CalendarDay__hovered_span,\r\n td.CalendarDay__selected_span {\r\n &,\r\n &:hover {\r\n background: transparent;\r\n color: ${colors.nightSkyBlack[80]};\r\n border-radius: 0;\r\n }\r\n &:hover {\r\n border-radius: 4px;\r\n }\r\n }\r\n\r\n ul.DayPicker_weekHeader_ul {\r\n font-weight: ${fontWeights.bold};\r\n }\r\n\r\n div.DayPickerNavigation_button__default {\r\n border: none;\r\n color: ${colors.digitalBrightRed[100]};\r\n }\r\n\r\n svg.DayPickerNavigation_svg__horizontal {\r\n fill: ${colors.digitalBrightRed[100]};\r\n }\r\n input.DateInput_input__focused {\r\n border-bottom: 2px solid ${colors.digitalBrightRed[100]};\r\n }\r\n td.CalendarDay__blocked_calendar,\r\n td.CalendarDay__blocked_calendar:active,\r\n td.CalendarDay__blocked_calendar:hover {\r\n background: none;\r\n border: none;\r\n color: ${colors.nightSkyBlack[60]};\r\n }\r\n\r\n td.CalendarDay__blocked_out_of_range,\r\n td.CalendarDay__blocked_out_of_range:active,\r\n td.CalendarDay__blocked_out_of_range:hover {\r\n color: ${colors.deepLakeBlue[20]};\r\n }\r\n\r\n .accordion__body {\r\n display: block;\r\n }\r\n\r\n .accordion__body--hidden {\r\n display: none;\r\n }\r\n\r\n .accordion__title {\r\n cursor: pointer;\r\n }\r\n\r\n .accordion__arrow {\r\n transition: transform 0.25s ease;\r\n }\r\n\r\n [aria-expanded='true'] .accordion__arrow,\r\n [aria-selected='true'] .accordion__arrow {\r\n transform: rotate(-180deg);\r\n }\r\n .ReactModal__Overlay {\r\n z-index: 2\r\n }\r\n \r\n body.ReactModal__Body--open {\r\n\r\n }\r\n\r\n input[type=button], input[type=search] {\r\n -webkit-appearance: none;\r\n }\r\n\r\n select[multiple] {\r\n min-height: 55px;\r\n }\r\n`;\r\n\r\nexport default GlobalStyle;\r\n","import React, { lazy, Suspense, useEffect, useMemo } from 'react';\r\nimport Modal from 'react-modal';\r\nimport { useMediaQuery } from 'react-responsive';\r\nimport { Switch, withRouter } from 'react-router';\r\nimport { Route, useLocation } from 'react-router-dom';\r\nimport uuidv4 from 'uuid/v4';\r\nimport AppConfiguration from './components/AppConfiguration/AppConfiguration';\r\nimport { CartContainer } from './components/Cart';\r\nimport FloatingMessage from './components/FloatingMessage/FloatingMessage';\r\nimport IEModal from './components/IEModal';\r\nimport theme from './components/ui-kit/themes/theme';\r\nimport { FLOW_NAMES } from './flows/DynamicFlow/utilities/constants';\r\nimport GlobalStyle from './GlobalStyle';\r\nimport routes from './routes';\r\nimport withAppInsights from './utilities/applicationInsights';\r\nimport { checkCookie, getCookie, setCookie } from './utilities/cookiesUtils';\r\nimport isAuthorMode from './utilities/isAuthorMode';\r\n\r\nconst DynamicFlow = lazy(() => import(/* webpackChunkName: \"DynamicFlow\" */ './flows/DynamicFlow/DynamicFlow'));\r\n\r\nconst BookTab = lazy(() => import(/* webpackChunkName: \"BookTab\" */ './components/BookTab/index'));\r\nconst EmailCapture = lazy(() => import(/* webpackChunkName: \"EmailCapture\" */ './components/EmailCapture'));\r\nconst AppLayout = lazy(() => import(/* webpackChunkName: \"AppLayout\" */ './layouts/AppLayout'));\r\nconst SummaryLayout = lazy(() => import(/* webpackChunkName: \"SummaryLayout\" */ './layouts/SummaryLayout'));\r\nconst NoMatchLayout = lazy(() => import(/* webpackChunkName: \"NoMatchLayout\" */ './layouts/NoMatchLayout'));\r\nconst HeaderWithTwoColumnLayout = lazy(() =>\r\n import(/* webpackChunkName: \"HeaderWithTwoColumnLayout\" */ './layouts/HeaderWithTwoColumnLayout')\r\n);\r\nconst NavigationMenuLayout = lazy(() =>\r\n import(\r\n /* webpackChunkName: \"NavigationMenuLayout\" */\r\n './layouts/NavigationMenuLayout'\r\n )\r\n);\r\nconst DayPassesPicker = lazy(() =>\r\n import(/* webpackChunkName: \"DayPassesPicker\" */ './components/DayPasses/DayPassesPicker')\r\n);\r\nconst DayPassesHeader = lazy(() =>\r\n import(/* webpackChunkName: \"DayPassesHeader\" */ './components/DayPasses/DayPassesHeader')\r\n);\r\nconst DayPassesInformation = lazy(() =>\r\n import(/* webpackChunkName: \"DayPassesInformation\" */ './components/DayPasses/DayPassesInformation')\r\n);\r\nconst PaymentForm = lazy(() => import(/* webpackChunkName: \"PaymentForm\" */ './components/PaymentForm'));\r\nconst GlobalModal = lazy(() => import(/* webpackChunkName: \"GlobalModal\" */ './components/GlobalModal'));\r\nconst PlanSearchForm = lazy(() => import(/* webpackChunkName: \"PlanSearchForm\" */ './components/PlanSearchForm'));\r\nconst BirthdaySearchFormRouter = lazy(() =>\r\n import(/* webpackChunkName: \"BirthdaySearchFormRouter\" */ './components/BirthdaySearchForm/BirthdaySearchFormRouter')\r\n);\r\nconst PreCheckIn = lazy(() => import(/* webpackChunkName: \"Reservation\" */ './pages/PreCheckIn'));\r\nconst Reservations = lazy(() => import(/* webpackChunkName: \"Reservations\" */ './pages/Reservations'));\r\nconst MyReservations = lazy(() =>\r\n import(/* webpackChunkName: \"MyReservations\" */ './pages/Reservations/MyReservations')\r\n);\r\nconst SearchReservations = lazy(() =>\r\n import(/* webpackChunkName: \"SearchReservations\" */ './pages/Reservations/SearchReservations')\r\n);\r\nconst ReferAFriendPage = lazy(() => import(/* webpackChunkName: \"ReferAFriend\" */ './pages/User/ReferAFriendPage'));\r\nconst UserProfile = lazy(() => import(/* webpackChunkName: \"UserProfile\" */ './pages/User/Profile'));\r\nconst EventCalendar = lazy(() => import(/* webpackChunkName: \"EventCalendar\" */ './pages/EventCalendar'));\r\nconst MyRecentSearches = lazy(() =>\r\n import(/* webpackChunkName: \"MyRecentSearches\" */ './pages/RecentSearches/MyRecentSearches')\r\n);\r\nconst ChangePassword = lazy(() => import(/* webpackChunkName: \"ChangePassword\" */ './pages/ChangePassword'));\r\nconst UpdatePassword = lazy(() =>\r\n import(/* webpackChunkName: \"UpdatePassword\" */ './pages/ChangePassword/UpdatePassword')\r\n);\r\nconst UnlockAccount = lazy(() => import(/* webpackChunkName: \"UnlockAccount\" */ './pages/UnlockAccount'));\r\nconst ReservationDetail = lazy(() => import(/* webpackChunkName: \"ReservationDetail\" */ './pages/ReservationDetail'));\r\nconst MyReservationsPage = lazy(() => import(/* webpackChunkName: \"MyReservationsPage\" */ './pages/MyReservations'));\r\nconst MyPreferences = lazy(() => import(/* webpackChunkName: \"MyPreferences\" */ './pages/User/Preferences'));\r\n\r\nconst DaypassBooking = lazy(() => import(/* webpackChunkName: \"DaypassBooking\" */ './pages/Daypass/DaypassBooking'));\r\nconst LandingPageForm = lazy(() => import(/* webpackChunkName: \"LandingPageForm\" */ './pages/Loyalty/LandingPageForm'));\r\nconst EmailQueuePage = lazy(() => import(/* webpackChunkName: \"LandingPageForm\" */ './pages/EmailQueue'));\r\nconst MysteryModal = lazy(() => import(/* webpackChunkName: \"MysteryModal\" */ './components/MysteryModal'));\r\nconst EventPlanner = lazy(() => import(/* webpackChunkName: \"EventPlanner\" */ './pages/EventPlanner'));\r\nconst Folio = lazy(() => import(/* webpackChunkName: \"Folio\" */ './pages/Folio'));\r\nconst IframeHandler = lazy(() => import(/* webpackChunkName: \"IframeHandler\" */ './pages/IframeHandler'));\r\n\r\nModal.setAppElement(document.getElementById('root'));\r\n\r\nconst App = ({ history, flowName }) => {\r\n if (!flowName) console.warn('No flowName attribute found in HTML');\r\n const flowAudience = window.flowAudience ?? 'ALL';\r\n\r\n console.log('FLOW_NAMES.birthday', FLOW_NAMES.BIRTHDAY);\r\n\r\n history.listen(() => {\r\n // It'll be used by the AOS library being used in the AEM project\r\n // that needs to trigger the footer animation when we're switching\r\n // between React routes\r\n window.dispatchEvent(new Event('resize'));\r\n });\r\n const { search } = useLocation();\r\n const searchParams = useMemo(() => new URLSearchParams(search), [search]);\r\n\r\n useEffect(() => {\r\n //This if statement to setup the did cookie\r\n //==========================================\r\n if (!checkCookie('did')) {\r\n setCookie('did', uuidv4(), 3650);\r\n }\r\n //This if statement is to setup the eid cookie\r\n //=============================================\r\n if (searchParams.get('eid') !== null) {\r\n //If the eid query string exists and the eid cookie doesn't exits create one\r\n //===========================================================================\r\n if (!checkCookie('eid')) setCookie('eid', searchParams.get('eid'), 3650);\r\n //If eid cookie exists but is different from the query string update the cookie with the query string\r\n //====================================================================================================\r\n if (\r\n getCookie('eid') !== null &&\r\n searchParams.get('eid') !== null &&\r\n searchParams.get('eid') !== getCookie('eid')\r\n ) {\r\n setCookie('eid', searchParams.get('eid'), 3650);\r\n }\r\n }\r\n //This if statement is to setup the pastGuest cookie\r\n //===================================================\r\n if (searchParams.get('pg') !== null) {\r\n //If the pg query string exists and the pastGuest cookie doesn't exits create one\r\n //==================================================================================\r\n if (!checkCookie('pastGuest')) setCookie('pastGuest', searchParams.get('pg'), 3650);\r\n //If pastGuest cookie exists but has different value from the pg from the query string it will update the cookie\r\n //===============================================================================================================\r\n if (\r\n getCookie('pastGuest') !== null &&\r\n searchParams.get('pg') !== null &&\r\n searchParams.get('pg') !== getCookie('pastGuest')\r\n ) {\r\n setCookie('pastGuest', searchParams.get('pg'), 3650);\r\n }\r\n }\r\n }, [history.location.pathname, searchParams]);\r\n\r\n const isTablet = useMediaQuery({ maxWidth: theme.breakpoints.lg });\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n
}>\r\n {searchParams.get('mystery') === 'true' ? : null}\r\n \r\n \r\n \r\n {!isAuthorMode() && }\r\n\r\n \r\n \r\n \r\n {\r\n return (\r\n \r\n );\r\n }}\r\n />\r\n {\r\n return ;\r\n }}\r\n />\r\n {\r\n return (\r\n \r\n );\r\n }}\r\n />\r\n {\r\n return (\r\n \r\n );\r\n }}\r\n />\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {\r\n return (\r\n <>\r\n \r\n \r\n >\r\n );\r\n }}\r\n />\r\n \r\n\r\n {/* This layout is the catch-all for non-Plan components that still renders dynamic features on AEM */}\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default withAppInsights(withRouter(App));\r\n","import 'react-app-polyfill/ie11';\r\nimport 'react-app-polyfill/stable';\r\n\r\n/**\r\n * Exposes mock data that should come from AEM to the global object\r\n * Note this needs to be at the top level so is accessible by all other\r\n * imported modules.\r\n */\r\nimport './data/birthdayPartyTimesAndLocationsJson';\r\nimport './data/bookingEngineAlert';\r\nimport './data/location';\r\nimport './data/mysteryDealPromoList';\r\nimport './data/promoCodeListJson';\r\n// end of mock data\r\n\r\nimport { ConnectedRouter } from 'connected-react-router';\r\nimport React from 'react';\r\nimport 'react-block-ui/style.css';\r\nimport 'react-dates/initialize';\r\n// Importing react-dates CSS as per the 'webpack' section of their documentation: https://github.com/react-dates/react-dates?tab=readme-ov-file#webpack\r\nimport 'react-dates/lib/css/_datepicker.css';\r\nimport ReactDOM from 'react-dom';\r\nimport { Provider } from 'react-redux';\r\nimport { ThemeProvider } from 'styled-components';\r\nimport ScrollToTop from './ScrollToTop';\r\nimport theme from './components/ui-kit/themes/theme';\r\nimport './index.css';\r\nimport './infrastructure/interceptors/axios_interceptors';\r\nimport * as serviceWorker from './serviceWorker';\r\nimport { history, store } from './store/configureStore';\r\n\r\n//App is the main component and needs to be imported last\r\n//TEMPORARY FIX, the main issue is a circular dependency between the store and the App component\r\nimport App from './App';\r\n\r\n// const persistedState = loadState();\r\nconst rootElement = document.getElementById('root');\r\nconst bookingEngineElement = document.getElementById('booking-engine');\r\nconst flowName = bookingEngineElement?.getAttribute('data-flow') ?? rootElement?.getAttribute('data-flow');\r\n\r\nReactDOM.render(\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ,\r\n rootElement\r\n);\r\n\r\n// If you want your app to work offline and load faster, you can change\r\n// unregister() to register() below. Note this comes with some pitfalls.\r\n// Learn more about service workers: http://bit.ly/CRA-PWA\r\nserviceWorker.unregister();\r\n"],"sourceRoot":""}