= ({\n asLink,\n to,\n children,\n sameTab = false,\n style,\n}) => (\n \n {asLink ? (\n {children}\n ) : (\n \n {children}\n \n )}\n \n)\n\nexport default LinkOrA\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport Price from '../../../pricing/Price'\nimport LineItemLabel from '../../../pricing/LineItemLabel'\n\nconst Table = styled.table`\n width: 100%;\n min-width: 216px;\n text-align: left;\n\n tfoot {\n font-weight: normal;\n }\n\n td {\n padding: 8px 0;\n &:last-child {\n text-align: right;\n }\n }\n`\n\nconst CardPricingBreakdown = ({ pricing, pricingSuffix }) => (\n \n \n {pricing?.lineItems?.map((item, index) => (\n // eslint-disable-next-line react/no-array-index-key\n \n \n \n | \n \n \n | \n
\n ))}\n {pricing?.customerServiceFee > 0 && (\n \n \n Service Fee\n | \n \n \n | \n
\n )}\n {pricing?.taxAmount > 0 && (\n \n \n Tax\n | \n \n \n | \n
\n )}\n \n
\n)\n\nexport default CardPricingBreakdown\n","import React from 'react'\nimport styled from 'styled-components'\nimport truncate from 'lodash/truncate'\n\nimport useFeatureFlag from 'hooks/useFeatureFlag'\nimport { simplifiedCardTitle } from 'featureFlags'\nimport Tooltip from 'components/display/Tooltip'\nimport InstantBookBadge from 'components/display/InstantBookBadge'\nimport ReviewScore from 'components/reviews/ReviewScore'\nimport { formatPrice } from 'components/utils/pricing'\nimport InfoOutline from 'components/icons/InfoOutline'\n\nimport LinkOrA from '../LinkOrA'\nimport { Location, Title } from '../styled'\n\nimport CardPricingBreakdown from './CardPricingBreakdown'\n\nconst PricingWrapper = styled.div<{ compact?: boolean }>`\n display: flex;\n justify-content: ${({ compact }) =>\n compact ? 'space-between' : 'flex-start'};\n align-items: ${({ compact }) => (compact ? 'center' : 'flex-start')};\n`\n\nconst Price = styled.div`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n text-align: right;\n color: ${({ theme }) => theme?.['-ds-neutral-600']?.value};\n\n strong {\n display: inline-flex;\n align-items: center;\n font-weight: 500;\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n }\n`\n\nconst PriceLarge = styled.div`\n min-width: 85px;\n\n strong {\n margin-bottom: 4px;\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-md']?.['font-size']?.value};\n }\n`\n\nconst PriceCompact = styled.div`\n display: flex;\n align-items: center;\n\n strong {\n margin-right: 5px;\n }\n`\n\nconst PriceDetails = styled.span`\n display: flex;\n align-items: center;\n justify-content: flex-end;\n\n svg {\n top: -2px;\n position: relative;\n }\n`\n\ntype PricingLineItem = {\n typename?: 'LineItem'\n itemType: string\n quantity: number\n price: number\n amount: number\n}\n\ntype PricingProps = {\n price: number\n pricing?: {\n typename?: 'Pricing'\n total?: number\n lineItems?: PricingLineItem[]\n customerServiceFee?: number\n }\n pricingSuffix: string\n nicePricingSuffix: string\n instantBookEnabled?: boolean\n compact?: boolean\n}\n\nconst Pricing = ({\n price,\n pricing,\n pricingSuffix,\n nicePricingSuffix,\n instantBookEnabled,\n compact,\n}: PricingProps) => {\n const totalPrice = pricing ? pricing?.total : price\n\n return (\n \n \n {instantBookEnabled && }\n {formatPrice(totalPrice, 0)}\n \n {pricing ? (\n \n total\n }>\n \n \n \n ) : (\n {nicePricingSuffix}
\n )}\n \n )\n}\n\ntype ListingDetailsProps = {\n title: string\n capacity: number\n locationName: string\n city: string\n reviewScore?: string\n subcategory: {\n id: string\n name: string\n }\n linkOptions: {\n url: string\n asLink?: boolean\n sameTab?: boolean\n }\n compact?: boolean\n simplifiedTitleFlag?: boolean\n} & PricingProps\n\nconst ListingDetails = ({\n title,\n capacity,\n locationName,\n city,\n reviewScore,\n subcategory,\n price,\n pricing,\n pricingSuffix,\n nicePricingSuffix,\n instantBookEnabled,\n linkOptions,\n compact,\n simplifiedTitleFlag = false,\n}: ListingDetailsProps) => {\n const { url, asLink, sameTab } = linkOptions\n const listingScore = parseFloat(reviewScore)\n\n const listingTitle = simplifiedTitleFlag\n ? `${subcategory.name} in ${city}`\n : title\n\n return (\n <>\n \n \n \n {compact ? truncate(listingTitle, { length: 65 }) : listingTitle}\n \n \n {!simplifiedTitleFlag && `${compact ? city : locationName} • `}\n Sleeps {capacity}\n \n {listingScore > 0 && !compact && (\n \n )}\n \n
\n\n \n \n {listingScore > 0 && compact && (\n \n )}\n \n >\n )\n}\n\nconst withFeatureFlags = >(\n Component: React.ComponentType
\n) => (props: P) => {\n const simplifiedTitleFlag = useFeatureFlag(simplifiedCardTitle)\n const { compact } = props\n\n return (\n \n )\n}\n\nexport default withFeatureFlags(ListingDetails)\n","import { useContext } from 'react'\n\nimport DescendantOfMapContext from '../contexts/DescendantOfMapContext'\n\nconst useIsDescendantOfMap = () => {\n const isDescendantOfMap = useContext(DescendantOfMapContext)\n return isDescendantOfMap\n}\n\nexport default useIsDescendantOfMap\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport useIsDescendantOfMap from 'hooks/useIsDescendantOfMap'\n\ntype MediaWrapperOptions = {\n portrait?: boolean\n rounded?: boolean\n}\n\nconst MediaWrapper = styled.div`\n position: relative;\n overflow: hidden;\n width: 100%;\n height: 0;\n\n /* css way of maintaining aspect ratio with reference to width */\n padding-top: ${({ portrait }) => (portrait ? '125%' : '72.222%')};\n\n ${({ rounded = true }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n background-color: #ddd;\n\n transform: translate3d(0, 0, 0);\n`\n\nexport const MediaWrapperOrientated: React.FC<\n React.ComponentProps & { portrait?: boolean }\n> = ({ children, portrait: portraitProp, ...props }) => {\n const isDescendantOfMap = useIsDescendantOfMap()\n\n const portrait = portraitProp === true && isDescendantOfMap !== true\n\n return (\n \n {children}\n \n )\n}\n\nexport default MediaWrapper\n","import styled from 'styled-components'\n\nimport { media } from '../../../styles/media'\n\nexport const BucketListButton = styled.button.attrs(\n ({ isActive, ...props }: { isActive?: boolean; 'aria-label'?: string }) => {\n if (props['aria-label']) {\n return {\n 'aria-label': props['aria-label'],\n }\n }\n\n return {\n 'aria-label': isActive ? 'Remove from bucket list' : 'Add to bucket list',\n }\n }\n)<{\n left?: boolean\n isActive?: boolean\n rounded?: boolean\n}>`\n position: absolute;\n appearance: none;\n border: none;\n outline: none;\n background: transparent;\n\n width: 55px;\n height: 55px;\n\n margin: 0;\n\n position: absolute;\n top: 0;\n\n ${({ rounded }) =>\n rounded !== false &&\n `\n border-radius: 6px;\n `}\n\n ${({ left }) =>\n left\n ? `\n left: 0;\n `\n : `\n right: 0;\n `}\n\n color: white;\n\n svg {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n\n width: 32px;\n height: 32px;\n\n transition: color 150ms ease-out;\n\n &:first-child {\n color: rgba(0, 0, 0, 0.3);\n }\n }\n\n ${({ isActive }) =>\n isActive &&\n `\n svg:first-child {\n color: #ebcec9;\n }\n `}\n`\n\nexport const CardWrapper = styled.div`\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n font-size: 16px;\n font-family: ${({ theme }) => theme.fonts.default};\n font-weight: 100;\n`\n\nexport const HeaderPlaceholder = styled.div<{ heightPx?: number }>`\n display: none;\n height: ${({ heightPx = 64 }) => heightPx}px;\n margin-bottom: 16px;\n\n ${media.md`\n display: block;\n `}\n`\n\nexport const Image = styled.div`\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n width: 100%;\n`\n\nexport const Details = styled.div`\n flex: 1;\n line-height: 1.6;\n\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n`\n\nexport const TitleWrapper = styled.div`\n white-space: normal;\n\n padding-right: 12px;\n`\n\nexport const HeartIcon = styled.i.attrs({\n className: 'icon icon-bucketlist-heart-on',\n})`\n margin-right: 0 !important;\n`\n\nexport const Location = styled.div<{ compact?: boolean }>`\n color: ${({ theme }) => theme?.['-ds-neutral-600']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n font-weight: 300;\n line-height: 1.4;\n margin-bottom: ${({ compact }) => (compact ? '4px' : '6px')};\n`\n\nexport const Title = styled.div<{ compact?: boolean }>`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n line-height: 1.4;\n font-weight: 400;\n margin-bottom: ${({ compact }) => (compact ? '4px' : '6px')};\n`\n\nexport const Media = styled.div`\n position: relative;\n`\n\nexport const Content = styled.div<{ compact?: boolean }>`\n display: flex;\n flex-direction: ${({ compact }) => (compact ? 'column' : 'row')};\n justify-content: space-between;\n text-align: left;\n padding: ${({ compact }) => (compact ? '8px 0' : '16px 0 32px 0')};\n`\n\nexport const Slide = styled.div`\n height: 100%;\n background-color: #ddd;\n overflow: hidden;\n`\n","import styled from 'styled-components'\nimport React from 'react'\n\nconst IconWithAttributes = styled.i`\n font-size: inherit;\n margin-right: 0.5em;\n`\n\ninterface ActivityMatchedIconProps {\n iconName?: string\n iconSize?: string\n}\n\nconst ActivityMatchedIcon = ({\n iconName,\n iconSize,\n}: ActivityMatchedIconProps) => {\n const className = `icon icon-${iconSize} icon-${iconName}`\n\n return \n}\n\nexport default ActivityMatchedIcon\n","import styled from 'styled-components'\n\nimport { media } from 'styles/media'\n\ntype Props = {\n $darkAppearance?: boolean\n}\n\nconst Alert = styled.div`\n display: flex;\n align-items: flex-start;\n\n ${media.md`\n align-items: center;\n `}\n\n padding: 16px;\n color: ${({ $darkAppearance, theme }) =>\n $darkAppearance ? theme?.['-ds-neutral-700']?.value : '#a92801'};\n background-color: ${({ $darkAppearance, theme }) =>\n $darkAppearance ? theme?.['-ds-information-100']?.value : '#fcf6f5'};\n border-radius: 8px;\n\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n\n svg {\n flex-shrink: 0;\n height: 30px;\n width: 30px;\n margin-right: 16px;\n }\n\n margin-bottom: 24px;\n`\n\nexport default Alert\n","import styled from 'styled-components'\n\nimport LazyImage from './LazyImage'\n\nconst Avatar = styled.div`\n position: relative;\n overflow: hidden;\n width: 40px;\n height: 40px;\n flex-shrink: 0;\n\n background-color: #ddd;\n border-radius: 50%;\n\n margin-right: 16px;\n\n ${LazyImage} {\n border-radius: 50%;\n }\n`\n\nexport default Avatar\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport Avatar from '../Avatar'\nimport LazyImage from '../LazyImage'\n\ntype Options = {\n avatarSize?: number\n $rightAlign?: boolean\n}\n\nconst StackedAvatar = styled(Avatar)<{ offset: number } & Options>`\n border: 2px solid ${({ theme }) => theme['-ds-neutral-200'].value};\n margin-right: 0;\n flex-shrink: 0;\n\n ${({ avatarSize }) =>\n avatarSize &&\n `\n width: ${avatarSize}px;\n height: ${avatarSize}px;\n `}\n\n &:not(:first-child) {\n ${({ offset }) => `\n transform: translateX(${offset}px);\n `}\n }\n`\n\nconst Outer = styled.div`\n display: flex;\n overflow: hidden;\n\n ${({ $rightAlign }) =>\n $rightAlign &&\n `\n flex-direction: row-reverse;\n `}\n`\n\ntype AvatarStackProps = {\n urls: string[]\n} & Options\n\nconst AvatarStack = ({ urls, avatarSize, $rightAlign }: AvatarStackProps) => {\n return (\n \n {urls.map((url, index) => {\n const baseOffset = $rightAlign ? 20 : -20\n const offset = baseOffset * index + 1\n return (\n \n \n \n )\n })}\n \n )\n}\n\nexport default AvatarStack\n","import styled from 'styled-components'\nimport { Link } from 'react-router-dom'\n\nconst BackLink = styled(Link)`\n display: block;\n margin-bottom: 20px;\n font-size: 14px;\n line-height: 40px;\n text-transform: uppercase;\n color: ${({ theme }) => theme.brand.jungle};\n`\n\nexport const BackLinkAnchor = styled.a`\n display: block;\n margin-bottom: 20px;\n font-size: 14px;\n line-height: 40px;\n text-transform: uppercase;\n color: ${({ theme }) => theme.brand.jungle};\n`\n\nexport default BackLink\n","import styled from 'styled-components'\n\nconst Badge = styled.span`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n width: 34px;\n height: 26px;\n line-height: 20px;\n margin: 0 6px;\n\n text-align: center;\n font-size: ${({ theme }) => theme['-ds-font-size-xxs']['font-size'].value};\n font-weight: 700;\n\n background-color: ${({ theme }) => theme['-ds-core-400'].value};\n border-radius: 100px;\n color: white;\n`\n\nexport default Badge\n","import styled from 'styled-components'\n\nexport default styled.span`\n font-weight: 400;\n`\n","import styled from 'styled-components'\n\nimport Button from '.'\n\nconst ButtonMedium = styled(Button)`\n padding-top: unset;\n padding-bottom: unset;\n height: 56px;\n`\n\nexport default ButtonMedium\n","import styled from 'styled-components'\n\nimport Button from '.'\n\nconst ButtonSmall = styled(Button)`\n padding-top: unset;\n padding-bottom: unset;\n height: 48px;\n`\n\nexport default ButtonSmall\n","import styled from 'styled-components'\n\n// transient props -- props we use for conditionally applying styles, but that shouldn't\n// be passed by styled-components down to the HTML elements, as they leave ugly console errors\nexport const transientProps = [\n 'active',\n 'compact',\n 'fullwidth',\n 'ghost',\n 'grey',\n 'inline',\n 'leftAlign',\n 'noBorder',\n 'noDisabledStyle',\n 'noHover',\n 'omitOpinionatedSvgStyle',\n 'rounded',\n 'roundedRight',\n 'uppercase',\n 'white',\n 'wider',\n 'warning',\n] as const\n\ntype TransientPropKeys = typeof transientProps[number]\n\ntype HTMLStringPropKeys = 'css' | 'href' | 'rel' | 'target' | 'type'\ntype HTMLBooleanPropKeys = 'disabled'\ntype HTMLPropKeys = HTMLStringPropKeys & HTMLBooleanPropKeys\n\ntype TransientProps = Record\ntype HTMLProps = Record &\n Record\n\ntype ButtonProps = Partial & {\n as?: string | React.ReactNode\n onClick?: (...args: any) => any\n style?: object\n}\n\nconst Button = styled.button\n .attrs(({ uppercase = true }: TransientProps) => ({\n uppercase,\n }))\n .withConfig({\n shouldForwardProp: (prop: TransientPropKeys & HTMLPropKeys) =>\n !transientProps.includes(prop),\n })`\n display: ${({ inline }) => (inline ? 'inline-block' : 'block')};\n padding: 1em;\n\n text-align: center;\n text-transform: ${({ uppercase }) => (uppercase ? 'uppercase' : 'inherit')};\n text-decoration: none !important;\n\n border: 1px solid transparent;\n\n font-weight: normal;\n letter-spacing: 1px;\n\n color: ${({ theme, white }) => (white ? theme.brand.jungle : 'white')};\n &:hover {\n color: ${({ theme, white }) => (white ? theme.brand.jungle : 'white')};\n }\n\n background-color: ${({ theme, disabled, white, warning }) => {\n if (disabled) {\n return theme.colors.textGreyLight\n }\n if (white) {\n return theme.colors.white\n }\n if (warning) {\n return theme?.['-ds-warning-300']?.value\n }\n return theme.brand.jungle\n }};\n\n ${({ omitOpinionatedSvgStyle }) =>\n !omitOpinionatedSvgStyle &&\n `\n svg {\n display: inline-block;\n vertical-align: sub;\n width: 20px;\n height: 20px;\n margin-right: 10px;\n }\n `}\n\n .icon {\n display: inline-block;\n vertical-align: middle;\n\n margin-top: -4px;\n margin-right: 8px;\n\n font-size: 24px;\n line-height: 1;\n }\n\n .icon-bucketlist-heart-on {\n color: #ff748c;\n }\n\n ${({ noHover }) =>\n !noHover &&\n `\n &:hover {\n text-decoration: none;\n cursor: pointer;\n }\n `};\n\n ${({ theme, ghost }) =>\n ghost &&\n `\n color: ${theme.brand.jungle};\n &:hover {\n color: ${theme.brand.jungle};\n }\n background-color: transparent;\n border: 1px solid currentColor;\n `};\n\n ${({ theme, ghost, disabled }) =>\n ghost &&\n disabled &&\n `\n color: ${theme.colors.textGreyLight};\n background-color: transparent;\n border: 1px solid currentColor;\n cursor: not-allowed;\n &:hover {\n color: ${theme.colors.textGreyLight} !important;\n border: 1px solid currentColor;\n cursor: not-allowed;\n }\n `};\n\n ${({ theme, noDisabledStyle }) =>\n noDisabledStyle &&\n `\n background-color: ${theme.brand.jungle};\n `};\n\n ${({ grey }) =>\n grey &&\n `\n background-color: #d6d6d6;\n `};\n\n ${({ wider }) =>\n wider &&\n `\n padding: 1em 2em;\n `};\n\n ${({ noBorder }) =>\n noBorder &&\n `\n border: 0;\n `};\n\n ${({ fullwidth }) =>\n fullwidth &&\n `\n width: 100%;\n `};\n\n ${({ leftAlign }) =>\n leftAlign &&\n `\n text-align: left;\n `};\n\n ${({ compact }) =>\n compact &&\n `\n padding: .75em 1em;\n `};\n\n ${({ roundedRight }) =>\n roundedRight &&\n `\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n `}\n\n ${({ rounded }) => {\n if (rounded === false) {\n return 'border-radius: 0;'\n }\n\n return 'border-radius: 6px;'\n }};\n\n ${({ disabled }) =>\n disabled &&\n `\n pointer-events: none;\n `};\n`\n\nexport default Button\n","import styled from 'styled-components'\nimport Button from './Button'\n\nconst ButtonLink = styled(Button.withComponent('a')).attrs(({ target }) => ({\n target,\n rel: target === '_blank' ? 'noopener noreferrer' : undefined,\n}))`\n /* overwriting bootstrap hover styles */\n &:hover {\n color: ${({ ghost, theme, white }) =>\n ghost || white ? theme?.['-ds-core-400']?.value : 'white'};\n }\n`\n\nexport default ButtonLink\n","import React from 'react'\nimport { useHistory } from 'react-router'\n\nimport Button from './Button'\n\ntype ButtonRouterLinkProps = {\n to: string\n onClick?: (e?: React.MouseEvent) => any\n} & React.ComponentProps\n\nconst ButtonRouterLink: React.FC = ({\n to,\n onClick,\n ...props\n}) => {\n const history = useHistory()\n\n const handleClick = (e: React.MouseEvent) => {\n e.preventDefault()\n\n if (onClick) {\n onClick(e)\n }\n\n history.push(to)\n }\n\n return \n}\n\nexport default ButtonRouterLink\n","import React from 'react'\n\nconst CheckboxLight = () => (\n \n)\n\nexport default CheckboxLight\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport CheckboxIcon from '../../icons/CheckboxLight'\n\ntype Options = {\n primaryTextFontWeight?: number\n primaryTextLineHeight?: number\n primaryTextFontSize?: number\n primaryTextColor?: string\n secondaryTextFontSize?: number\n secondaryTextLineHeight?: number\n secondaryTextColor?: string\n}\n\nconst Item = styled.li`\n display: flex;\n\n svg {\n width: 24px;\n height: 24px;\n margin-right: 12px;\n margin-top: 4px;\n flex-shrink: 0;\n }\n\n div {\n p {\n margin: 0;\n }\n\n p:first-child {\n font-size: ${({ theme, primaryTextFontSize }) =>\n primaryTextFontSize || theme['-ds-font-size-xs']['font-size'].value};\n color: ${({ theme, primaryTextColor }) =>\n primaryTextColor || theme['-ds-core-400'].value};\n line-height: ${({ primaryTextLineHeight }) => primaryTextLineHeight || 2};\n }\n p:last-child {\n line-height: 1.25;\n font-size: ${({ theme, secondaryTextFontSize }) =>\n secondaryTextFontSize || theme['-ds-font-size-xs']['font-size'].value};\n color: ${({ theme, secondaryTextColor }) =>\n secondaryTextColor || theme['-ds-neutral-600'].value};\n line-height: ${({ secondaryTextLineHeight }) =>\n secondaryTextLineHeight || 1.5};\n }\n }\n`\n\nconst List = styled.ul`\n list-style-type: none;\n padding: 0;\n margin: 0;\n\n li:not(:last-child) {\n margin-bottom: 30px;\n }\n`\n\ntype ChecklistItem = {\n primaryText: React.ReactNode\n secondaryText?: React.ReactNode\n}\n\ntype ChecklistProps = Options & {\n items: ChecklistItem[]\n}\n\nconst Checklist = ({\n items,\n primaryTextFontSize,\n primaryTextFontWeight,\n primaryTextColor,\n primaryTextLineHeight,\n secondaryTextFontSize,\n secondaryTextColor,\n secondaryTextLineHeight,\n}: ChecklistProps) => {\n return (\n \n {items?.map(({ primaryText, secondaryText }) => (\n - \n \n
\n
{primaryText}
\n
{secondaryText}
\n
\n \n ))}\n
\n )\n}\n\nexport default Checklist\n","import styled from 'styled-components'\n\nimport InvisibleButton from 'components/display/InvisibleButton'\n\nconst CloseButton = styled(InvisibleButton).attrs({ type: 'button' })<{\n $colour?: '-ds-neutral-700' | '-ds-neutral-100' | '-ds-core-400'\n $small?: boolean\n}>`\n position: absolute;\n display: flex;\n justify-content: center;\n align-items: center;\n cursor: pointer;\n color: ${({ theme, $colour }) => {\n if ($colour) return theme?.[$colour]?.value\n return theme?.['-ds-core-400']?.value\n }};\n\n top: 0;\n right: 0;\n\n width: 64px;\n height: 64px;\n\n svg {\n width: ${({ $small }) => ($small ? '14px' : '32px')};\n height: ${({ $small }) => ($small ? '14px' : '32px')};\n filter: ${({ $colour }) =>\n $colour === '-ds-neutral-100'\n ? 'drop-shadow(0 0 2px rgba(0, 0, 0, .7))'\n : 'none'};\n }\n`\n\nexport default CloseButton\n","import React from 'react'\nimport styled from 'styled-components'\n\nconst ComponentError = styled.div`\n padding: 16px;\n\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n\n font-size: 16px;\n\n color: #333;\n background-color: ${({ theme }) => theme.brand.afterglow};\n`\n\nexport default class ErrorBoundary extends React.Component {\n constructor(props) {\n super(props)\n this.state = {\n error: null,\n errorInfo: null,\n }\n }\n\n componentDidCatch(error, errorInfo) {\n // Catch errors in any components below and re-render with error message\n this.setState({\n error,\n errorInfo,\n })\n }\n\n render() {\n const { children } = this.props\n const { errorInfo, error } = this.state\n if (errorInfo) {\n return (\n \n Error in this component tree.
\n \n {error && error.toString()}\n
\n {errorInfo.componentStack}\n \n \n )\n }\n // Normally, just render children\n return children\n }\n}\n","import React from 'react'\nimport Clipboard from 'react-clipboard.js'\n\nimport Button from './Button'\n\nconst CopyButton = Button.withComponent(Clipboard)\n\ntype Props = {\n dataClipboardTarget: string\n} & React.ComponentProps\n\nconst CopyToClipboardButton: React.FC = ({\n children,\n dataClipboardTarget,\n ...props\n}) => {\n return (\n \n {children || 'Copy'}\n \n )\n}\n\nexport default CopyToClipboardButton\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport CrossIcon from '../icons/CrossOut'\nimport SmallCloseIcon from '../icons/AirbnbClose'\nimport CloseButton from './CloseButton'\nimport Modal, { ModalProps } from './Modal'\nimport { media } from '../../styles/media'\n\ntype DialogBodyProps = {\n noPadding?: boolean\n reducedBottomPadding?: boolean\n smallModal?: boolean\n}\n\nconst DialogBody = styled.div`\n position: relative;\n padding: 64px 16px;\n font-size: 16px;\n\n ${({ noPadding }) =>\n noPadding &&\n `\n padding: 0 !important;\n `}\n\n ${media.sm`\n padding: ${({ smallModal, reducedBottomPadding }) => {\n if (smallModal) return '40px 16px'\n if (reducedBottomPadding) return ' 64px 16px 30px'\n return '64px 16px 64px'\n }};\n `}\n`\n\nconst Title = styled.h1<{\n titleAlign?: 'left' | 'right' | 'center'\n}>`\n margin: 0;\n margin-bottom: 40px;\n text-align: ${({ titleAlign }) => titleAlign || 'center'};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xl']?.['font-size']?.value};\n\n ${media.sm`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxl']?.['font-size']?.value};\n `}\n`\n\nexport type DialogModalProps = {\n title?: string\n titleAlign?: 'left' | 'right' | 'center'\n onRequestClose?: (...args: any) => any\n noPadding?: boolean\n reducedBottomPadding?: boolean\n fullScreen?: boolean\n closeButtonColour?: '-ds-neutral-700' | '-ds-neutral-100' | '-ds-core-400'\n style?: React.CSSProperties\n white?: boolean\n rounded?: boolean\n narrow?: boolean\n mobileCentered?: boolean\n smallModal?: boolean\n autoWidth?: boolean\n disableClose?: boolean\n} & ModalProps\n\nconst DialogModal: React.FC = ({\n title,\n titleAlign,\n onRequestClose,\n children,\n noPadding,\n reducedBottomPadding,\n closeButtonColour,\n fullScreen = false,\n white = false,\n rounded,\n narrow = false,\n mobileCentered = false,\n smallModal,\n autoWidth,\n disableClose,\n ...props\n}) => {\n const modalClassName = [\n 'ReactModal__Content',\n fullScreen ? 'c-fullscreen-modal__content' : 'c-basic-modal__content',\n white ? 'white' : '',\n rounded && !fullScreen ? 'rounded' : '',\n narrow && !fullScreen ? 'narrow' : '',\n autoWidth ? 'auto-width' : '',\n mobileCentered && 'mobile-centered',\n ].join(' ')\n\n const modalOverlayClassName = [\n 'ReactModal__Overlay',\n fullScreen ? 'c-fullscreen-modal__overlay' : 'c-basic-modal__overlay',\n ].join(' ')\n\n return (\n \n \n {title && {title}}\n\n {children}
\n\n {!disableClose && (\n \n {smallModal ? : }\n \n )}\n \n \n )\n}\n\nexport default DialogModal\n","import React from 'react'\n\nimport formatDateRange from 'helpers/formatDateRange'\n\ntype DiscountDescriptionProps = {\n short?: boolean\n discount: {\n name?: string\n percentage: number\n startDate: string\n endDate: string\n }\n}\n\nexport default function DiscountDescription({\n short = false,\n discount,\n}: DiscountDescriptionProps) {\n const { startDate, endDate } = discount\n const dateRange = formatDateRange(startDate, endDate)\n\n if (short) {\n return (\n <>\n Get {discount.percentage}% off the nightly price for stays between{' '}\n {dateRange}\n >\n )\n }\n\n return (\n <>\n {discount.name} Get {discount.percentage}% off the\n nightly price between {dateRange}.\n >\n )\n}\n","import styled from 'styled-components'\n\ntype FadeInProps = {\n $show: boolean\n}\n\nconst FadeIn = styled.div`\n visibility: hidden;\n opacity: 0;\n z-index: -1;\n transition: visibility 0s linear 300ms, z-index 0s linear 300ms,\n opacity 300ms ease-out;\n\n ${({ $show }) =>\n $show &&\n `\n visibility: visible;\n opacity: 1;\n z-index: 3;\n transition: visibility 0s linear 0s, z-index 0s linear 0s, opacity 300ms ease-out;\n `}\n`\n\nexport default FadeIn\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport Button from './Button'\nimport ResponsiveImage from './ResponsiveImage'\n\nconst Wrapper = styled.div<{\n taller?: boolean\n}>`\n position: relative;\n\n width: 100%;\n height: 300px;\n\n padding: 20px;\n\n @media (min-width: 768px) {\n padding: 40px;\n }\n\n background-color: #333;\n background-repeat: no-repeat;\n background-position: center;\n background-size: cover;\n\n @media (min-width: 768px) {\n height: ${({ taller }) => (taller ? '600px' : '500px')};\n }\n`\n\nconst Content = styled.div`\n position: relative;\n\n display: flex;\n align-items: flex-end;\n justify-content: flex-end;\n\n width: 100%;\n height: 100%;\n`\n\nconst ActionButton = styled(Button)`\n color: #333 !important;\n background-color: rgba(255, 255, 255, 0.9);\n transition: background-color 300ms ease-out;\n &:hover {\n background-color: white;\n }\n`\n\ninterface GalleryHeaderProps {\n backgroundImage?: Omit\n photos?: Pick[]\n videos?: Array<{ id: string; streamUrl: string; thumbnailUrl: string }>\n taller?: boolean\n onOpen?: (...args: any) => any\n}\n\nconst GalleryHeader = ({\n backgroundImage,\n photos = [],\n videos = [],\n taller,\n onOpen,\n}: GalleryHeaderProps) => {\n const content = [...photos, ...videos]\n\n const medium = backgroundImage?.medium\n const large = backgroundImage?.large\n\n return (\n \n \n \n {onOpen && content?.length > 1 && (\n \n Photos\n \n )}\n \n \n )\n}\n\nexport default GalleryHeader\n","import styled from 'styled-components'\n\ntype Props = {\n variant: 'error' | 'success' | 'information' | 'warning'\n iconWidth?: number\n}\n\nconst InlineAlert = styled.div`\n display: flex;\n flex-wrap: wrap;\n padding: 16px;\n border-radius: 8px;\n\n background-color: ${({ theme, variant }) => {\n switch (variant) {\n case 'success':\n return theme?.['-ds-success-100']?.value\n case 'error':\n return theme?.['-ds-error-100']?.value\n case 'warning':\n return theme?.['-ds-warning-100']?.value\n case 'information':\n default:\n return theme?.['-ds-information-100']?.value\n }\n }};\n\n color: ${({ theme, variant }) => {\n switch (variant) {\n case 'success':\n return theme?.['-ds-success-300']?.value\n case 'error':\n return theme?.['-ds-error-300']?.value\n case 'warning':\n return theme?.['-ds-warning-300']?.value\n case 'information':\n default:\n return theme?.['-ds-information-300']?.value\n }\n }};\n\n svg {\n width: ${({ iconWidth }) => (iconWidth ? `${iconWidth}px` : '22px')};\n max-height: ${({ iconWidth }) => (iconWidth ? `${iconWidth}px` : '22px')};\n }\n\n svg + * {\n width: calc(\n 100% - ${({ iconWidth }) => (iconWidth ? `${iconWidth}px` : '22px')}\n );\n padding-left: 16px;\n }\n`\nexport default InlineAlert\n","import React from 'react'\nimport styled, { keyframes } from 'styled-components'\nimport theme from '../../styles/theme'\n\nconst rotateAnimation = keyframes`\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n`\n\nexport const InlineSpinnerWrapper = styled.div`\n display: inline-flex;\n position: relative;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n width: 1em;\n height: 1em;\n div {\n display: block;\n position: absolute;\n border: 1px solid ${({ color }) => color};\n border-radius: 50%;\n animation: ${rotateAnimation} 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n border-color: ${({ color }) => color} transparent transparent transparent;\n width: 1em;\n height: 1em;\n }\n div:nth-child(1) {\n animation-delay: -0.45s;\n }\n div:nth-child(2) {\n animation-delay: -0.3s;\n }\n div:nth-child(3) {\n animation-delay: -0.15s;\n }\n`\n\nInlineSpinnerWrapper.defaultProps = {\n color: theme.brand.forest,\n}\n\nexport default (props) => (\n \n \n \n \n \n \n)\n","import React from 'react'\n\nconst SvgInstantBook = () => (\n \n)\n\nexport default SvgInstantBook\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport InstantBookIcon from '../icons/InstantBook'\n\nconst CustomBadge = styled.div<{ compact?: boolean }>`\n display: inline-block;\n padding: 0 6px;\n\n width: auto;\n height: 20px;\n line-height: 20px;\n\n margin: 0;\n\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxxs']?.['font-size']?.value};\n font-weight: 500;\n letter-spacing: 0.8px;\n text-transform: uppercase;\n white-space: nowrap;\n\n border-radius: 5px;\n\n color: ${({ theme, compact }) =>\n compact\n ? theme?.['-ds-core-200']?.value\n : theme?.['-ds-neutral-700']?.value};\n background-color: ${({ theme, compact }) =>\n compact ? 'transparent' : theme?.['-ds-core-200']?.value};\n\n svg {\n display: inline-block;\n vertical-align: middle;\n height: ${({ compact }) => (compact ? '18px' : '10px')};\n margin-right: ${({ compact }) => (compact ? '0' : '6px')};\n }\n`\n\nconst InstantBookBadge = ({ compact }: { compact?: boolean }) => (\n \n \n {!compact && Instant Book}\n \n)\n\nexport default InstantBookBadge\n","import styled from 'styled-components'\n\nconst InvisibleButton = styled.button.attrs({ type: 'button' })`\n appearance: none;\n background: none;\n border: none;\n padding: 0;\n margin: 0;\n\n &:focus {\n outline: 0;\n }\n`\n\nexport default InvisibleButton\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport { media, mediaMax } from '../../styles/media'\n\nimport Container from '../layout/Container'\n\nimport Button from './Button'\nimport ButtonLink from './ButtonLink'\nimport LazyImage from './LazyImage'\n\nconst mobileHeaderHeight = 56\nconst desktopHeaderHeight = 100\n\ntype HeaderWrapperProps = {\n backgroundImage: string\n alignBottom?: boolean\n}\n\nconst HeaderWrapper = styled.header`\n display: flex;\n align-items: center;\n width: 100%;\n min-height: ${300 - mobileHeaderHeight}px;\n padding: 40px 0;\n\n color: white;\n\n background-repeat: no-repeat;\n background-position: center;\n background-size: cover;\n background-color: black;\n background-image: url(${({ backgroundImage }) => backgroundImage});\n ${({ alignBottom }) =>\n alignBottom &&\n `\n background-position: center 100%;\n `}\n\n h1 {\n font-size: 36px;\n margin-bottom: 20px;\n }\n\n h2 {\n font-size: 24px;\n margin-bottom: 10px;\n font-weight: 300;\n }\n\n @media (min-width: 768px) {\n height: 800px;\n\n h1 {\n font-size: 42px;\n }\n h2 {\n font-size: 30px;\n }\n }\n\n ${media.sm`\n height: ${500 - desktopHeaderHeight}px;\n `}\n\n ${media.xxxl`\n height: ${700 - desktopHeaderHeight}px;\n `}\n\n ${media.xwide`\n height: ${900 - desktopHeaderHeight}px;\n `}\n`\n\ntype SectionProps = {\n rounded?: boolean\n grey?: boolean\n sand?: boolean\n centered?: boolean\n borderBottom?: boolean\n borderTop?: boolean\n marginBottom?: boolean\n marginTop?: boolean\n}\n\nexport const Section = styled.section`\n padding: 40px 0;\n\n ${({ rounded }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n ${({ grey }) =>\n grey &&\n `\n background: #f5f5f5;\n `}\n\n ${({ theme, sand }) =>\n sand &&\n `\n background: ${theme.brand.sand};\n `}\n\n ${({ centered }) =>\n centered &&\n `\n text-align: center;\n `}\n\n ${({ borderBottom }) =>\n borderBottom &&\n `\n border-bottom: 1px solid #d5d5d5;\n `}\n\n ${({ borderTop }) =>\n borderTop &&\n `\n border-top: 1px solid #d5d5d5;\n `}\n\n ${({ marginBottom }) =>\n marginBottom &&\n `\n margin-bottom: 40px;\n\n @media (min-width: 768px) {\n margin-bottom: 80px;\n }\n `}\n\n${({ marginTop }) =>\n marginTop &&\n `\n margin-top: 40px;\n\n @media (min-width: 768px) {\n margin-top: 80px;\n }\n `}\n\n @media (min-width: 768px) {\n padding: 80px 0;\n }\n\n p {\n line-height: 1.8;\n margin: 0 auto;\n margin-bottom: 40px;\n max-width: 784px;\n\n a {\n text-decoration: none;\n color: ${({ theme }) => theme.brand.jungle};\n }\n }\n\n ${Button}, ${ButtonLink} {\n display: inline-block;\n width: 100%;\n max-width: 296px;\n }\n\n h1 {\n color: ${({ theme }) => theme.brand.forest};\n }\n\n h2 {\n line-height: 1.333;\n }\n\n ${media.md`\n p {\n font-size: 18px;\n }\n `}\n`\n\nexport const SectionIntro = styled.p`\n font-size: 18px;\n line-height: 1.6;\n max-width: 1060px !important;\n margin-bottom: 0 !important;\n\n @media (min-width: 768px) {\n font-size: 20px;\n }\n`\n\ntype SectionRowProps = {\n reverse?: boolean\n}\n\nexport const SectionRow = styled.div`\n display: flex;\n flex-direction: ${({ reverse }) => (reverse ? 'row-reverse' : 'row')};\n\n & > *:not(:last-child) {\n ${({ reverse }) => (reverse ? 'margin-left: 64px;' : 'margin-right: 64px;')}\n }\n\n ${mediaMax.md`\n flex-direction: column;\n\n & > *:not(:last-child) {\n margin-right: 0;\n margin-left: 0;\n margin-bottom: 40px;\n }\n `}\n`\n\nexport const SectionImage = styled(LazyImage)`\n max-width: 100%;\n min-height: 380px;\n\n @media (min-width: 768px) {\n margin-bottom: 0;\n }\n`\n\ntype SectionHeaderProps = {\n noMargin?: boolean\n}\n\nexport const SectionHeader = styled.h1`\n font-size: 32px;\n line-height: 1.2;\n margin-bottom: 32px;\n color: ${({ theme }) => theme.brand.forest};\n\n ${({ noMargin }) =>\n noMargin &&\n `\n margin-top: 0 !important;\n `}\n\n @media (min-width: 768px) {\n font-size: 40px;\n }\n`\n\ntype SectionSubtitleProps = {\n noMargin?: boolean\n}\n\nexport const SectionSubtitle = styled.h2`\n font-size: 20px;\n font-weight: 300;\n line-height: 1.4;\n margin-bottom: 30px;\n\n a {\n text-decoration: none;\n font-weight: 500;\n color: ${({ theme }) => theme.brand.jungle};\n }\n\n @media (min-width: 768px) {\n font-size: 30px;\n margin-bottom: 40px;\n }\n\n ${({ noMargin }) =>\n noMargin &&\n `\n margin-bottom: 0 !important;\n `}\n`\n\nexport const SmallerContainer = styled(Container)`\n max-width: 1000px;\n`\n\ntype LandingHeaderProps = HeaderWrapperProps & {}\n\nexport const LandingHeader: React.FC = ({\n children,\n backgroundImage,\n ...custom\n}) => (\n \n \n \n)\n\nexport const ColumnReversible = styled.div.attrs({ className: 'row' })`\n ${media.lg`\n display: flex;\n align-items: center;\n `}\n\n ${mediaMax.md`\n display: flex;\n flex-direction: column-reverse;\n margin-top: -40px;\n\n img {\n margin-bottom: 33px;\n }\n .mobile-full-width {\n padding-left: 0;\n padding-right: 0;\n }\n `}\n`\n\nexport const TwoButtons = styled.div`\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n\n ${Button}, ${ButtonLink} {\n &:first-child {\n margin-bottom: 16px;\n }\n }\n\n ${media.md`\n flex-direction: row;\n ${Button}, ${ButtonLink} {\n margin: 0 8px;\n\n &:first-child {\n margin-bottom: 0;\n }\n }\n `}\n`\n","import styled from 'styled-components'\nimport { cover, timingFunctions } from 'polished'\n\ntype LazyImageProps = {\n 'data-src'?: string\n 'data-srcset'?: string\n cover?: boolean\n transformRule?: string\n zIndex?: Number\n rounded?: boolean\n height?: number\n width?: number\n preload?: boolean\n style?: React.CSSProperties\n}\n\n/**\n * Helper for setting `data-sizes=auto` on the
, if a prop `data-srcset` is present.\n *\n * The `data-sizes=auto` property allows the lazysizes library to automatically handle selecting the right src from a srcset:\n * https://github.com/aFarkas/lazysizes#automatically-setting-the-sizes-attribute\n */\nconst automaticallyAddSizesAttributeWithSrcSet = (props: LazyImageProps) => {\n return {\n ...props,\n ...(props?.['data-srcset'] ? { 'data-sizes': 'auto' } : {}),\n }\n}\n\nconst LazyImage = styled.img\n .attrs(({ className = '', preload, ...props }) => ({\n className: className + ' lazyload' + (preload ? ' lazypreload' : ''),\n ...automaticallyAddSizesAttributeWithSrcSet(props),\n }))\n .withConfig({\n shouldForwardProp: (prop) => {\n return (\n ['cover', 'transformRule', 'zIndex', 'rounded', 'preload'].includes(\n prop\n ) !== true\n )\n },\n })`\n width: ${({ width }) => (width ? `${width}px` : '100%')};\n height: ${({ height }) => (height ? `${height}px` : '100%')};\n object-fit: cover;\n\n ${({ rounded }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n ${({ transformRule }) =>\n transformRule &&\n `\n transform: ${transformRule};\n `}\n\n ${({ zIndex }) =>\n zIndex &&\n `\n z-index: ${zIndex};\n `}\n\n opacity: 0;\n transition: opacity 300ms ease-out;\n transition-timing-function: ${timingFunctions('easeOutQuad')};\n\n &.lazyloaded {\n opacity: 1;\n }\n\n &.lazyload {\n opacity: 0;\n }\n\n ${(props) => props.cover && cover()}\n`\n\nexport default LazyImage\n","import React from 'react'\nimport SpinnerContainer from './SpinnerContainer'\nimport Spinner from './Spinner'\n\nconst Loading = () => (\n \n \n \n)\n\nexport default Loading\n","import { createGlobalStyle } from 'styled-components'\n\nconst LockBodyScroll = createGlobalStyle`\n html, body {\n overflow: hidden;\n }\n`\n\nexport default LockBodyScroll\n","/* global analytics */\nimport React, { useState } from 'react'\nimport styled from 'styled-components'\n\nimport Vimeo from '../Vimeo'\nimport CrossOutIcon from '../icons/CrossOut'\nimport { formatPrice } from '../utils/pricing'\n\nimport Modal from './Modal'\nimport Button from './Button'\nimport InvisibleButton from './InvisibleButton'\nimport LazyImage from './LazyImage'\nimport StreamableVideo from './StreamableVideo'\n\nconst Wrapper = styled.div`\n background-color: white;\n`\n\nconst Header = styled.header`\n position: absolute;\n z-index: 1;\n width: 100%;\n display: flex;\n justify-content: flex-end;\n\n height: 64px;\n padding: 16px;\n\n background-color: white;\n border-bottom: 1px solid #d5d5d5;\n`\n\nconst CloseButton = styled(InvisibleButton)`\n width: 32px;\n height: 32px;\n color: ${({ theme }) => theme.brand.forest};\n\n svg {\n width: 100%;\n height: 100%;\n }\n`\n\nconst Content = styled.div`\n height: 100%;\n padding: 16px;\n padding-top: 80px; /* Header Height + 16px */\n padding-bottom: 104px; /* Footer Height + 16px */\n\n overflow-x: hidden;\n overflow-y: scroll;\n -webkit-overflow-scrolling: touch;\n`\n\nconst Placeholder = styled.div`\n position: relative;\n width: 100%;\n height: 0;\n margin-bottom: 16px;\n background-color: #ddd;\n\n &:last-child {\n margin-bottom: 0;\n }\n`\n\nconst Footer = styled.footer`\n position: absolute;\n bottom: 0;\n left: 0;\n width: 100%;\n\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n height: 88px;\n padding: 16px;\n\n background-color: white;\n border-top: 1px solid #d5d5d5;\n\n overflow-x: hidden;\n overflow-y: scroll;\n -webkit-overflow-scrolling: touch;\n`\n\nconst Details = styled.div`\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n padding-right: 16px;\n`\n\nconst ListingTitle = styled.div`\n color: ${({ theme }) => theme.brand.forest};\n font-weight: 500;\n line-height: 1.375;\n letter-spacing: 0.25px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n`\n\nconst ListingPrice = styled.div`\n color: #999;\n font-weight: 300;\n line-height: 1.375;\n letter-spacing: 0.25px;\n`\n\nconst VideoContainer = styled(Placeholder)`\n padding-top: 56.25%;\n\n iframe {\n position: absolute;\n top: 0;\n left: 0;\n }\n`\n\ninterface MobileGalleryProps {\n photos?: Pick[]\n videos?: Array<{ id: string; streamUrl: string; thumbnailUrl: string }>\n photoVersion?: 'hero' | 'large' | 'medium' | 'original' | 'thumb'\n listing?: {\n price: number\n nicePricingSuffix: string\n title: string\n }\n videoUrl?: string\n total?: number\n isOpen?: boolean\n onRequestClose: (...args: any) => any\n onBook?: (...args: any) => any\n}\n\nconst MobileGallery = ({\n photos,\n videos = [],\n photoVersion = 'large',\n listing,\n videoUrl,\n total,\n isOpen,\n onRequestClose,\n onBook,\n}: MobileGalleryProps) => {\n const [videoPlayed, setVideoPlayed] = useState(false)\n const handleVideoPlayed = (url: string) => {\n if (!videoPlayed) {\n setVideoPlayed(true)\n analytics.track('Played Video', { source: 'page', url })\n }\n }\n\n return (\n \n \n \n \n {videoUrl && (\n \n \n \n )}\n {videos?.map(({ id, streamUrl, thumbnailUrl }) => (\n \n \n \n
\n \n ))}\n {photos?.map(({ id, image, aspectRatio }) => (\n \n \n \n ))}\n \n {listing && (\n \n )}\n \n \n )\n}\n\nexport default MobileGallery\n","import React, { useCallback, useEffect, useState } from 'react'\nimport ReactModal from 'react-modal'\n\nimport useIsServer from '../../hooks/useIsServer'\nimport useBodyScrollLock from '../../hooks/useBodyScrollLock'\n\n/**\n * Abstraction for working with modals whose content needs to scroll while disabling scrolling everywhere else.\n *\n * Returns:\n * 1. a ref function to attach to the element that needs to scroll, and\n * 2. the dom node that ref currently points to, which can be passed via props to the modal component\n */\nexport const useScrollableModalContent = (isOpen: boolean) => {\n const { enableBodyScroll, disableBodyScroll } = useBodyScrollLock()\n const [scrollableNode, setScrollableNode] = useState()\n\n const scrollableRefFn = useCallback((node) => {\n if (node != null) {\n setScrollableNode(node)\n }\n }, [])\n\n useEffect(() => {\n if (scrollableNode) {\n if (isOpen) {\n disableBodyScroll(scrollableNode)\n } else {\n enableBodyScroll(scrollableNode)\n }\n }\n }, [isOpen, scrollableNode])\n\n return { scrollableRefFn, scrollableNode }\n}\n\nexport type ModalProps = {\n onAfterOpen?: (...args: any) => any\n noScrollLock?: boolean\n scrollableNodes?: Element[]\n} & React.ComponentProps\n\nconst Modal: React.FC = (props) => {\n const {\n children,\n onAfterOpen,\n onRequestClose,\n noScrollLock,\n isOpen,\n scrollableNodes = [],\n } = props\n const isServer = useIsServer()\n\n /*\n We use a 3rd party library to prevent the document body from scrolling while the modal is open because iOS doesn't\n respect `overflow-y: hidden` on the body element. Instead, the library takes html nodes, and attaches event listeners\n to them so it they are still allowed to scroll, while disabling scrolling on everything else, also via event listeners.\n\n So our component can optionally be told which elements to still allow scrolling on -- it will pass these to\n the 3rd party library. It also attaches listeners to the .ReactModal__Content element -- this is done in the\n onAfterOpen handler to ensure the content element is there.\n */\n\n const {\n enableBodyScroll,\n disableBodyScroll,\n clearAllBodyScrollLocks,\n } = useBodyScrollLock()\n\n const [defaultScrollableNode, setDefaultScrollableNode] = useState()\n\n useEffect(() => {\n if (defaultScrollableNode) {\n if (isOpen) {\n disableBodyScroll(defaultScrollableNode)\n } else {\n enableBodyScroll(defaultScrollableNode)\n }\n }\n }, [isOpen, defaultScrollableNode])\n\n useEffect(() => {\n if (noScrollLock !== true) {\n scrollableNodes?.forEach((node) => {\n if (node) {\n if (isOpen) {\n disableBodyScroll(node)\n } else {\n enableBodyScroll(node)\n }\n }\n })\n }\n }, [noScrollLock, isOpen, scrollableNodes.toString()])\n\n useEffect(() => {\n return () => {\n clearAllBodyScrollLocks()\n }\n }, [])\n\n const handleOpen = () => {\n if (!isServer && scrollableNodes.length === 0) {\n const modalContentElement = document.querySelector('.ReactModal__Content')\n setDefaultScrollableNode(modalContentElement)\n }\n\n if (onAfterOpen) {\n onAfterOpen()\n }\n }\n\n return (\n \n <>{children}>\n \n )\n}\n\nexport default Modal\n","import styled from 'styled-components'\n\nconst MoreButton = styled.button`\n display: block;\n text-decoration: none !important;\n\n appearance: none;\n background: none;\n border: 0;\n border-radius: 0;\n outline: 0;\n\n color: ${({ theme }) => theme.brand.jungle};\n font-size: 16px;\n font-weight: 500;\n line-height: 22px;\n\n padding-left: 0;\n padding-top: 16px;\n margin-top: 8px;\n`\n\nexport default MoreButton\n","import styled from 'styled-components'\n\nimport Theme from 'styles/theme'\n\nconst DEFAULT_COLOR = Theme['-ds-core-400'].value\nconst DEFAULT_OPACITY = 0.2\nconst DEFAULT_Z_INDEX = 10\n\ntype Options = {\n color: string\n opacity?: number\n zIndex?: number\n}\n\nconst UniformOverlay = styled.div`\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n\n background-color: ${({ color = DEFAULT_COLOR }) => color};\n\n z-index: ${({ zIndex = DEFAULT_Z_INDEX }) => zIndex};\n\n opacity: ${({ opacity = DEFAULT_OPACITY }) => opacity};\n`\n\nexport default UniformOverlay\n","import styled from 'styled-components'\n\nconst Overlay = styled.div`\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: rgba(255, 255, 255, 0.65);\n z-index: 10;\n`\n\nexport default Overlay\n","import React from 'react'\nimport styled from 'styled-components'\n\nexport const BasePanel = styled.div`\n visibility: hidden;\n opacity: 0;\n\n transition-property: opacity;\n transition-duration: 150ms;\n transition-delay: 0;\n\n ${({ open }) =>\n open &&\n `\n visibility: visible;\n opacity: 1;\n `}\n`\n\nexport default class Panel extends React.Component {\n componentDidMount() {\n document.addEventListener('click', this.onClickOutsidePanel, true)\n document.addEventListener('keyup', this.onEscapeKey)\n }\n\n componentWillUnmount() {\n document.removeEventListener('click', this.onClickOutsidePanel, true)\n document.removeEventListener('keyup', this.onEscapeKey)\n }\n\n onClickOutsidePanel = (e) => {\n const { id, open, onClose } = this.props\n\n if ($(e.target).closest(`.js-panel-${id}`).length === 0) {\n if (open) onClose()\n }\n }\n\n onEscapeKey = (e) => {\n const { open, onClose } = this.props\n\n if (e.keyCode === 27 && open) onClose()\n }\n\n render() {\n const { id, open, children } = this.props\n return (\n \n {open && children}\n \n )\n }\n}\n","import React from 'react'\n\nimport LazyImage from '../LazyImage'\n\nimport type { ResponsiveImageProperties } from './types'\n\ntype LazyImageProps = React.ComponentProps\n\ntype ResponsiveImageProps = ResponsiveImageProperties & LazyImageProps\n\nconst ResponsiveImage = (props: ResponsiveImageProps) => {\n let src\n let srcset\n let lazyImageProps: LazyImageProps = {}\n\n if ('w800' in props) {\n const { w400, w800, w1200, ...rest } = props\n lazyImageProps = rest\n src = w800\n srcset = `\n ${w800} 800w,\n ${w1200 ? `${w1200} 1200w` : ''},\n ${w400 ? `${w400} 400w` : ''},\n `\n } else if ('medium' in props) {\n const { medium, large, ...rest } = props\n lazyImageProps = rest\n src = medium\n srcset = `\n ${medium} 600w,\n ${large ? `${large} 1200w` : ''},\n `\n }\n\n return \n}\n\nexport default ResponsiveImage\n","import styled from 'styled-components'\n\nimport { media } from '../../styles/media'\n\nconst Separator = styled.hr`\n display: none;\n margin: 0;\n padding: 0;\n border-top: 1px solid ${({ theme }) => theme.colors.textGreyLight};\n\n ${media.md`\n display: block;\n `}\n`\n\nexport default Separator\n","import React from 'react'\n\nconst SvgIconShare = (props) => (\n \n)\n\nexport default SvgIconShare\n","import React, { useState } from 'react'\nimport styled from 'styled-components'\n\nimport withRenderClientsideOnly from 'components/utils/withRenderClientsideOnly'\nimport { trackPageShared, Method } from '../../analytics/share'\n\nimport ShareIcon from '../icons/Share'\nimport TrayModal from '../modals/TrayModal'\n\nimport Button from './Button'\nimport ShareList from './ShareList'\n\nconst EntryButton = styled(Button).attrs({\n uppercase: false,\n})`\n display: flex;\n align-items: center;\n justify-content: center;\n`\n\ntype ButtonLikeProps = Omit, 'onClick'>\n\ntype ModalProps = {\n isOpen: boolean\n onRequestClose: () => any\n title: string\n url: string\n source: Parameters[0]['source']\n excludeMethods?: Method[]\n message?: string\n}\n\nconst Modal = withRenderClientsideOnly(\n ({\n isOpen,\n onRequestClose,\n title,\n url,\n source,\n excludeMethods = [],\n message,\n }: ModalProps) => (\n \n {\n trackPageShared({ method, source, url })\n }}\n />\n \n )\n)\n\ntype ShareButtonProps = {\n title: string\n url: string\n source: Parameters[0]['source']\n EntryButtonComponent?: React.ComponentType\n excludeMethods?: Method[]\n message?: string\n} & ButtonLikeProps\n\nconst ShareButton = ({\n title,\n url,\n source,\n EntryButtonComponent = EntryButton,\n excludeMethods = [],\n message,\n ...props\n}: ShareButtonProps) => {\n const [open, setOpen] = useState(false)\n\n return (\n <>\n setOpen(true)} {...props}>\n {props.children || (\n <>\n \n Share\n >\n )}\n \n\n setOpen(false)}\n title={title}\n url={url}\n source={source}\n excludeMethods={excludeMethods}\n message={message}\n />\n >\n )\n}\n\nexport default ShareButton\n","/* global analytics */\n\nexport type Method =\n | 'email'\n | 'facebook'\n | 'link'\n | 'messenger'\n | 'sms'\n | 'twitter'\n | 'whatsapp'\n\ntype Source =\n | 'adventure_page'\n | 'bucket_list'\n | 'listing_page'\n | 'story_page'\n | 'itinerary_builder'\n | 'booking_confirmation_page'\n\nexport const trackPageShared = ({\n method,\n source,\n url,\n}: {\n method: Method\n source: Source\n url: string\n}) => {\n analytics.track('Page Shared', {\n method,\n source,\n url,\n })\n}\n","import React from 'react'\n\nconst SvgIconMessage = (props) => (\n \n)\n\nexport default SvgIconMessage\n","import React from 'react'\n\nconst SvgIconMessenger = () => (\n \n)\n\nexport default SvgIconMessenger\n","import React, { useContext } from 'react'\nimport styled, { useTheme } from 'styled-components'\nimport {\n EmailShareButton,\n FacebookShareButton,\n TwitterShareButton,\n WhatsappShareButton,\n FacebookMessengerShareButton,\n FacebookIcon,\n TwitterIcon,\n WhatsappIcon,\n} from 'react-share'\n\nimport TouchDeviceContext from 'contexts/TouchDeviceContext'\nimport { useToasts } from 'react-toast-notifications'\nimport { Method } from '../../analytics/share'\n\nimport CopyIcon from '../icons/Copy'\nimport MessageIcon from '../icons/Message'\nimport EmailIcon from '../icons/Mail'\nimport MessengerIcon from '../icons/Messenger'\nimport { InlineInput, TextField } from '../form'\n\nimport Button from './Button'\nimport CopyToClipboardButton from './CopyToClipboardButton'\n\nconst List = styled.div`\n padding: 16px 0;\n display: flex;\n flex-direction: column;\n gap: 16px;\n\n & > * {\n display: flex;\n align-items: center;\n width: 100%;\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-sm']?.['font-size']?.value};\n\n svg {\n width: 24px;\n height: 24px;\n margin-right: 16px;\n }\n }\n\n button {\n display: flex;\n align-items: center;\n }\n\n input {\n margin: 0;\n }\n`\n\nconst ShareMethodButton = styled(Button).attrs({\n ghost: true,\n uppercase: false,\n})``\n\nconst ShareMethodButtonOuter = styled(ShareMethodButton).attrs({ as: 'div' })`\n padding: 0;\n\n & > button {\n padding: 16px !important;\n width: 100% !important;\n }\n`\n\nconst CopyWrapper = styled.div`\n margin-left: 8px;\n\n button {\n height: 100%;\n }\n`\n\nconst iconProps = {\n size: 48,\n round: true,\n}\n\ntype ShareListProps = {\n url: string\n message?: string\n excludeMethods?: Method[]\n onShare?: (method: Method) => void\n}\n\nconst ShareList = ({\n url,\n message,\n excludeMethods = [],\n onShare,\n}: ShareListProps) => {\n const { addToast } = useToasts()\n const theme = useTheme()\n\n const isTouchDevice = useContext(TouchDeviceContext)\n\n const body = `${message}: ${url}`\n\n return (\n \n {!excludeMethods.includes('link') && (\n \n \n \n \n \n {\n onShare('link')\n addToast('Link copied')\n }}\n style={{ marginRight: 0 }}\n >\n \n Copy Link\n \n \n
\n )}\n\n {!excludeMethods.includes('email') && (\n \n onShare('email')}\n subject={message}\n url={url}\n >\n \n Email\n \n \n )}\n\n {!excludeMethods.includes('sms') && (\n onShare('sms')}\n >\n \n Messages\n \n )}\n\n {!excludeMethods.includes('facebook') && (\n \n onShare('facebook')}\n quote={message}\n url={url}\n >\n Facebook\n \n \n )}\n\n {!excludeMethods.includes('twitter') && (\n \n onShare('twitter')}\n title={message}\n url={url}\n >\n \n Twitter\n \n \n )}\n\n {window?.fbAppId != null &&\n !isTouchDevice &&\n !excludeMethods.includes('messenger') && (\n \n {\n onShare('messenger')\n }}\n >\n \n Messenger\n \n \n )}\n\n {!excludeMethods.includes('whatsapp') && (\n \n onShare('whatsapp')}\n title={message}\n url={url}\n >\n \n WhatsApp\n \n \n )}\n
\n )\n}\n\nexport default ShareList\n","import styled from 'styled-components'\n\nconst SimpleA = styled.a.attrs(({ target }) => {\n if (target === '_blank') {\n return {\n rel: 'noopener noreferrer',\n }\n }\n\n return {}\n})<{ href: string; textDecoration?: string; target?: '_blank'; rel?: string }>`\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n text-decoration: ${({ textDecoration = 'underline' }) => textDecoration};\n\n &:hover,\n &:link {\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n text-decoration: ${({ textDecoration = 'underline' }) => textDecoration};\n }\n`\n\nexport default SimpleA\n","import { Link } from 'react-router-dom'\nimport styled from 'styled-components'\n\nconst SimpleLink = styled(Link)<{ textDecoration?: string; width?: string }>`\n width: ${({ width = 'fit-content' }) => width};\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n text-decoration: ${({ textDecoration }) => textDecoration || 'none'};\n\n &:hover,\n &:link {\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n text-decoration: ${({ textDecoration }) => textDecoration || 'none'};\n }\n`\n\nexport default SimpleLink\n","import React from 'react'\nimport styled from 'styled-components'\n\nconst Wrapper = styled.div`\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 10px 0;\n`\n\nconst transientIconProps = ['white', 'small'] as const\n\ntype HTMLStringPropKeys = 'css' | 'href' | 'rel' | 'target' | 'type'\ntype HTMLBooleanPropKeys = 'disabled'\ntype HTMLPropKeys = HTMLStringPropKeys & HTMLBooleanPropKeys\ntype HTMLProps = Record &\n Record\n\ntype TransientIconPropKeys = typeof transientIconProps[number]\ntype TransientIconProps = Record\n\ntype IconProps = Partial & {\n style?: object\n}\n\nconst Icon = styled.div.withConfig({\n shouldForwardProp: (prop: TransientIconPropKeys & HTMLPropKeys) =>\n !transientIconProps.includes(prop),\n})`\n margin: 10px auto;\n font-size: 8px;\n width: 1em;\n height: 1em;\n border-radius: 50%;\n position: relative;\n text-indent: -9999em;\n -webkit-transform: translateZ(0);\n -ms-transform: translateZ(0);\n transform: translateZ(0);\n\n ${({ small }) =>\n small &&\n `\n font-size: 4px;\n `}\n\n ${({ white }) =>\n white &&\n `\n -webkit-animation: loadWhite 1.1s infinite ease;\n animation: loadWhite 1.1s infinite ease;\n @-webkit-keyframes loadWhite {\n 0%,\n 100% {\n box-shadow: 0em -2.6em 0em 0em #FFF, 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.5), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7);\n }\n 12.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.7), 1.8em -1.8em 0 0em #FFF, 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5);\n }\n 25% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.5), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7), 2.5em 0em 0 0em #FFF, 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 37.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5), 2.5em 0em 0 0em rgba(255, 255, 255, 0.7), 1.75em 1.75em 0 0em #FFF, 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 50% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.5), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.7), 0em 2.5em 0 0em #FFF, -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 62.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.5), 0em 2.5em 0 0em rgba(255, 255, 255, 0.7), -1.8em 1.8em 0 0em #FFF, -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 75% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.5), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.7), -2.6em 0em 0 0em #FFF, -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 87.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.5), -2.6em 0em 0 0em rgba(255, 255, 255, 0.7), -1.8em -1.8em 0 0em #FFF;\n }\n }\n @keyframes loadWhite {\n 0%,\n 100% {\n box-shadow: 0em -2.6em 0em 0em #FFF, 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.5), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7);\n }\n 12.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.7), 1.8em -1.8em 0 0em #FFF, 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5);\n }\n 25% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.5), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7), 2.5em 0em 0 0em #FFF, 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 37.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5), 2.5em 0em 0 0em rgba(255, 255, 255, 0.7), 1.75em 1.75em 0 0em #FFF, 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 50% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.5), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.7), 0em 2.5em 0 0em #FFF, -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 62.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.5), 0em 2.5em 0 0em rgba(255, 255, 255, 0.7), -1.8em 1.8em 0 0em #FFF, -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 75% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.5), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.7), -2.6em 0em 0 0em #FFF, -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);\n }\n 87.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.5), -2.6em 0em 0 0em rgba(255, 255, 255, 0.7), -1.8em -1.8em 0 0em #FFF;\n }\n }\n `}\n\n ${({ white }) =>\n !white &&\n `\n -webkit-animation: loadBlack 1.1s infinite ease;\n animation: loadBlack 1.1s infinite ease;\n @-webkit-keyframes loadBlack {\n 0%,\n 100% {\n box-shadow: 0em -2.6em 0em 0em #000000, 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.5), -1.8em -1.8em 0 0em rgba(0,0,0, 0.7);\n }\n 12.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.7), 1.8em -1.8em 0 0em #000000, 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.5);\n }\n 25% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.5), 1.8em -1.8em 0 0em rgba(0,0,0, 0.7), 2.5em 0em 0 0em #000000, 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 37.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.5), 2.5em 0em 0 0em rgba(0,0,0, 0.7), 1.75em 1.75em 0 0em #000000, 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 50% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.5), 1.75em 1.75em 0 0em rgba(0,0,0, 0.7), 0em 2.5em 0 0em #000000, -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 62.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.5), 0em 2.5em 0 0em rgba(0,0,0, 0.7), -1.8em 1.8em 0 0em #000000, -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 75% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.5), -1.8em 1.8em 0 0em rgba(0,0,0, 0.7), -2.6em 0em 0 0em #000000, -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 87.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.5), -2.6em 0em 0 0em rgba(0,0,0, 0.7), -1.8em -1.8em 0 0em #000000;\n }\n }\n @keyframes loadBlack {\n 0%,\n 100% {\n box-shadow: 0em -2.6em 0em 0em #000000, 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.5), -1.8em -1.8em 0 0em rgba(0,0,0, 0.7);\n }\n 12.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.7), 1.8em -1.8em 0 0em #000000, 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.5);\n }\n 25% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.5), 1.8em -1.8em 0 0em rgba(0,0,0, 0.7), 2.5em 0em 0 0em #000000, 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 37.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.5), 2.5em 0em 0 0em rgba(0,0,0, 0.7), 1.75em 1.75em 0 0em #000000, 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 50% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.5), 1.75em 1.75em 0 0em rgba(0,0,0, 0.7), 0em 2.5em 0 0em #000000, -1.8em 1.8em 0 0em rgba(0,0,0, 0.2), -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 62.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.5), 0em 2.5em 0 0em rgba(0,0,0, 0.7), -1.8em 1.8em 0 0em #000000, -2.6em 0em 0 0em rgba(0,0,0, 0.2), -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 75% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.5), -1.8em 1.8em 0 0em rgba(0,0,0, 0.7), -2.6em 0em 0 0em #000000, -1.8em -1.8em 0 0em rgba(0,0,0, 0.2);\n }\n 87.5% {\n box-shadow: 0em -2.6em 0em 0em rgba(0,0,0, 0.2), 1.8em -1.8em 0 0em rgba(0,0,0, 0.2), 2.5em 0em 0 0em rgba(0,0,0, 0.2), 1.75em 1.75em 0 0em rgba(0,0,0, 0.2), 0em 2.5em 0 0em rgba(0,0,0, 0.2), -1.8em 1.8em 0 0em rgba(0,0,0, 0.5), -2.6em 0em 0 0em rgba(0,0,0, 0.7), -1.8em -1.8em 0 0em #000000;\n }\n }\n `}\n`\n\ntype SpinnerProps = {\n white?: boolean\n small?: boolean\n}\n\nconst Spinner = ({ white = false, small = false }: SpinnerProps) => (\n \n \n \n)\n\nexport default Spinner\n","import styled from 'styled-components'\n\nconst SpinnerContainer = styled.div`\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n min-height: 200px;\n @media (min-width: 768px) {\n min-height: 300px;\n }\n @media (min-width: 992px) {\n min-height: 400px;\n }\n @media (min-width: 1200px) {\n min-height: 500px;\n }\n`\n\nexport default SpinnerContainer\n","import React from 'react'\n\nconst SvgIconPlayCircle = (props) => (\n \n)\n\nexport default SvgIconPlayCircle\n","import { useEffect, useState } from 'react'\n\nimport useIsServer from 'hooks/useIsServer'\n\nconst loadVideo = (video: HTMLVideoElement, videoSrc: string) => {\n // eslint-disable-next-line global-require\n const Hls = require('hls.js')\n let hls: typeof Hls\n\n if (video.canPlayType('application/vnd.apple.mpegurl')) {\n // Some browers (safari and ie edge) support HLS natively\n // eslint-disable-next-line no-param-reassign\n video.src = videoSrc\n } else if (Hls?.isSupported()) {\n // This will run in all other modern browsers\n hls = new Hls({\n enableWorker: true,\n lowLatencyMode: true,\n capLevelToPlayerSize: true,\n backBufferLength: 90,\n })\n hls.loadSource(videoSrc)\n hls.attachMedia(video)\n } else {\n // eslint-disable-next-line no-console\n console.error(\"This is a legacy browser that doesn't support MSE\")\n }\n\n return hls\n}\n\nexport const useVideoPlaying = (\n videoRef: React.MutableRefObject\n) => {\n const [videoPlaying, setVideoPlaying] = useState(false)\n\n useEffect(() => {\n videoRef.current?.addEventListener('play', () => setVideoPlaying(true))\n videoRef.current?.addEventListener('pause', () => setVideoPlaying(false))\n\n return () => {\n videoRef.current?.removeEventListener('play', () => setVideoPlaying(true))\n videoRef.current?.removeEventListener('pause', () =>\n setVideoPlaying(false)\n )\n }\n }, [videoRef])\n\n return videoPlaying\n}\n\nexport const useVideoEnded = (\n videoRef: React.MutableRefObject,\n playing: boolean\n) => {\n const [ended, setEnded] = useState(false)\n\n const handleEnded = () => setEnded(true)\n\n useEffect(() => {\n videoRef.current?.addEventListener('ended', handleEnded)\n\n return () => {\n videoRef.current?.removeEventListener('ended', handleEnded)\n }\n }, [videoRef])\n\n useEffect(() => {\n if (playing) {\n setEnded(false)\n }\n }, [playing])\n\n return ended\n}\n\nexport const useForcePause = (\n videoRef: React.MutableRefObject,\n forcePause: boolean\n) => {\n useEffect(() => {\n if (videoRef.current != null && forcePause === true) {\n videoRef.current.pause()\n }\n }, [forcePause, videoRef])\n}\n\nexport const useLoadVideo = (\n videoRef: React.MutableRefObject,\n src: string\n) => {\n const isServer = useIsServer()\n useEffect(() => {\n let hls: any // need some way to type Hls instance here\n if (videoRef.current && src) {\n hls = loadVideo(videoRef.current, src)\n }\n\n return () => {\n if (hls) {\n hls.destroy()\n }\n }\n }, [videoRef, src, isServer])\n}\n\nexport const useReloadOnEnded = (\n videoRef: React.MutableRefObject,\n src: string,\n videoEnded: boolean\n) => {\n useEffect(() => {\n if (videoEnded && src && videoRef.current) {\n loadVideo(videoRef.current, src)\n }\n }, [videoRef, videoEnded])\n}\n","import React, { useRef } from 'react'\nimport styled from 'styled-components'\n\nimport PlayCircleIcon from '../../icons/PlayCircle'\n\nimport InvisibleButton from '../InvisibleButton'\n\nimport {\n useForcePause,\n useLoadVideo,\n useReloadOnEnded,\n useVideoEnded,\n useVideoPlaying,\n} from './playbackStateHooks'\n\nconst PlayToggle = styled(InvisibleButton)`\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n`\n\nconst Figure = styled.figure`\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n`\n\nconst IconWrapper = styled.div`\n display: flex;\n align-items: center;\n justify-content: center;\n\n svg {\n color: ${({ theme }) => theme['-ds-neutral-100'].value};\n width: 48px;\n height: 48px;\n }\n`\n\nconst Video = styled.video<{ objectFit: 'contain' | 'cover' }>`\n width: 100%;\n height: 100%;\n object-fit: ${({ objectFit = 'cover' }) => objectFit};\n`\n\ntype StreamableVideoProps = {\n src: string\n poster: string\n forcePause?: boolean\n browserControls?: boolean\n objectFit?: 'contain' | 'cover'\n}\n\nconst StreamableVideo = ({\n src,\n poster,\n forcePause,\n browserControls,\n objectFit,\n}: StreamableVideoProps) => {\n const videoRef = useRef(null)\n\n useLoadVideo(videoRef, src)\n\n useForcePause(videoRef, forcePause)\n\n const videoPlaying = useVideoPlaying(videoRef)\n\n const videoEnded = useVideoEnded(videoRef, videoPlaying)\n\n useReloadOnEnded(videoRef, src, videoEnded)\n\n const togglePlay = (e: React.MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n\n const video = videoRef.current\n\n if (videoPlaying) {\n video?.pause()\n } else {\n video?.play()\n }\n }\n\n return (\n \n {src && (\n <>\n {/* eslint-disable-next-line jsx-a11y/media-has-caption */}\n \n {!browserControls && (\n \n {!videoPlaying && (\n \n \n \n )}\n \n )}\n >\n )}\n \n )\n}\n\nexport default StreamableVideo\n","import React from 'react'\nimport styled from 'styled-components'\n\nexport const TagWrapper = styled.div`\n display: inline-flex;\n align-items: center;\n padding: 12px;\n\n font-size: 16px;\n font-weight: 300;\n line-height: 1;\n\n color: #1d1d1d;\n background-color: ${({ theme }) => theme.brand.sand};\n border-radius: 5px;\n\n .icon {\n display: inline-block;\n vertical-align: middle;\n\n font-size: 24px;\n margin-right: 8px;\n }\n\n ${({ theme, sunUp }) =>\n sunUp &&\n `\n background-color: ${theme.brand.sunup};\n `}\n\n ${({ disabled }) =>\n disabled &&\n `\n color: #979797;\n\n span {\n text-decoration: line-through;\n }\n `}\n\n ${({ active, theme }) =>\n active &&\n `\n color: white;\n background-color: ${theme.brand.jungle};\n `}\n`\n\nexport default ({ icon, children, ...props }) => (\n \n \n {children}\n \n)\n","import React from 'react'\n\nconst InfoLight = () => (\n \n)\n\nexport default InfoLight\n","import React, { useState, useEffect, useCallback } from 'react'\nimport styled from 'styled-components'\nimport { usePopper } from 'react-popper'\nimport { OffsetsFunction } from '@popperjs/core/lib/modifiers/offset'\n\nimport coreTheme from '../../styles/theme'\n\nimport InfoLightIcon from '../icons/InfoLight'\nimport IconClose from '../icons/AirbnbClose'\nimport InvisibleButton from './InvisibleButton'\n\nconst IconWrapper = styled(InvisibleButton)`\n appearance: none;\n outline: none;\n border: none;\n background: transparent;\n padding: 0;\n margin: 0;\n\n position: relative;\n top: 2px;\n margin-left: 8px;\n\n display: inline-block;\n color: #999;\n\n &:hover {\n color: ${({ theme }) => theme?.['-ds-neutral-600']?.value};\n }\n\n svg {\n display: block;\n width: 16px;\n height: 16px;\n }\n`\ntype WrapperProps = {\n backgroundColor: string\n}\nconst Wrapper = styled.div`\n position: absolute;\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n background-color: ${({ backgroundColor }) => backgroundColor};\n box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.15);\n border-radius: 6px;\n`\n\ntype ArrowProps = {\n foregroundColor: string\n}\nconst Arrow = styled.div`\n position: absolute;\n height: 24px;\n width: 24px;\n overflow: hidden;\n\n &:after {\n content: '';\n position: absolute;\n width: 12px;\n height: 12px;\n left: 6px;\n top: -6px;\n\n background: ${({ foregroundColor }) => foregroundColor};\n transform: rotate(45deg);\n box-shadow: 2px 2px 4px 0 rgba(0, 0, 0, 0.1);\n }\n\n ${Wrapper}[data-popper-placement^='top'] > & {\n top: 100%;\n }\n\n ${Wrapper}[data-popper-placement^='bottom'] > & {\n bottom: 100%;\n\n &:after {\n top: auto;\n bottom: -6px;\n box-shadow: 2px 0px 4px 0 rgba(0, 0, 0, 0.15);\n }\n }\n`\n\nconst CloseButton = styled.button`\n display: block;\n appearance: none;\n padding: 0;\n margin: 0;\n border: none;\n outline: none;\n background-color: transparent;\n position: absolute;\n top: 12px;\n right: 12px;\n\n svg {\n display: block;\n width: 14px;\n height: 14px;\n pointer-events: none;\n }\n`\n\nconst Content = styled.div`\n padding: 16px 35px 16px 16px;\n font-weight: 300;\n text-transform: none;\n`\n\ntype TooltipPopoverProps = {\n referenceElement: Element\n placement?:\n | 'top'\n | 'bottom'\n | 'top-start'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-end'\n zIndex?: number\n backgroundColor?: string\n children?: React.ReactNode\n onClose: () => unknown\n}\n\nconst dynamicPopperOffset: OffsetsFunction = ({\n placement: actualPlacement,\n}) => {\n if (actualPlacement === 'top' || actualPlacement === 'bottom') {\n return [0, 12]\n }\n if (actualPlacement.includes('start')) {\n return [-12, 12]\n }\n return [12, 12]\n}\n\nfunction useClickOutside(element: HTMLElement, onClickOutside: () => unknown) {\n const onDocumentClick = useCallback(\n (e: MouseEvent) => {\n if (!element?.contains(e.target as HTMLElement)) {\n onClickOutside()\n }\n },\n [element, onClickOutside]\n )\n\n useEffect(() => {\n document.addEventListener('click', onDocumentClick, { capture: true })\n\n return () => {\n document.removeEventListener('click', onDocumentClick, { capture: true })\n }\n }, [onDocumentClick])\n}\n\nfunction useGlobalEscapeKeyHandler(onKeyUp: () => unknown) {\n const onDocumentKeyUp = useCallback(\n (e: KeyboardEvent) => {\n if (['Esc', 'Escape'].includes(e.key)) {\n e.preventDefault()\n onKeyUp()\n }\n },\n [onKeyUp]\n )\n\n useEffect(() => {\n document.addEventListener('keyup', onDocumentKeyUp, { capture: true })\n\n return () => {\n document.removeEventListener('keyup', onDocumentKeyUp, { capture: true })\n }\n }, [onDocumentKeyUp])\n}\n\nconst TOOLTIP_POPOVER_ID = 'tooltip'\nexport function TooltipPopover({\n referenceElement,\n placement = 'top-end',\n zIndex = 1,\n backgroundColor = coreTheme['-ds-neutral-200']?.value,\n children,\n onClose,\n}: TooltipPopoverProps) {\n const [popoverElement, setPopoverElement] = useState(null)\n const [arrowElement, setArrowElement] = useState(null)\n\n useClickOutside(popoverElement, onClose)\n useGlobalEscapeKeyHandler(onClose)\n\n useEffect(() => {\n referenceElement?.setAttribute('aria-describedby', TOOLTIP_POPOVER_ID)\n\n return () => referenceElement?.removeAttribute('aria-describedby')\n }, [referenceElement])\n\n const { styles, attributes } = usePopper(referenceElement, popoverElement, {\n placement,\n modifiers: [\n { name: 'arrow', options: { element: arrowElement, padding: 6 } },\n { name: 'offset', options: { offset: dynamicPopperOffset } },\n {\n name: 'flip',\n options: {\n padding: 16,\n allowedAutoPlacements: ['top', 'bottom'],\n },\n },\n {\n name: 'preventOverflow',\n options: { padding: 16, boundary: document.documentElement },\n },\n ],\n })\n\n return (\n \n {\n e.preventDefault()\n onClose()\n }}\n >\n \n \n {children}\n \n \n )\n}\n\ntype TooltipProps = Omit<\n TooltipPopoverProps,\n 'referenceElement' | 'onClose'\n> & {\n initiallyOpen?: boolean\n icon?: React.ReactNode\n}\n\nconst Tooltip = ({\n initiallyOpen = false,\n placement = 'top-end',\n zIndex = 1,\n backgroundColor = coreTheme['-ds-neutral-200']?.value,\n children,\n icon,\n}: TooltipProps) => {\n const [iconElement, setIconElement] = useState(null)\n const [open, setOpen] = useState(initiallyOpen)\n\n return (\n <>\n {\n setOpen(!open)\n }}\n >\n {icon || }\n \n {open && (\n setOpen(false)}\n >\n {children}\n \n )}\n >\n )\n}\n\nexport default Tooltip\n","import styled, { css } from 'styled-components'\nimport { media } from 'styles/media'\n\ninterface TextProps {\n uppercase?: boolean\n centered?: boolean\n noMargin?: boolean\n weight?: '500' | '400' | '300'\n styleLink?: boolean\n notResponsive?: boolean\n}\n\nconst baseTypographyStyles = css`\n ${({ noMargin }) =>\n noMargin &&\n `\n margin-top: 0;\n margin-bottom: 0;\n `}\n\n ${({ weight }) =>\n weight &&\n `\n font-weight: ${weight};\n `}\n\n ${media.md`\n text-align: ${({ centered }) => (centered ? 'center' : 'inherit')};\n `}\n\n ${({ styleLink, theme }) =>\n styleLink &&\n `\n a {\n text-decoration: underline;\n text-underline-offset: 1px;\n text-decoration-thickness: 1px;\n color: ${theme?.['-ds-core-400']?.value};\n\n &:hover {\n color: ${theme?.['-ds-core-300']?.value};\n }\n }\n `}\n`\n\nexport const SectionTitle = styled.h3`\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n letter-spacing: 0.08em;\n line-height: 1.3;\n text-transform: uppercase;\n margin-bottom: 8px;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 300;\n `}\n`\n\nexport const HeadingXxl = styled.h4`\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xl']?.['font-size']?.value};\n line-height: 1.3;\n margin-bottom: 24px;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 400;\n `}\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxl']?.['font-size']?.value};\n `}\n`\n\nexport const HeadingXl = styled.h4`\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-lg']?.['font-size']?.value};\n line-height: 1.3;\n margin-bottom: 24px;\n ${baseTypographyStyles}\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 400;\n `}\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xl']?.['font-size']?.value};\n `}\n`\n\nexport const HeadingLg = styled.h4`\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-md']?.['font-size']?.value};\n line-height: 1.3;\n margin-bottom: 8px;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 400;\n `}\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-lg']?.['font-size']?.value};\n `}\n`\n\nexport const HeadingMd = styled.h4`\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-sm']?.['font-size']?.value};\n line-height: 1.3;\n margin-bottom: 16px;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 400;\n `}\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-md']?.['font-size']?.value};\n `}\n`\n\nexport const HeadingSm = styled.h4`\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n line-height: 1.3;\n margin-bottom: 16px;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 400;\n `}\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-sm']?.['font-size']?.value};\n `}\n`\n\nexport const ParagraphLg = styled.p`\n ${baseTypographyStyles}\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-sm']?.['font-size']?.value};\n line-height: 1.3;\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 300;\n `}\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-lg']?.['font-size']?.value};\n line-height: 1.4;\n `}\n`\n\nexport const ParagraphMd = styled.p`\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n line-height: 1.4;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 300;\n `}\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-md']?.['font-size']?.value};\n max-width: 640px;\n margin-left: ${({ centered }) => (centered ? 'auto' : '0')};\n margin-right: ${({ centered }) => (centered ? 'auto' : '0')};\n `}\n`\n\nexport const ParagraphSm = styled.p`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n line-height: 1.4;\n letter-spacing: 0.01em;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 300;\n `}\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-sm']?.['font-size']?.value};\n line-height: 1.3;\n max-width: 640px;\n margin-left: ${({ centered }) => (centered ? 'auto' : '0')};\n margin-right: ${({ centered }) => (centered ? 'auto' : '0')};\n `}\n`\n\nexport const ParagraphXs = styled.p`\n\n font-size: ${({ theme, notResponsive }) =>\n !notResponsive\n ? theme['-ds-font-size-xxs']['font-size'].value\n : theme['-ds-font-size-xs']['font-size'].value};\n color: ${({ theme }) => theme?.['-ds-neutral-600']?.value};\n line-height: 1.4;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 300;\n `}\n\n ${media.md`\n font-size: ${({ theme }) => theme['-ds-font-size-xs']['font-size'].value};\n `}\n`\n\nexport const ParagraphXxs = styled.p`\n font-size: ${({ theme }) => theme['-ds-font-size-xxs']['font-size'].value};\n text-align: ${({ centered }) => (centered ? 'center' : 'inherit')};\n text-transform: ${({ uppercase }) => (uppercase ? 'uppercase' : 'none')};\n letter-spacing: 0.01em;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 300;\n `}\n`\n\nexport const ParagraphMicro = styled.p`\n font-size: ${({ theme }) => theme['-ds-font-size-xxxs']['font-size'].value};\n text-align: ${({ centered }) => (centered ? 'center' : 'inherit')};\n text-transform: ${({ uppercase }) => (uppercase ? 'uppercase' : 'none')};\n letter-spacing: 0.08em;\n\n ${baseTypographyStyles}\n\n ${({ weight }) =>\n !weight &&\n `\n font-weight: 400;\n `}\n`\n\nexport const StyledLink = styled.a`\n text-decoration: underline;\n text-underline-offset: 1px;\n text-decoration-thickness: 1px;\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n background-color: transparent;\n border: none;\n\n &:hover {\n color: ${({ theme }) => theme?.['-ds-core-300']?.value};\n }\n`\n","// @ts-nocheck\n\nimport { DayPickerRangeController } from 'react-dates'\n\n// Globally disable `CalendarDay__before_hovered_end` class name from being\n// added to react-dates calendar days - this styling is not used by our calendar\n// implementation and introduces problems due to bugs in the react-dates\n// implementation, e.g. when selecting the already-selected end date as the new\n// start date it causes the days before the end date to become stuck in the\n// \"hovered\" state.\n//\n// By overriding the prototype of the class component we can make attempts by\n// the component to set those styles to be a no-op:\n\nDayPickerRangeController.prototype.isDayBeforeHoveredEndDate = function customDayBeforeHoveredEndDate() {\n return false\n}\nconst originalAddModifierToRange =\n DayPickerRangeController.prototype.addModifierToRange\n\nDayPickerRangeController.prototype.addModifierToRange = function customAddModifierToRange(\n updatedDays,\n start,\n end,\n modifier\n) {\n if (modifier === 'before-hovered-end') {\n return updatedDays\n }\n return originalAddModifierToRange.call(\n this,\n updatedDays,\n start,\n end,\n modifier\n )\n}\n","import DiscountDescription from 'components/display/DiscountDescription'\nimport React from 'react'\nimport styled from 'styled-components'\n\nimport { DaysAvailabilities } from './types'\n\ntype DiscountProps = { discount?: DaysAvailabilities[string]['discount'] }\n\nconst DiscountIndicator = styled.span`\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background-color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n`\n\nconst DISCOUNT_DESCRIPTION_ID = 'discount'\n\nconst DiscountAvailableWrapper = styled.div`\n margin-bottom: 10px;\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n\n ${DiscountIndicator} {\n display: inline-block;\n margin: 0 0.4em 0.1em 0;\n }\n`\n\nexport const DiscountMarker = styled(DiscountIndicator).attrs({\n role: 'doc-noteref',\n 'aria-describedby': DISCOUNT_DESCRIPTION_ID,\n})``\n\nexport function DiscountAvailable({ discount }: DiscountProps) {\n return (\n \n \n {discount ? (\n \n ) : (\n <>Select dates to see discount amount>\n )}\n \n )\n}\n","import React from 'react'\nimport styled from 'styled-components'\n\nconst Wrapper = styled.div`\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin: 10px 0;\n`\n\nconst KeyWrapper = styled.div`\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 10px;\n`\n\nconst KeyIcon = styled.div`\n width: 20px;\n height: 20px;\n border: 1px solid ${({ theme }) => theme?.['-ds-neutral-300']?.value};\n\n &.check-in {\n background: linear-gradient(\n to top left,\n #fff 0%,\n #fff 49.9%,\n #ececec 50%,\n #ececec 100%\n );\n }\n\n &.check-out {\n background: linear-gradient(\n to bottom right,\n #fff 0%,\n #fff 49.9%,\n #ececec 50%,\n #ececec 100%\n );\n }\n`\n\nconst CalendarKeys = () => {\n return (\n \n \n \n Check-in only\n \n\n \n \n Checkout only\n \n \n )\n}\n\nexport default CalendarKeys\n","import React from 'react'\nimport pluralize from 'pluralize'\nimport styled from 'styled-components'\n\nimport { TooltipPopover } from 'components/display/Tooltip'\nimport { DaysAvailabilities, TooltipConfig } from './types'\nimport { DiscountAvailable } from './discounts'\nimport CalendarKeys from './CalendarKeys'\n\nconst AvailabilityInfoInner = styled.div`\n padding: 0 21px 8px 21px;\n color: ${({ theme }) => theme?.['-ds-neutral-500']?.value};\n`\n\nconst TooltipContents = styled.div`\n max-width: 220px;\n`\n\ninterface AvailabilityInfoProps {\n discountsVisible: boolean\n activeDiscount?: DaysAvailabilities[string]['discount']\n minimumNights?: number\n snoozed?: boolean\n concurrentBookings?: boolean\n tooltip?: TooltipConfig\n onCloseTooltip: (tooltip: TooltipConfig) => unknown\n}\n\nconst AvailabilityInfo = ({\n discountsVisible,\n activeDiscount,\n minimumNights,\n concurrentBookings,\n snoozed,\n tooltip,\n onCloseTooltip,\n}: AvailabilityInfoProps) => {\n return (\n <>\n \n {discountsVisible && }\n \n {concurrentBookings && (\n Availability needs to be confirmed by the host
\n )}\n {minimumNights > 1 && (\n \n The minimum booking is {pluralize('night', minimumNights, true)}\n
\n )}\n {snoozed ? (\n \n The host is currently taking a short break and isn't taking new\n bookings during this time.\n
\n ) : (\n \n Prices might be higher on weekends, holidays and during peak season\n
\n )}\n \n {tooltip && (\n onCloseTooltip(tooltip)}\n >\n {tooltip.message}\n \n )}\n >\n )\n}\n\nexport default AvailabilityInfo\n","import moment, { Moment } from 'moment'\nimport { sortedIndex } from 'lodash'\n\nimport { FocusedInput, DaysAvailabilities } from './types'\n\ntype FindAvailability = (arg0: {\n day: Moment\n daysData: DaysAvailabilities\n}) => DaysAvailabilities[string]\n\nexport const findAvailability: FindAvailability = ({ day, daysData }) => {\n return daysData[day.format('YYYY-MM-DD')]\n}\n\nfunction isPreviousDayAvailable(\n day: Moment,\n daysData: DaysAvailabilities\n): boolean {\n const prevDay = findAvailability({\n day: moment(day).subtract(1, 'day'),\n daysData,\n })\n\n if (prevDay) {\n return prevDay.available\n }\n return true\n}\n\nexport type FindNextUnavailableDay = (date: string) => Moment | null\n\ntype BuildFindNextUnavailableDayOptions = {\n daysData: DaysAvailabilities\n}\n\nexport function buildFindNextUnavailableDay({\n daysData,\n}: BuildFindNextUnavailableDayOptions): FindNextUnavailableDay {\n // `daysData` keys are dates in the ISO date format `'YYYY-MM-DD`, we can take\n // advantage of the lexicographical ordering of ISO dates to perform a binary\n // search over a sorted set of unavailable dates:\n const sortedUnavailableDates = Object.keys(daysData)\n .filter((day) => !daysData[day].available)\n .sort()\n\n return (date) => {\n const nextUnavailableDateIndex = sortedIndex(sortedUnavailableDates, date)\n\n if (nextUnavailableDateIndex === sortedUnavailableDates.length) {\n // No unavailable date was found, return null:\n return null\n }\n\n return moment(sortedUnavailableDates[nextUnavailableDateIndex]).endOf('day')\n }\n}\n\ntype DayStatusFunction = (day: Moment, dayDate?: string) => boolean\nfunction cachedDayResult(dayFn: DayStatusFunction): DayStatusFunction {\n const cache = new Map()\n\n return (day) => {\n const dayDate = day.format('YYYY-MM-DD')\n if (cache.has(dayDate)) {\n return cache.get(dayDate)\n }\n\n const result = dayFn(day, dayDate)\n cache.set(dayDate, result)\n return result\n }\n}\n\ntype IsDayBlocked = DayStatusFunction\n\ntype BuildIsDayBlockedOptions = {\n focusedInput: FocusedInput\n startDate?: Moment\n daysData: DaysAvailabilities\n}\n\nexport function buildIsDayBlocked({\n focusedInput,\n startDate,\n daysData,\n}: BuildIsDayBlockedOptions): IsDayBlocked {\n return cachedDayResult((day, dayDate) => {\n const availability = daysData[dayDate]\n const isAvailable = availability?.available !== false\n\n // Only perform check-out only test if there was an availability record\n // indicating that it was unavailable:\n if (availability && !isAvailable && focusedInput === 'endDate') {\n if (!startDate || day.isAfter(startDate)) {\n // Dates that are unavailable but where the previous day is available are\n // not blocked for the purposes of selecting an end date because they can\n // be used for check-out only:\n const previousDayAvailable = isPreviousDayAvailable(day, daysData)\n if (previousDayAvailable) {\n return false\n }\n }\n }\n\n return !isAvailable\n })\n}\n\nfunction supportsMinimumNights(\n day: Moment,\n dayDate: string,\n daysData: DaysAvailabilities,\n findNextUnavailableDay: FindNextUnavailableDay\n) {\n const availability = daysData[dayDate]\n const isAvailable = availability?.available !== false\n const minimumNights = availability?.minimumNights\n\n if (isAvailable && minimumNights > 0) {\n const unavailableDay = findNextUnavailableDay(dayDate)\n if (unavailableDay && unavailableDay.diff(day, 'days') < minimumNights) {\n // There aren't enough available days after the provided day to meet the\n // minimum nights requirements:\n return false\n }\n }\n\n return true\n}\n\ntype IsOutsideRange = DayStatusFunction\n\ntype BuildIsOutsideRangeOptions = {\n today: Moment\n focusedInput: FocusedInput\n startDate?: Moment\n maxStart?: Moment\n daysData: DaysAvailabilities\n firstUnavailableDate?: Moment\n findNextUnavailableDay: FindNextUnavailableDay\n}\n\nexport function buildIsOutsideRange({\n today,\n focusedInput,\n startDate,\n maxStart,\n daysData,\n firstUnavailableDate,\n findNextUnavailableDay,\n}: BuildIsOutsideRangeOptions): IsOutsideRange {\n if (focusedInput === 'startDate') {\n return cachedDayResult((day, dayDate) => {\n // Dates in the past cannot be selected:\n if (day.isBefore(today)) {\n return true\n }\n\n if (maxStart && day.isAfter(maxStart)) {\n // Dates beyond the maximum start date cannot be selected for a\n // start date:\n return true\n }\n\n return !supportsMinimumNights(\n day,\n dayDate,\n daysData,\n findNextUnavailableDay\n )\n })\n }\n\n return cachedDayResult((day, dayDate) => {\n // Dates in the past cannot be selected:\n if (day.isBefore(today)) {\n return true\n }\n\n if (startDate && day.isBefore(startDate)) {\n // When selecting an end date it is also possible to choose a new start\n // date, so we only want to allows days that support minimum nights:\n return !supportsMinimumNights(\n day,\n dayDate,\n daysData,\n findNextUnavailableDay\n )\n }\n\n if (firstUnavailableDate) {\n // If day is beyond the first unavailable day after `startDate`, then\n // it cannot be selected for an end date (the first unavailable day\n // itself can be selected because it is valid as a checkout day):\n return day.isAfter(firstUnavailableDate)\n }\n\n return false\n })\n}\n","import React, { useState } from 'react'\nimport styled from 'styled-components'\nimport moment, { Moment } from 'moment'\nimport { tint, transparentize } from 'polished'\n\nimport { formatPrice } from '../../utils/pricing'\nimport { findAvailability } from './dayAvailability'\n\nimport { DiscountMarker } from './discounts'\nimport { DaysAvailabilities, FocusedInput } from './types'\n\nconst DayNumber = styled.div`\n color: #333;\n font-size: 16px;\n`\n\nconst Detail = styled.div`\n height: 12px;\n font-size: 11px;\n margin-bottom: 4px;\n line-height: 1;\n color: ${tint(0.4, '#333')};\n overflow: visible;\n`\n\nconst Wrapper = styled.div`\n position: relative;\n display: flex;\n flex-direction: column;\n justify-content: space-around;\n text-align: center;\n align-items: center;\n padding: 4px 0;\n font-weight: 400;\n\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n\n // Ensure that focus/active outlines render correctly even when this element\n // has a background set:\n outline: inherit;\n\n &.discount {\n ${DiscountMarker} {\n position: absolute;\n top: 4px;\n left: 4px;\n }\n\n ${Detail} {\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n }\n }\n\n &.check-out-only {\n background: linear-gradient(\n to bottom right,\n #fff 0%,\n #fff 49.9%,\n #ececec 50%,\n #ececec 100%\n );\n\n .CalendarDay__hovered_span & {\n background: none;\n }\n }\n\n &.check-in-only {\n background: linear-gradient(\n to top left,\n #fff 0%,\n #fff 49.9%,\n #ececec 50%,\n #ececec 100%\n );\n }\n\n .CalendarDay__blocked_out_of_range:not(.CalendarDay__blocked_calendar) &:not(.past),\n .CalendarDay__blocked_minimum_nights &,\n &.check-out-only {\n cursor: pointer;\n }\n\n &.check-out-only,\n &.check-in-only {\n .CalendarDay:not(.CalendarDay__blocked_calendar):not(.CalendarDay__blocked_out_of_range)\n &:hover,\n .CalendarDay__selected & {\n background: none;\n }\n }\n\n &.past, &.after-max {\n .CalendarDay__blocked_out_of_range:not(.CalendarDay__blocked_calendar):not(.CalendarDay__selected_span):not(.CalendarDay__selected_end) & {\n background: #fff;\n }\n }\n\n &.past {\n .CalendarDay__blocked_out_of_range & {\n ${Detail} {\n // Hide pricing from user but still have it impact the layout:\n visibility: hidden;\n }\n }\n }\n\n .CalendarDay__default:active &,\n .CalendarDay__default:hover & {\n ${DayNumber}, ${Detail} {\n color: #333;\n }\n }\n\n .CalendarDay__blocked_calendar &,\n .CalendarDay__blocked_calendar:active &,\n .CalendarDay__blocked_calendar:hover & {\n ${DayNumber}, ${Detail} {\n color: ${tint(0.4, '#333')};\n }\n }\n\n .CalendarDay__blocked_out_of_range &,\n .CalendarDay__blocked_out_of_range:active &,\n .CalendarDay__blocked_out_of_range:hover &,\n .CalendarDay__blocked_minimum_nights & {\n ${DayNumber}, ${Detail} {\n color: ${tint(0.7, '#333')};\n }\n }\n\n .CalendarDay__selected_span &,\n .CalendarDay__selected_span:active &,\n .CalendarDay__selected_span:hover &,\n .CalendarDay__hovered_span &:not(.check-in-only) {\n ${DayNumber}, ${Detail} {\n color: #333;\n }\n }\n\n .CalendarDay__selected &,\n .CalendarDay__selected:active &,\n .CalendarDay__selected:hover & {\n ${DiscountMarker} {\n background-color: ${transparentize(0.6, '#fff')};\n }\n\n ${DayNumber} {\n color: #fff;\n }\n\n ${Detail} {\n color: ${transparentize(0.6, '#fff')};\n }\n }\n\n /* .CalendarDay__blocked_out_of_range &.past,\n .CalendarDay__blocked_calendar &:not(.check-out-only) {\n ${DayNumber} {\n text-decoration: line-through;\n }\n } */\n`\n\ntype CalendarDayProps = {\n focusedInput: FocusedInput\n day: Moment\n daysData: DaysAvailabilities\n today: Moment\n maxStartDate?: Moment\n startDate?: Moment\n firstUnavailableDate?: Moment\n activeDiscount?: DaysAvailabilities[string]['discount']\n onTooltipOpen: (referenceElement: HTMLElement, message: string) => unknown\n}\n\nconst CalendarDay = ({\n focusedInput,\n day,\n daysData,\n today,\n maxStartDate,\n startDate,\n firstUnavailableDate,\n activeDiscount,\n onTooltipOpen,\n}: CalendarDayProps) => {\n const [dayNumberElement, setDayNumberElement] = useState(null)\n\n const inThePast = day.isBefore(today)\n const afterMaxStart = day.isAfter(maxStartDate)\n\n const dayData = findAvailability({ day, daysData })\n const isAvailable = dayData?.available !== false\n\n const previousDayData = findAvailability({\n day: moment(day).subtract(1, 'day'),\n daysData,\n })\n const previousDayAvailable = previousDayData?.available !== false\n const availableForCheckInOnly = isAvailable && !previousDayAvailable\n const availableForCheckOutOnly = !isAvailable && previousDayAvailable\n const beyondFirstUnavailable =\n firstUnavailableDate && day.isAfter(firstUnavailableDate)\n\n const handleClick: React.MouseEventHandler = (e) => {\n const parentClassName = e.currentTarget.parentElement.className\n const isBlocked = parentClassName.includes('CalendarDay__blocked')\n const isUnavailable =\n parentClassName.includes('CalendarDay__blocked_calendar') &&\n !availableForCheckOutOnly\n const beforeStartDate =\n startDate && day.isBefore(moment(startDate).startOf('day'))\n\n // No tooltip for dates that aren't blocked, are in the past, or are\n // clearly unavailable (due to being booked):\n if (isUnavailable || !isBlocked || inThePast) {\n return\n }\n\n let message: string\n if (focusedInput === 'startDate' || beforeStartDate) {\n if (afterMaxStart) {\n const latestCheckIn = maxStartDate.format('D MMM YYYY')\n message = `Check-in cannot be later than ${latestCheckIn}`\n } else if (availableForCheckOutOnly) {\n message = 'Checkout only'\n } else if (dayData.minimumNights > 1) {\n message = `${dayData.minimumNights} night minimum stay`\n }\n } else if (parentClassName.includes('minimum_nights')) {\n const startDayData = findAvailability({ day: startDate, daysData })\n if (startDayData.minimumNights > 1) {\n // When selecting an end date some days are blocked because they don't\n // meet the minimum nights:\n message = `${startDayData.minimumNights} night minimum stay`\n }\n } else if (beyondFirstUnavailable) {\n const latestCheckOut = firstUnavailableDate.format('D MMM YYYY')\n message = `Closest available checkout is ${latestCheckOut}`\n }\n\n if (message) {\n onTooltipOpen(dayNumberElement, message)\n }\n }\n\n const inSelectableRange = isAvailable && !inThePast && !beyondFirstUnavailable\n // Only show discount if one exists, if the day is selectable and if the\n // discount is the same as the discount of the selected start date (if one is\n // selected):\n const showDiscount =\n inSelectableRange &&\n dayData?.discount &&\n (!startDate || activeDiscount?.id === dayData.discount.id)\n\n return (\n \n {showDiscount && }\n {day.format('D')}\n {isAvailable && dayData && formatPrice(dayData.price)}\n \n )\n}\n\nexport default React.memo(CalendarDay)\n","import React from 'react'\nimport styled from 'styled-components'\nimport moment, { Moment } from 'moment'\n\nimport useDateDisplayFormat from 'components/utils/useDateDisplayFormat'\nimport IconArrowRight from 'components/icons/ArrowRightSlim'\n\nconst Wrapper = styled.div`\n width: 100%;\n border-radius: 6px;\n border: 1px solid ${({ theme }) => theme?.['-ds-neutral-400']?.value};\n background-color: ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n display: flex;\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n justify-content: space-between;\n align-items: center;\n\n .date-input {\n flex: 1 1 auto;\n\n &:last-of-type input {\n text-align: right;\n }\n }\n\n input {\n width: 100%;\n border: none !important;\n outline: none !important;\n background-color: transparent;\n padding: 0;\n padding: 18px;\n }\n\n svg {\n width: 20px;\n max-height: 20px;\n }\n`\n\nconst DateInput = styled.input<{ $disabled?: boolean }>`\n color: ${({ $disabled, theme }) =>\n $disabled\n ? theme?.['-ds-neutral-500']?.value\n : theme?.['-ds-neutral-700']?.value};\n`\n\ninterface DatesInputProps {\n onDateClick: (type: 'start' | 'end') => any\n startDate: Moment\n endDate: Moment\n}\n\nconst DatesInput = ({ onDateClick, startDate, endDate }: DatesInputProps) => {\n const displayFormat = useDateDisplayFormat({ yearFormat: 'YYYY' })\n\n return (\n \n \n onDateClick('start')}\n $disabled={!startDate}\n autoComplete=\"off\"\n value={startDate ? moment(startDate).format(displayFormat) : ''}\n placeholder=\"Start date\"\n readOnly\n />\n
\n \n \n onDateClick('end')}\n $disabled={!endDate}\n readOnly\n autoComplete=\"off\"\n value={endDate ? moment(endDate).format(displayFormat) : ''}\n placeholder=\"End date\"\n />\n
\n \n )\n}\n\nexport default DatesInput\n","import styled from 'styled-components'\nimport { tint } from 'polished'\n\nimport { media } from 'styles/media'\n\nexport const CalendarWrapper = styled.div`\n padding: 44px 0;\n\n ${media.md`\n padding: 31px 12px;\n `}\n\n .DayPicker {\n margin: 0 auto;\n // Adding a min-height stops the calendar jumping around when navigating months\n min-height: 560px;\n }\n\n .CalendarDay__default {\n position: relative;\n\n &:focus,\n &:focus-visible {\n z-index: 1;\n }\n }\n\n .CalendarDay__default:active,\n .CalendarDay__default:hover {\n background: ${({ theme }) => tint(0.8, theme['-ds-core-400'].value)};\n border: 1px double ${({ theme }) => tint(0.8, theme['-ds-core-400'].value)};\n }\n\n .CalendarDay__blocked_calendar,\n .CalendarDay__blocked_out_of_range:active,\n .CalendarDay__blocked_out_of_range:hover {\n background: #fff;\n border-color: #e4e7e7;\n }\n\n .CalendarDay__blocked_calendar,\n .CalendarDay__blocked_calendar:active,\n .CalendarDay__blocked_calendar:hover {\n background: #ececec;\n border: 1px solid #ececec;\n }\n\n .CalendarDay__selected_span {\n background: #66e2da;\n border: 1px double #33dacd;\n border-right-style: solid; // Avoid border overlap with selected end date\n\n &:active,\n &:hover {\n background: #33dacd;\n border: 1px double #33dacd;\n border-right-style: solid; // Avoid border overlap with selected end date\n\n &.CalendarDay__blocked_calendar,\n &.CalendarDay__blocked_out_of_range {\n // Don't change appearance when hovered if blocked:\n background: #66e2da;\n border: 1px double #33dacd;\n border-right-style: solid; // Avoid border overlap with selected end date\n }\n }\n }\n\n .CalendarDay__selected {\n background: ${({ theme }) => theme['-ds-core-400'].value};\n border: 1px double ${({ theme }) => theme['-ds-core-400'].value};\n\n &:active,\n &:hover {\n background: ${({ theme }) => tint(0.1, theme['-ds-core-400'].value)};\n border: 1px double\n ${({ theme }) => tint(0.1, theme['-ds-core-400'].value)};\n\n &.CalendarDay__blocked_calendar,\n &.CalendarDay__blocked_out_of_range {\n // Don't change appearance when hovered if blocked:\n background: ${({ theme }) => theme['-ds-core-400'].value};\n border: 1px double ${({ theme }) => theme['-ds-core-400'].value};\n }\n }\n }\n`\n","import { useCallback, useMemo, useState } from 'react'\nimport moment, { Moment } from 'moment'\n\nimport { DaysAvailabilities } from './types'\nimport { findAvailability } from './dayAvailability'\n\ntype NumberOfMonths = 1 | 2\ntype VisibleMonths = [string, string?]\n\nconst MONTH_FORMAT = 'YYYY-MM'\n\nfunction buildVisibleMonths(\n visibleDate: Moment,\n numberOfMonths: NumberOfMonths\n): VisibleMonths {\n const visibleMonths: VisibleMonths = [visibleDate.format(MONTH_FORMAT)]\n\n if (numberOfMonths === 2) {\n visibleMonths.push(moment(visibleDate).add(1, 'M').format(MONTH_FORMAT))\n }\n\n return visibleMonths\n}\n\nexport function useVisibleMonths(\n startDate: Moment | null,\n numberOfMonths: NumberOfMonths\n) {\n const [visibleMonths, setVisibleMonths] = useState(() => {\n return buildVisibleMonths(startDate || moment(), numberOfMonths)\n })\n\n const updateCurrentMonth = useCallback(\n (currentMonth: Moment) => {\n setVisibleMonths(buildVisibleMonths(currentMonth, numberOfMonths))\n },\n [numberOfMonths]\n )\n\n return [visibleMonths, updateCurrentMonth] as const\n}\n\nexport default function useDiscountsVisible(\n startDate: Moment | null,\n numberOfMonths: NumberOfMonths,\n daysData: DaysAvailabilities\n) {\n const [visibleMonths, updateCurrentMonth] = useVisibleMonths(\n startDate,\n numberOfMonths\n )\n\n const discountsVisible = useMemo(() => {\n if (!daysData) {\n return false\n }\n\n if (startDate) {\n const startDateData = findAvailability({ day: startDate, daysData })\n return Boolean(startDateData?.discount)\n }\n\n const today = moment().format('YYYY-MM-DD')\n return Object.keys(daysData).some((date) => {\n if (date < today) {\n // We don't need to check dates in the past or after the selected\n // start date:\n return false\n }\n\n const dateData = daysData[date]\n return (\n dateData?.discount &&\n dateData?.available &&\n visibleMonths.some((month) => date.startsWith(month))\n )\n })\n }, [startDate, visibleMonths, daysData])\n\n return { discountsVisible, updateCurrentMonth }\n}\n","import React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport ReactDOM from 'react-dom'\nimport { change } from 'redux-form'\nimport { DayPickerRangeController } from 'react-dates'\n// @ts-ignore -- no typings for react-dates/constants\nimport { START_DATE, END_DATE } from 'react-dates/constants'\nimport moment, { Moment } from 'moment'\nimport styled from 'styled-components'\n\nimport { useMediaQueryContext } from 'contexts/MediaQueryContext'\nimport DialogModal from 'components/display/DialogModal'\nimport { HeadingMd } from 'components/display/Typography'\nimport InvisibleButton from 'components/display/InvisibleButton'\nimport './overrides'\nimport AvailabilityInfo from './AvailabilityInfo'\nimport CalendarDay from './CalendarDay'\nimport {\n findAvailability,\n buildFindNextUnavailableDay,\n buildIsDayBlocked,\n buildIsOutsideRange,\n} from './dayAvailability'\nimport useFirstUnavailableDate from './useFirstUnavailableDate'\nimport DatesInput from './DatesInput'\nimport { CalendarWrapper } from './styles'\nimport { FocusedInput, DaysAvailabilities, TooltipConfig } from './types'\nimport useDiscountsVisible from './useDiscountsVisible'\n\nconst CalendarHeader = styled.div`\n display: flex;\n align-items: center;\n margin-left: 20px;\n width: calc(100% - 32px);\n border-bottom: 1px solid ${({ theme }) => theme?.['-ds-neutral-300']?.value};\n padding-bottom: 16px;\n margin-bottom: 8px;\n\n ${InvisibleButton} {\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n text-decoration: underline;\n text-underline-offset: 2px;\n font-weight: 400;\n margin-left: 10px;\n }\n`\n\nexport interface BookingFormCalendarProps {\n start_date?: string\n end_date?: string\n dispatch: (arg0: any) => void\n formName: string\n daysData: DaysAvailabilities\n listing: {\n concurrentBookings: boolean\n listingType: {\n slug: string\n }\n }\n maxStartDate: string\n onMonthsForward?: (arg0: Moment) => any\n onMonthsBack?: (arg0: Moment) => any\n onCalendarClose?: () => any\n snoozed?: boolean\n}\n\nconst BookingFormCalendar = (props: BookingFormCalendarProps) => {\n const {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n start_date,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n end_date,\n daysData,\n dispatch,\n formName,\n listing,\n maxStartDate,\n onMonthsForward,\n onMonthsBack,\n onCalendarClose,\n snoozed,\n } = props\n\n const { lg: largerThanLg } = useMediaQueryContext()\n const [startDate, setStartDate] = useState(null)\n const [endDate, setEndDate] = useState(null)\n const [focusedInput, setFocusedInput] = useState(START_DATE)\n const [minimumNights, setMinimumNights] = useState(1)\n const [modalOpen, setModalOpen] = useState(false)\n const [isDayPickerFocused, setIsDayPickerFocused] = useState(true)\n\n useEffect(() => {\n if (start_date) setStartDate(moment(start_date))\n if (end_date) setEndDate(moment(end_date))\n }, [start_date, end_date])\n\n const onDatesChange = ({\n startDate: newStartDate,\n endDate: newEndDate,\n }: {\n startDate: Moment\n endDate: Moment\n }): void => {\n /**\n * `DayPickerRangeController` caches the currently focused date for keyboard\n * accessibility, this means when the user changes the startDate the focus\n * does not switch to the new date. To work around this we need the component\n * to see the `isFocused` prop change by toggle to false here, then back to\n * true in onBlur. To avoid React batching hiding the toggle behaviour we\n * need to use flushSync\n */\n ReactDOM.flushSync(() => {\n setIsDayPickerFocused(false)\n })\n\n const availability = findAvailability({ daysData, day: newStartDate })\n\n if (availability?.minimumNights) {\n setMinimumNights(availability.minimumNights)\n }\n\n if (!startDate || newStartDate.isSame(startDate)) {\n dispatch(\n change(\n formName,\n 'booking[start_date]',\n newStartDate && newStartDate.format('YYYY-MM-DD')\n )\n )\n dispatch(\n change(\n formName,\n 'booking[end_date]',\n newEndDate && newEndDate.format('YYYY-MM-DD')\n )\n )\n\n setStartDate(newStartDate)\n setEndDate(newEndDate)\n } else {\n /**\n * QA: If a user already has a date range selected,\n * when they go to select a new date range,\n * clear the existing selection after the first date is selected\n */\n dispatch(\n change(\n formName,\n 'booking[start_date]',\n newStartDate && newStartDate.format('YYYY-MM-DD')\n )\n )\n dispatch(change(formName, 'booking[end_date]', null))\n setStartDate(newStartDate)\n setEndDate(null)\n }\n\n if (newEndDate && !newEndDate.isSame(endDate)) {\n setModalOpen(false)\n }\n }\n\n const handleDateClick = useCallback(\n (type: 'start' | 'end') => {\n if (type === 'start') {\n setFocusedInput(START_DATE)\n } else {\n setFocusedInput(startDate ? END_DATE : START_DATE)\n }\n\n setModalOpen(true)\n },\n [startDate]\n )\n\n const handleClearDates = useCallback(() => {\n setStartDate(null)\n setEndDate(null)\n setFocusedInput(START_DATE)\n }, [])\n\n const maxStart = useMemo(\n () => maxStartDate && moment(maxStartDate).endOf('day'),\n [maxStartDate]\n )\n\n const isDayBlocked = useMemo(\n () => buildIsDayBlocked({ focusedInput, startDate, daysData }),\n [focusedInput, startDate, daysData]\n )\n\n const findNextUnavailableDay = useMemo(\n () => buildFindNextUnavailableDay({ daysData }),\n [daysData]\n )\n\n const today = useMemo(() => moment().startOf('day'), [new Date().getDay()])\n const firstUnavailableDate = useFirstUnavailableDate(\n startDate,\n findNextUnavailableDay\n )\n\n const isOutsideRange = useMemo(\n () =>\n buildIsOutsideRange({\n today,\n focusedInput,\n startDate,\n maxStart,\n daysData,\n firstUnavailableDate,\n findNextUnavailableDay,\n }),\n [\n today,\n focusedInput,\n startDate,\n maxStart,\n daysData,\n firstUnavailableDate,\n findNextUnavailableDay,\n ]\n )\n\n const [tooltip, setTooltip] = useState(null)\n\n const numberOfMonths = largerThanLg ? 2 : 1\n const { discountsVisible, updateCurrentMonth } = useDiscountsVisible(\n startDate,\n numberOfMonths,\n daysData\n )\n\n const startDayData =\n startDate && findAvailability({ day: startDate, daysData })\n\n const renderAvailabilityInfo = () => (\n {\n setTooltip((lastTooltip) => {\n if (\n closedTooltip.referenceElement === lastTooltip?.referenceElement\n ) {\n return null\n }\n\n return lastTooltip\n })\n }}\n />\n )\n\n const renderDayContents = useCallback(\n (day: Moment) => (\n {\n setTooltip({ referenceElement, message })\n }}\n />\n ),\n [\n focusedInput,\n daysData,\n today,\n maxStart,\n startDate,\n startDayData,\n firstUnavailableDate,\n ]\n )\n\n const handleNextMonthClick = useCallback(\n (currentMonth) => {\n updateCurrentMonth(currentMonth)\n return onMonthsForward ? onMonthsForward(currentMonth) : undefined\n },\n [onMonthsForward, updateCurrentMonth]\n )\n\n const handlePrevMonthClick = useCallback(\n (currentMonth) => {\n updateCurrentMonth(currentMonth)\n return onMonthsBack ? onMonthsBack(currentMonth) : undefined\n },\n [onMonthsBack, updateCurrentMonth]\n )\n\n return (\n <>\n \n\n setModalOpen(false)}\n smallModal\n autoWidth\n closeButtonColour=\"-ds-neutral-700\"\n rounded\n noPadding\n >\n \n \n \n {!startDate && !endDate && 'Select dates'}\n {startDate && `${moment(startDate).format('DD MMM')} - `}\n {endDate && moment(endDate).format('DD MMM')}\n \n\n {startDate && (\n \n Clear dates\n \n )}\n \n\n setIsDayPickerFocused(true)}\n hideKeyboardShortcutsPanel\n calendarInfoPosition=\"bottom\"\n firstDayOfWeek={1}\n transitionDuration={0} // Fix for iOS 14\n />\n \n \n >\n )\n}\n\nexport default BookingFormCalendar\n","import { useMemo, useRef } from 'react'\nimport { Moment } from 'moment'\n\nimport { FindNextUnavailableDay } from './dayAvailability'\n\nexport default function useFirstUnavailableDate(\n startDate: Moment,\n findNextUnavailableDay: FindNextUnavailableDay\n) {\n // Memoize firstUnavailable using a ref + memo, so that calculations of\n // the new value can be derived off of the previous value.\n const firstUnavailable = useRef<{\n startDate: Moment\n unavailableDate: Moment\n }>({ startDate: null, unavailableDate: null })\n\n // Because `current` is set on every render, we can rely upon it being up\n // to date for that specific render pass (normally if a ref is async it may\n // not trigger a re-render but that isn't a concern here):\n firstUnavailable.current = useMemo(() => {\n const { current } = firstUnavailable\n if (startDate) {\n // If a start date is set we want to calculate the next unavailable date,\n // but only if we haven't found one already (this avoids problems if the\n // user pages so far forward in the calendar that the data set no longer\n // includes the start date, such that recalculating the next unavailable\n // date would be inaccurate):\n if (!current.unavailableDate || startDate !== current.startDate) {\n return {\n startDate,\n unavailableDate: findNextUnavailableDay(\n startDate.format('YYYY-MM-DD')\n ),\n }\n }\n\n return current\n }\n\n // Clear out when there is no longer a start date selected:\n return { startDate: null, unavailableDate: null }\n }, [startDate, findNextUnavailableDay])\n\n return firstUnavailable.current.unavailableDate\n}\n","import moment, { Moment } from 'moment'\n\n// set data start date to include one month either side of the 2 \"on screen\" months\nexport const getInitialStartDate = (\n startDate: string | Moment,\n offsetInMonths: number = 1\n) => moment(startDate).subtract(offsetInMonths, 'month').startOf('month')\nexport const getInitialEndDate = (\n startDate: string | Moment,\n offsetInMonths: number = 2\n) => moment(startDate).add(offsetInMonths, 'months').endOf('month')\n\nexport const getInitialDataBounds = (\n startDate?: string | Moment,\n offscreenMonthsEitherSide: number = 1\n) => {\n if (startDate == null || moment(startDate).isValid() !== true) {\n // eslint-disable-next-line no-param-reassign\n startDate = moment()\n }\n\n const startDateOffset = offscreenMonthsEitherSide\n const endDateOffset = offscreenMonthsEitherSide + 1 // there are 2 months on screen at any one time -- need to shift by 1\n return {\n initialDataStartDate: getInitialStartDate(startDate, startDateOffset),\n initialDataEndDate: getInitialEndDate(startDate, endDateOffset),\n }\n}\n\ninterface MoveDataWindowArgs {\n dataStartDate: string | Moment\n dataEndDate: string | Moment\n shiftByMonths?: number\n}\n\nexport const moveDataWindowForward = ({\n dataStartDate,\n dataEndDate,\n shiftByMonths = 1,\n}: MoveDataWindowArgs) => {\n const nextDataStartDate = moment(dataStartDate)\n .add(shiftByMonths, 'month')\n .startOf('month')\n const nextDataEndDate = moment(dataEndDate)\n .add(shiftByMonths, 'month')\n .endOf('month')\n\n return {\n nextDataStartDate,\n nextDataEndDate,\n }\n}\n\nexport const moveDataWindowBackwards = ({\n dataStartDate,\n dataEndDate,\n shiftByMonths = 1,\n}: MoveDataWindowArgs) => {\n const nextDataStartDate = moment(dataStartDate)\n .subtract(shiftByMonths, 'month')\n .startOf('month')\n const nextDataEndDate = moment(dataEndDate)\n .subtract(shiftByMonths, 'month')\n .endOf('month')\n\n return {\n nextDataStartDate,\n nextDataEndDate,\n }\n}\n","import React, { useCallback, useEffect, useState } from 'react'\nimport styled from 'styled-components'\nimport { connect } from 'react-redux'\nimport { Moment } from 'moment'\nimport { QueryResult } from '@apollo/client'\nimport debounce from 'lodash/debounce'\n\nimport {\n useGetCalendarDaysForBookingQuery,\n useGetCalendarDaysForListingQuery,\n} from 'hooks/useQueries'\n\nimport Overlay from '../../display/Overlay'\nimport Spinner from '../../display/Spinner'\n\nimport BookingFormCalendar from './BookingFormCalendarComponent'\nimport {\n getInitialDataBounds,\n moveDataWindowForward,\n moveDataWindowBackwards,\n} from './utils/monthDataBounds'\n\nimport { DaysAvailabilities } from './types'\n\nconst MONTHS_EITHER_SIDE_OF_ONSCREEN = 2\nconst MS_FETCHMORE_DEBOUNCE = 500\n\nconst PlaceholderInput = styled.div`\n position: relative;\n min-width: 280px;\n min-height: 60px;\n width: 100%;\n overflow: hidden;\n padding: 18px;\n border-radius: 6px;\n border: 1px solid ${({ theme }) => theme?.['-ds-neutral-400']?.value};\n background-color: ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n`\n\nconst formatDateForGql = (date: Moment) => date.format('YYYY-MM-DD')\n\nconst availabilitiesToDict = (\n days:\n | GQL_GetCalendarDaysForListingQuery['listing']['calendar']['days']\n | GQL_GetCalendarDaysForBookingQuery['booking']['calendar']['days']\n) =>\n days.reduce(\n (daysDict: DaysAvailabilities, day: DaysAvailabilities[string]) => {\n return {\n ...daysDict,\n [day.date]: day,\n }\n },\n {}\n )\n\ntype DateRange = { startDate: string; endDate: string }\n\ntype BookingDays = QueryResult<\n GQL_GetCalendarDaysForBookingQuery,\n Exact<{\n bookingId: string\n startDate: any\n endDate: any\n }>\n>\n\ntype ListingDays = QueryResult<\n GQL_GetCalendarDaysForListingQuery,\n Exact<{\n bookingId: string\n startDate: any\n endDate: any\n }>\n>\n\nfunction useCalendarDaysQuery(\n dateRange: DateRange,\n listingId: number,\n bookingId: number\n): BookingDays\nfunction useCalendarDaysQuery(\n dateRange: DateRange,\n listingId: number\n): ListingDays\nfunction useCalendarDaysQuery(\n dateRange: DateRange,\n listingId: number,\n bookingId?: number\n) {\n const resultBooking = useGetCalendarDaysForBookingQuery({\n skip: bookingId == null,\n variables: {\n bookingId: bookingId?.toString(),\n ...dateRange,\n },\n })\n const resultListing = useGetCalendarDaysForListingQuery({\n skip: bookingId != null,\n variables: {\n listingId: listingId.toString(),\n ...dateRange,\n },\n })\n\n if (bookingId) {\n return resultBooking\n }\n\n return resultListing\n}\n\ninterface BookingFormWithDataProps {\n bookingId: number\n dispatch: (...arg: any) => any\n formName: string\n listingId: number\n start_date?: string\n end_date?: string\n}\n\nconst BookingFormWithData = (props: BookingFormWithDataProps) => {\n const {\n bookingId,\n listingId,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n start_date,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n end_date,\n dispatch,\n formName,\n } = props\n\n const { initialDataStartDate, initialDataEndDate } = getInitialDataBounds(\n start_date,\n MONTHS_EITHER_SIDE_OF_ONSCREEN\n )\n\n const [dataStartDate, setDataStartDate] = useState(initialDataStartDate)\n const [dataEndDate, setDataEndDate] = useState(initialDataEndDate)\n\n useEffect(() => {\n const {\n initialDataStartDate: newInitialStartDate,\n initialDataEndDate: newInitialEndDate,\n } = getInitialDataBounds(start_date, MONTHS_EITHER_SIDE_OF_ONSCREEN)\n\n setDataStartDate(newInitialStartDate)\n setDataEndDate(newInitialEndDate)\n }, [start_date])\n\n const dateRange = {\n startDate: formatDateForGql(initialDataStartDate),\n endDate: formatDateForGql(initialDataEndDate),\n }\n\n const { data, error, loading, fetchMore } = useCalendarDaysQuery(\n dateRange,\n listingId,\n bookingId\n )\n\n const fetchMoreData = useCallback(\n ({\n nextDataStartDate,\n nextDataEndDate,\n }: {\n nextDataStartDate: Moment\n nextDataEndDate: Moment\n }) =>\n fetchMore({\n variables: {\n [bookingId ? 'bookingId' : 'listingId']: bookingId || listingId,\n startDate: formatDateForGql(nextDataStartDate),\n endDate: formatDateForGql(nextDataEndDate),\n },\n updateQuery: (prev, { fetchMoreResult }) => {\n if (!fetchMoreResult) return prev\n return fetchMoreResult\n },\n }),\n [bookingId, listingId]\n )\n const debouncedFetchMoreData = debounce(fetchMoreData, MS_FETCHMORE_DEBOUNCE)\n\n const onMonthsBack = useCallback(() => {\n const { nextDataStartDate, nextDataEndDate } = moveDataWindowBackwards({\n dataStartDate,\n dataEndDate,\n })\n\n debouncedFetchMoreData({ nextDataStartDate, nextDataEndDate })\n setDataStartDate(nextDataStartDate)\n setDataEndDate(nextDataEndDate)\n }, [dataStartDate, dataEndDate])\n\n const onMonthsForward = useCallback(() => {\n const { nextDataStartDate, nextDataEndDate } = moveDataWindowForward({\n dataStartDate,\n dataEndDate,\n })\n\n debouncedFetchMoreData({ nextDataStartDate, nextDataEndDate })\n setDataStartDate(nextDataStartDate)\n setDataEndDate(nextDataEndDate)\n }, [dataStartDate, dataEndDate])\n\n if (error) {\n return (\n \n Oops, couldn't get the booking information for this listing. Please\n let us know!\n
\n )\n }\n\n if (loading || !data) {\n return (\n \n \n \n \n \n )\n }\n\n let calendar\n if (bookingId) {\n calendar = (data as GQL_GetCalendarDaysForBookingQuery).booking.calendar\n } else {\n calendar = (data as GQL_GetCalendarDaysForListingQuery).listing.calendar\n }\n\n const { days, maxStartDate } = calendar\n\n // reduce availability data to a dictionary for more efficient lookup later\n const daysData = availabilitiesToDict(days)\n\n return (\n \n )\n}\n\nexport default connect()(BookingFormWithData)\n","import React from 'react'\n\nconst StepperButtonMinus = (props) => (\n \n)\n\nexport default StepperButtonMinus\n","import React from 'react'\n\nconst StepperButtonPlus = (props) => (\n \n)\n\nexport default StepperButtonPlus\n","import React from 'react'\nimport styled from 'styled-components'\nimport { Field } from 'redux-form'\nimport pluralize from 'pluralize'\n\nimport ChevronDown from '../icons/ChevronDown'\nimport StepperButtonMinusIcon from '../icons/StepperButtonMinus'\nimport StepperButtonPlusIcon from '../icons/StepperButtonPlus'\nimport Panel from '../display/Panel'\n\nimport { AGE_ANNOTATIONS } from '../../search/filters/common/QuantitySelect'\n\nexport const Wrapper = styled.div`\n position: relative;\n width: 100%;\n padding: 18px;\n\n ${({ noMargin }) => !noMargin && 'margin: 8px 0 8px;'}\n\n border: 1px solid\n ${({ theme, error }) =>\n error\n ? theme?.['-ds-error-300']?.value\n : theme?.['-ds-neutral-400']?.value};\n\n ${({ rounded }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n ${({ open }) =>\n open &&\n `\n border-bottom: 0;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n `}\n\n background-color: white;\n\n &:focus {\n border-color: ${({ theme }) => theme.brand.jungle};\n }\n\n > span {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n pointer-events: none;\n top: 0;\n right: 0;\n\n height: 100%;\n padding: 0 18px;\n\n color: ${({ theme }) => theme?.['-ds-neutral-400']?.value};\n }\n\n svg {\n width: 13px;\n height: 6px;\n }\n`\n\nconst Trigger = styled.button.attrs({ type: 'button' })`\n position: absolute;\n width: 100%;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n padding: 18px;\n\n text-align: left;\n appearance: none;\n background: transparent;\n border: 0;\n outline: 0;\n`\n\nconst Dropdown = styled.div`\n position: absolute;\n left: -1px;\n right: -1px;\n top: 100%;\n\n padding: 18px;\n\n border: 1px solid ${({ theme }) => theme?.['-ds-neutral-400']?.value};\n border-top: 0;\n border-bottom-left-radius: 6px;\n border-bottom-right-radius: 6px;\n background-color: white;\n\n z-index: 9;\n`\n\nexport const Option = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n margin-bottom: 15px;\n`\n\nexport const Label = styled.div`\n display: flex;\n align-items: flex-start;\n flex-direction: column;\n\n div {\n color: ${({ theme }) => theme.colors.labelGrey};\n font-size: 14px;\n }\n`\n\nexport const Footer = styled.footer`\n width: 100%;\n margin-top: 20px;\n text-align: right;\n`\n\nexport const CloseButton = styled.button`\n display: inline-block;\n appearance: none;\n outline: 0;\n border: none;\n background: none;\n\n padding: 10px 20px;\n padding-right: 0;\n color: ${({ theme }) => theme.brand.jungle};\n\n text-transform: uppercase;\n`\n\nconst Stepper = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100px;\n`\n\nconst StepButton = styled.button.attrs({ type: 'button' })`\n width: 26px;\n height: 26px;\n padding: 0;\n\n appearance: none;\n border: none;\n background: none;\n border-radius: 0;\n\n text-align: center;\n\n color: ${({ theme, active }) => (active ? theme.brand.jungle : '#C9C9C9')};\n\n svg {\n display: inline-block;\n width: 100%;\n height: 100%;\n }\n`\n\nexport const renderStepper = ({\n input: { value, onChange },\n guests,\n capacity,\n minValue = 0,\n increaseLabel = 'Plus',\n decreaseLabel = 'Minus',\n}) => (\n \n onChange(value - 1 >= minValue ? value - 1 : value)}\n active={value > minValue}\n aria-label={decreaseLabel}\n >\n \n \n {value}
\n onChange(guests < capacity ? value + 1 : value)}\n active={guests < capacity}\n aria-label={increaseLabel}\n >\n \n \n \n)\n\nclass GuestsInput extends React.Component {\n state = {\n open: false,\n }\n\n handleToggle = () => {\n this.setState({ open: !this.state.open })\n }\n\n handleClose = () => {\n this.setState({ open: false })\n }\n\n render() {\n const { guests } = this.props\n const { open } = this.state\n\n return (\n \n \n \n {pluralize('Person', guests, true)}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n )\n }\n}\n\nGuestsInput.defaultProps = {\n guests: 1,\n capacity: 99,\n}\n\nexport default GuestsInput\n","import React, { useEffect, useRef, useState } from 'react'\nimport styled from 'styled-components'\nimport { Field } from 'redux-form'\nimport Input from 'react-phone-number-input/input'\nimport en from 'react-phone-number-input/locale/en.json'\nimport { getCountries, getCountryCallingCode } from 'react-phone-number-input'\nimport { isValidNumber, parsePhoneNumber } from 'libphonenumber-js'\n\nimport { useGetUserCountryAndStripeKeyQuery } from 'hooks/useQueries'\n\nimport ChevronDown from '../icons/ChevronDown2'\nimport ValidIcon from '../icons/Valid'\n\nimport { InputGroup, SelectField } from '.'\n\nexport const validPhoneNumber = (value) => {\n if (value && !isValidNumber(value)) {\n return 'Not a valid phone number'\n }\n\n return undefined\n}\n\nconst PhoneInputWrapper = styled.div`\n position: relative;\n width: 100%;\n flex: 1;\n overflow: hidden;\n\n margin: 8px 0 8px;\n\n border: 1px solid\n ${({ theme, error, success }) => {\n if (error) {\n return theme?.['-ds-error-300']?.value\n }\n\n if (success) {\n return theme.brand.jungle\n }\n\n return theme.colors.textGreyLight\n }};\n\n ${({ rounded }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n input {\n width: 100%;\n padding: 18px;\n border: none;\n outline: none;\n }\n\n .PhoneInputCountry {\n padding-left: 18px;\n }\n\n & > svg {\n position: absolute;\n\n top: 50%;\n width: 20px;\n\n height: 20px;\n right: 20px;\n\n color: #9b9b9b;\n\n transform: translateY(-50%);\n }\n`\n\nconst CountrySelect = ({ value, onChange, labels = en, rounded, ...rest }) => {\n const countries = getCountries()\n\n const preferredCountries = ['AU', 'NZ', 'US']\n\n return (\n \n \n \n \n \n \n \n )\n}\n\nconst useCountryState = (value) => {\n const [country, setCountry] = useState()\n\n const { data } = useGetUserCountryAndStripeKeyQuery({\n fetchPolicy: 'cache-and-network',\n skip: country != null,\n })\n\n const userDefaultCountryCode = data?.currentUser?.defaultCountry?.code\n\n const setOnceFromValue = useRef(false)\n\n // set initial state once based on on user's default country unless it's been set based on initial value\n useEffect(() => {\n if (country == null && setOnceFromValue.current === false) {\n setCountry(userDefaultCountryCode)\n }\n }, [userDefaultCountryCode, setOnceFromValue])\n\n // set initial state once based on value -- this pre-populates the field when a saved phone number already exists\n useEffect(() => {\n if (setOnceFromValue.current === true) {\n return\n }\n\n let parsed\n\n try {\n parsed = parsePhoneNumber(value)\n } catch (parseError) {\n if (parseError?.message === 'TOO_SHORT') {\n // ignore, this is okay, as parsed object will still have country property with a value\n }\n }\n\n if (parsed?.country) {\n setCountry(parsed?.country)\n setOnceFromValue.current = true\n }\n }, [value, setOnceFromValue])\n\n return [country, setCountry]\n}\n\nexport const PhoneInput = ({\n input,\n meta: { error, submitFailed },\n showAsValid,\n phoneInputClassName,\n rounded,\n ...custom\n}) => {\n const { value, onChange, name: phoneInputName } = input\n\n const [country, setCountry] = useCountryState(value)\n\n const handleChangeCountry = (newCountry) => {\n onChange('') // reset phone number value when a new country is chosen\n setTimeout(() => {\n setCountry(newCountry)\n }, 0)\n }\n\n return (\n \n \n \n \n {showAsValid && }\n \n \n )\n}\n\nexport default (props) => {\n return (\n (value === undefined ? '' : value)}\n {...props}\n />\n )\n}\n","import React from 'react'\nimport { connect } from 'react-redux'\nimport styled from 'styled-components'\nimport { TextFieldWrapper } from '.'\n\nconst InputWrapper = styled.div`\n input {\n width: 100%;\n padding: 18px;\n margin: 8px 0 8px;\n outline: 0;\n color: ${({ theme, readOnly, disabled }) =>\n readOnly || disabled ? theme.colors.labelGrey : 'black'};\n text-overflow: ellipsis;\n border: 1px solid\n ${({ theme, error, success }) =>\n error\n ? theme?.['-ds-error-300']?.value\n : success\n ? theme.brand.jungle\n : theme.colors.textGreyLight};\n\n ${({ rounded }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n &:focus {\n border-color: ${({ theme }) => theme.brand.jungle};\n }\n }\n`\n\nclass PlacesInput extends React.Component {\n constructor(props) {\n super(props)\n this.Autocomplete = null\n this.AutocompleteInstance = null\n }\n\n componentDidMount() {\n // google maps script loading is deferred -- component needs to be able to wait until it has finished loading\n if (window.google) {\n this.Autocomplete = google.maps.places.Autocomplete\n this.instantiateAutocomplete()\n }\n\n const googleScript = document.getElementById('google-maps-script')\n googleScript.addEventListener('load', () => {\n this.Autocomplete = google.maps.places.Autocomplete\n this.instantiateAutocomplete()\n })\n }\n\n handleChange = (e) => {\n const { onSelectChange, input } = this.props\n\n input.onChange(e)\n\n if (onSelectChange) {\n onSelectChange({\n latitude: null,\n longitude: null,\n googlePlaceId: null,\n })\n }\n }\n\n handleSelect() {\n const { onSelectChange } = this.props\n const {\n formatted_address,\n geometry: { location },\n place_id,\n } = this.AutocompleteInstance.getPlace()\n\n if (onSelectChange) {\n onSelectChange({\n location: formatted_address,\n latitude: location.lat(),\n longitude: location.lng(),\n googlePlaceId: place_id,\n })\n }\n }\n\n instantiateAutocomplete() {\n const { onlyRegions, country } = this.props\n const additionalProps = onlyRegions\n ? {\n types: ['(regions)'],\n }\n : {\n componentRestrictions: {\n country,\n },\n }\n this.AutocompleteInstance = new this.Autocomplete(this.input, {\n ...additionalProps,\n })\n // Prevent the browser autocomplete menu from appearing.\n setTimeout(\n () => this.input?.setAttribute('autocomplete', 'new-location'),\n 200\n )\n this.AutocompleteInstance.addListener('place_changed', () =>\n this.handleSelect()\n )\n }\n\n componentDidlUnmount() {\n this?.Autocomplete?.removeListener('place_changed', () =>\n this.handleSelect()\n )\n }\n\n render() {\n const {\n input,\n meta: { error, submitFailed },\n rounded = true,\n placeholder,\n } = this.props\n\n return (\n \n \n {\n this.input = node\n }}\n onChange={this.handleChange}\n value={input.value}\n />\n \n \n )\n }\n}\n\nexport default connect()(PlacesInput)\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport { InputGroup, Label, ErrorLabel, Hint, OptionalTag } from '.'\n\nlet AutosizeTextarea = () => {}\nif (typeof document !== 'undefined') {\n // eslint-disable-next-line global-require\n AutosizeTextarea = require('react-textarea-autosize').default\n}\n\nexport const Textarea = styled(AutosizeTextarea)\n .attrs((props) => ({\n minRows: 8,\n ...props,\n }))\n .withConfig({\n shouldForwardProp: (prop) =>\n [\n 'rounded',\n 'error',\n 'readOnly',\n 'white',\n 'isPlaceholder',\n 'grey',\n 'noResize',\n 'noMargin',\n 'smallMargin',\n 'minRows',\n ].includes(prop) !== true,\n })`\n width: 100%;\n padding: 18px;\n margin: 8px 0 8px;\n outline: 0;\n resize: vertical;\n color: black;\n border: 1px solid\n ${({ theme, error }) =>\n error ? theme?.['-ds-error-300']?.value : theme.colors.textGreyLight};\n\n ${({ rounded = true }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n &:focus {\n border-color: ${({ theme }) => theme.brand.jungle};\n }\n\n ${({ rounded }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n ${({ noResize }) =>\n noResize &&\n `\n resize: none;\n `}\n`\n\nexport const renderTextArea = ({\n input,\n label,\n hint,\n meta: { form, error, submitFailed },\n noSubmitFailed,\n optional,\n bigLabel,\n mediumLabel,\n liteLabel,\n minRows,\n ...custom\n}) => (\n \n {label && (\n \n )}\n \n {error && (noSubmitFailed || submitFailed) && (\n {error}\n )}\n {hint && {hint}}\n \n)\n","import React from 'react'\n\nconst SvgIconExperiences = (props) => (\n \n)\n\nexport default SvgIconExperiences\n","import React from 'react'\n\nconst SvgIconEquipment = (props) => (\n \n)\n\nexport default SvgIconEquipment\n","import React from 'react'\n\nconst SvgIconKombi = (props) => (\n \n)\n\nexport default SvgIconKombi\n","import React from 'react'\n\nconst Warning = () => (\n \n)\n\nexport default Warning\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport Panel from '../display/Panel'\nimport ChevronDown from '../icons/ChevronDown'\n\nexport const Wrapper = styled.div`\n position: relative;\n width: 100%;\n padding: 18px;\n margin: 8px 0 8px;\n border: 1px solid\n ${({ theme, error }) =>\n error ? theme?.['-ds-error-300']?.value : theme.colors.textGreyLight};\n\n background-color: ${({ white }) => (white ? 'white' : 'transparent')};\n\n &:focus {\n border-color: ${({ theme }) => theme.brand.jungle};\n }\n\n color: black;\n\n select {\n position: absolute;\n width: 100%;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n padding: 0 18px;\n\n appearance: none;\n overflow: hidden;\n background: transparent;\n color: currentColor;\n border: 0;\n outline: 0;\n }\n\n span {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n pointer-events: none;\n top: 0;\n right: 0;\n\n height: 100%;\n padding: 0 18px;\n }\n\n svg {\n width: 13px;\n height: 6px;\n }\n`\n\nconst Trigger = styled.button.attrs({ type: 'button' })`\n appearance: none;\n background-color: #fff;\n\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n padding: 18px;\n\n text-align: left;\n border: 0;\n\n ${({ roundedLeft, open }) => {\n if (roundedLeft) {\n if (open) {\n return `\n border-top-left-radius: 6px;\n `\n }\n\n return `\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n `\n }\n\n return ``\n }}\n`\n\nconst Dropdown = styled.ul`\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n\n margin: 0;\n padding: 0;\n\n text-align: left;\n\n background: white;\n border: 1px solid ${({ theme }) => theme.colors.textGreyLight};\n\n z-index: 999;\n\n li {\n display: block;\n padding: 18px;\n outline: 0;\n\n border-bottom: 1px solid ${({ theme }) => theme.colors.textGreyLight};\n\n &:last-child {\n border-bottom: none;\n }\n\n &:hover {\n cursor: pointer;\n background: white;\n color: ${({ theme }) => theme.brand.jungle};\n }\n\n &.selected {\n color: white;\n background: ${({ theme }) => theme.brand.jungle};\n }\n }\n\n ${({ roundedBottom }) =>\n roundedBottom &&\n `\n border-bottom-left-radius: 6px;\n border-bottom-right-radius: 6px;\n overflow: hidden;\n `}\n`\n\nexport default class DropdownField extends React.Component {\n constructor(props) {\n super(props)\n this.state = {\n open: false,\n }\n }\n\n onToggle = () => {\n const { open: prev } = this.state\n\n this.setState({\n open: !prev,\n })\n }\n\n onClose = () => {\n this.setState({\n open: false,\n })\n }\n\n handleChange = (code) => {\n const {\n input: { onChange },\n } = this.props\n onChange(code)\n this.onClose()\n }\n\n render() {\n const {\n input: { value },\n meta: { error, submitFailed },\n placeholder,\n items,\n white,\n roundedLeft,\n roundedDropdown,\n } = this.props\n\n const { open } = this.state\n const selectedItem = items.find((item) => item.id === value)\n return (\n \n \n \n {selectedItem ? selectedItem.label : placeholder}\n \n \n \n {items.map(({ id, label }, index) => (\n this.handleChange(id)}\n >\n {label}\n \n ))}\n \n \n \n \n \n \n )\n }\n}\n","import React from 'react'\nimport styled from 'styled-components'\nimport Cleave from 'cleave.js/react'\n\nconst MaskedInputWrapper = styled.div`\n margin: 8px 0 8px;\n`\n\nconst MaskedInput = styled(Cleave)`\n width: 100%;\n padding: 18px;\n font-size: inherit;\n border: 1px solid\n ${({ theme, error }) =>\n error ? theme?.['-ds-error-300']?.value : theme.colors.textGreyLight};\n`\n\nconst renderMaskedDateInput = ({\n input,\n meta: { error, submitFailed },\n ...custom\n}) => {\n const value = input.value || ''\n\n return (\n \n \n \n )\n}\n\nexport default renderMaskedDateInput\n","import React from 'react'\nimport styled, { css } from 'styled-components'\nimport { Field } from 'redux-form'\nimport padStart from 'lodash/padStart'\nimport ChevronDown from '../icons/ChevronDown'\n\nimport AccommodationIcon from '../icons/Cabin'\nimport ExperiencesIcon from '../icons/Experiences'\nimport EquipmentIcon from '../icons/Equipment'\nimport VehicleIcon from '../icons/Kombi'\nimport StoriesIcon from '../icons/Stories'\n\nimport ValidIcon from '../icons/Valid'\nimport InfoIcon from '../icons/Info'\nimport WarningIcon from '../icons/Warning'\n\nimport Button from '../display/Button'\nimport DropdownField from './DropdownField'\n\nexport const isRequired = (value: unknown) =>\n value ? undefined : 'This field is required'\nexport { default as renderMaskedDateInput } from './MaskedDateInput'\n\nexport const mapSlugToIcon = {\n accommodation: AccommodationIcon,\n experiences: ExperiencesIcon,\n equipment: EquipmentIcon,\n motorVehicle: VehicleIcon,\n stories: StoriesIcon,\n}\n\nexport const RadioWrapper = styled.label`\n display: flex;\n align-items: center;\n margin: 16px 0;\n font-weight: 300;\n color: ${({ theme }) => theme.colors.carbon};\n\n input[type='radio'] {\n margin: 0;\n margin-right: 16px;\n }\n`\n\nexport const RadioWrapperCapitalized = styled(RadioWrapper)`\n text-transform: capitalize;\n`\n\nexport const Recommended = styled.span`\n font-size: 14px;\n font-weight: 400;\n text-transform: uppercase;\n color: ${({ theme }) => theme.colors.carbon};\n margin-left: 8px;\n`\n\nexport const TextFieldWrapper = styled.div`\n position: relative;\n width: 100%;\n flex: 1;\n\n svg {\n position: absolute;\n\n top: 50%;\n width: 20px;\n\n height: 20px;\n right: 20px;\n\n color: #9b9b9b;\n\n transform: translateY(-50%);\n }\n`\n\ntype TextProps = {\n textTransform?: string\n}\n\ntype FontWeightProps = {\n fontWeight?: number\n}\n\ntype HintWrapperProps = TextProps &\n FontWeightProps & {\n noLeftPadding?: boolean\n }\n\nexport const HintWrapper = styled.div`\n padding-left: ${({ noLeftPadding }) => (noLeftPadding ? '0' : '30px')};\n color: ${({ theme }) => theme?.['-ds-neutral-500']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n font-weight: 400;\n line-height: 1.4;\n\n svg {\n width: 20px;\n margin-left: -30px;\n margin-right: 6px;\n margin-bottom: -4px;\n display: inline-block;\n float: left;\n }\n\n a {\n text-decoration: underline;\n color: ${({ theme }) => theme.brand.jungle};\n }\n\n text-transform: ${({ textTransform }) => textTransform || 'inherit'};\n\n ${({ fontWeight }) =>\n fontWeight &&\n `\n font-weight: ${fontWeight};\n `}\n`\n\nexport const ListingTypeGroup = styled.div<{ homeSearch?: boolean }>`\n display: flex;\n\n ${({ homeSearch }) =>\n !homeSearch &&\n `\n margin: 0 -8px;\n flex-wrap: wrap;\n `}\n`\n\nexport const ListingType = styled.div<{ homeSearch?: boolean }>`\n cursor: pointer;\n\n ${({ homeSearch }) =>\n homeSearch &&\n `\n flex: 1;\n margin-left: -1px;\n\n &:first-child {\n margin-left: 0;\n }\n `}\n\n ${({ homeSearch }) =>\n !homeSearch &&\n `\n padding: 0 8px;\n margin-bottom: 8px;\n `}\n`\n\ntype HintProps = {\n className?: string\n style?: React.CSSProperties\n omitIcon?: boolean\n}\n\nexport const Hint: React.FC = ({\n className = '',\n children,\n omitIcon,\n ...custom\n}) => (\n \n {!omitIcon && } {children}\n \n)\n\nconst WarningWrapper = styled(HintWrapper)`\n color: ${({ theme }) => theme.colors.orange};\n`\n\nexport const Warning: React.FC<{ className?: string }> = ({\n className,\n children,\n}) => (\n \n {children}\n \n)\n\ntype MarginProps = {\n noMargin?: boolean\n lessMargin?: boolean\n smallMargin?: boolean\n}\n\nexport const InputGroup = styled.div.withConfig({\n shouldForwardProp: (prop) => {\n const shouldForward =\n ['noMargin', 'lessMargin', 'smallMargin', 'width'].includes(prop) !== true\n\n return shouldForward\n },\n})`\n position: relative;\n width: 100%;\n max-width: ${({ width }) => width || '100%'};\n\n ${({ noMargin }) =>\n !noMargin &&\n `\n margin-bottom: 40px;\n\n @media (min-width: 768px) {\n margin-bottom: ${({ lessMargin }: MarginProps) =>\n lessMargin ? '40px' : '80px'};\n }\n `}\n\n ${({ smallMargin }) =>\n smallMargin &&\n `\n margin-bottom: 20px;\n `}\n`\n\nexport const InlineInputGroup = styled.div<{\n noWrap?: boolean\n}>`\n display: flex;\n ${({ noWrap }) =>\n !noWrap &&\n `\n flex-wrap: wrap;\n `}\n\n margin: 0 -8px;\n\n &:last-child {\n margin-bottom: 0;\n }\n`\n\nexport const InputFlexWrapper = styled.div`\n width: 100%;\n display: flex;\n\n .inline-button {\n margin: 8px 0;\n margin-left: 15px;\n }\n input {\n flex: 1;\n }\n`\n\nexport const InlineInputGroupWrapper = styled.div<{ lessMargin?: boolean }>`\n margin-bottom: 20px;\n @media (min-width: 768px) {\n margin-bottom: ${({ lessMargin }) => (lessMargin ? '20px' : '40px')};\n }\n`\n\nexport const InlineInput = styled.div<{\n width?: string\n noFlex?: boolean\n $margin?: string\n}>`\n flex: ${({ width, noFlex }) => (width || noFlex ? 'none' : '1')};\n width: ${({ width }) => (width ? '100%' : 'auto')};\n max-width: ${({ width }) => width || '100%'};\n margin: ${({ $margin = '0 8px' }) => $margin};\n`\n\ntype LabelProps = {\n for?: string\n fontSize?: string\n forestColor?: boolean\n error?: boolean\n moreMargin?: boolean\n liteLabel?: boolean\n mediumLabel?: boolean\n bigLabel?: boolean\n checkList?: boolean\n}\n\nexport const Label = styled.label`\n display: block;\n margin-bottom: 8px;\n font-size: ${({ fontSize, theme }) =>\n fontSize || theme?.['-ds-font-size-sm']?.['font-size']?.value};\n font-weight: 400;\n color: ${({ theme, error, forestColor }) => {\n if (error) {\n return theme?.['-ds-error-300']?.value\n }\n if (forestColor) {\n return theme.brand.forest\n }\n\n return theme?.['-ds-neutral-700']?.value\n }};\n\n ${({ moreMargin }) =>\n moreMargin &&\n `\n margin-bottom: 16px;\n `}\n\n ${({ liteLabel }) =>\n liteLabel &&\n `\n font-weight: 300;\n `}\n\n ${({ mediumLabel }) =>\n mediumLabel &&\n `\n font-size: 16px;\n `}\n\n ${({ bigLabel }) =>\n bigLabel &&\n `\n color: black;\n font-size: 18px;\n line-height: 1.55;\n text-transform: none;\n `}\n\n ${({ checkList }) =>\n checkList &&\n `\n display: flex;\n align-items: baseline;\n color: #333;\n font-size: 16px;\n font-weight: 300;\n letter-spacing: 0.25px;\n text-transform: none;\n\n input[type='checkbox'] {\n margin-right: 8px !important;\n }\n `}\n\n`\n\nexport const LabelMd = styled(Label)`\n font-size: 16px;\n`\n\nexport const LabelLite = styled(Label)`\n font-weight: 300;\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n`\n\nexport const RadioButtonGroup = styled.div`\n margin-bottom: 16px;\n`\n\nexport const RadioLabel = styled.label`\n display: block;\n padding-top: 8px;\n font-weight: normal;\n color: #999;\n\n span {\n margin-left: 10px;\n }\n`\n\nexport const BigLabel = styled.label<{ error?: boolean }>`\n margin-bottom: 14px;\n font-size: 20px;\n font-weight: bold;\n\n color: ${({ error, theme }) =>\n error ? theme?.['-ds-error-300']?.value : 'black'};\n`\n\nexport const InlineLabel = styled.div`\n padding: 18px 0 18px 0;\n margin: 8px 0 8px;\n text-transform: uppercase;\n white-space: nowrap;\n`\n\nexport const ErrorLabel = styled.label`\n color: ${({ theme }) => theme?.['-ds-error-300']?.value};\n font-weight: normal;\n font-size: 12px;\n margin-bottom: 5px;\n`\n\nexport const InputGroupError = styled.div`\n position: relative;\n color: ${({ theme }) => theme?.['-ds-error-300']?.value};\n font-weight: normal;\n font-size: 12px;\n\n top: -40px;\n\n @media (min-width: 768px) {\n top: -80px;\n }\n`\n\nconst sharedInputStyles = css<{ readOnly?: boolean; disabled?: boolean }>`\n width: 100%;\n outline: 0;\n color: ${({ theme, readOnly, disabled }) =>\n readOnly || disabled ? theme.colors.labelGrey : 'black'};\n text-overflow: ellipsis;\n`\n\nconst sharedFieldStyles = css<{\n error?: boolean\n success?: boolean\n rounded?: boolean\n}>`\n padding: 18px;\n margin: 8px 0 8px;\n border: 1px solid\n ${({ theme, error, success }) => {\n if (error) {\n return theme?.['-ds-error-300']?.value\n }\n if (success) {\n return theme?.['-ds-core-400']?.value\n }\n return theme.colors.textGreyLight\n }};\n\n &:focus,\n &:focus-within {\n border-color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n }\n\n ${({ rounded = true }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n`\n\ntype TextFieldProps = {\n rounded?: boolean\n $white?: boolean\n}\n\nexport const TextField = styled.input.attrs(\n ({ type, rounded = true, $white }) => ({\n type: type || 'text',\n $white,\n rounded,\n })\n)`\n ${sharedInputStyles}\n ${sharedFieldStyles}\n input {\n width: 100%;\n height: 100%;\n }\n\n ${({ $white, theme }) =>\n $white && `background-color: ${theme?.['-ds-neutral-100']?.value}`}\n`\n\nexport const CurrencyFieldInput = styled.input`\n ${sharedInputStyles}\n border: 0;\n font-weight: 300;\n\n &::-webkit-inner-spin-button,\n &::-webkit-outer-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n`\n\nconst CurrencyFieldLabel = styled.label<{\n readOnly?: boolean\n disabled?: boolean\n error?: boolean\n success?: boolean\n rounded?: boolean\n}>`\n display: flex;\n align-items: center;\n font-weight: 300;\n color: ${({ theme, readOnly, disabled }) =>\n readOnly || disabled ? theme.colors.labelGrey : 'black'};\n ${sharedFieldStyles}\n`\n\nexport const CurrencyField = ({\n symbol = '$',\n style = undefined,\n rounded = true,\n ...props\n}) => {\n const { error, success } = props\n return (\n \n {symbol}\n \n \n )\n}\n\nexport const renderTextField = ({\n id,\n input,\n label,\n hint,\n meta: { error, submitFailed },\n lessMargin,\n noMargin,\n optional,\n ...custom\n}: any) => (\n \n \n \n {error && submitFailed && (\n {error}\n )}\n {hint && {hint}}\n \n)\n\nexport const renderError = ({ input, meta: { error, submitFailed } }: any) =>\n error && submitFailed ? (\n {error}\n ) : null\n\nexport const renderInlineTextField = ({\n id,\n input,\n label,\n meta: { error, submitFailed },\n ...custom\n}: any) => (\n \n \n \n {error && submitFailed && (\n {error}\n )}\n \n)\n\nexport const renderTextInput = ({\n input,\n meta: { error, submitFailed },\n showAsValid,\n ...custom\n}: any) => (\n \n \n {showAsValid && }\n \n)\n\nexport const renderNumberOptions = (length = 10) =>\n [...Array(length)].map((e, i) => (\n /* eslint-disable react/no-array-index-key */\n \n /* eslint-enable react/no-array-index-key */\n ))\n\nexport const renderTimeOptions = () =>\n [...Array(24)].map((e, i) => {\n const timeLabel = `${i}:00`\n const timeValue = `${padStart(i.toString(), 2, '0')}:00`\n /* eslint-disable react/no-array-index-key */\n return (\n \n )\n /* eslint-enable react/no-array-index-key */\n })\n\nexport const renderCheckboxInput = ({\n input,\n label,\n liteLabel = false,\n hint,\n bigLabel,\n disabled,\n checkList,\n ...custom\n}: any) => {\n const LabelComp = liteLabel ? LabelLite : Label\n return (\n \n \n {/* eslint-disable-next-line @typescript-eslint/no-use-before-define */}\n {' '}\n {label}\n {/* eslint-disable-next-line @typescript-eslint/no-use-before-define */}\n {custom?.optional && }\n \n {hint && {hint}}\n \n )\n}\n\nexport const RadioGroup = styled.div`\n label {\n font-weight: normal;\n margin-right: 16px;\n margin-bottom: 16px;\n\n span {\n margin-left: 12px;\n }\n }\n`\n\nexport const CheckboxGroupWrapper = styled.div`\n padding-top: 4px;\n label {\n font-weight: normal;\n margin-right: 16px;\n margin-bottom: 16px;\n\n span {\n margin-left: 12px;\n }\n }\n`\n\nconst CustomRadio = styled.div<{ checked?: boolean; homeSearch?: boolean }>`\n position: relative;\n\n height: 124px;\n width: 124px;\n\n padding: 16px;\n\n font-size: 12px;\n font-weight: normal;\n text-align: center;\n\n color: ${({ checked }) => (checked ? 'white' : '#333')};\n\n background-color: white;\n\n border: 1px solid ${({ theme }) => theme.colors.textGreyLight};\n\n svg {\n display: inline-block;\n width: 56px;\n margin-bottom: 16px;\n }\n\n ${({ homeSearch, theme }) =>\n homeSearch &&\n `\n flex: 1;\n height: auto;\n width: auto;\n padding: 16px 8px;\n\n color: ${theme.brand.forest};\n background-color: white;\n border: 1px solid ${theme.brand.jungle};\n\n svg {\n width: 42px;\n margin-bottom: 10px;\n }\n `}\n\n ${({ checked, theme }) =>\n checked &&\n `\n color: white;\n background-color: ${theme.brand.jungle};\n `}\n`\n\nexport const HomeSearchRadio = styled.div<{\n checked?: boolean\n homeSearch?: boolean\n}>`\n position: relative;\n\n height: 124px;\n width: 124px;\n\n padding: 16px;\n\n font-size: 12px;\n font-weight: normal;\n text-align: center;\n\n color: ${({ checked }) => (checked ? 'white' : '#999')};\n\n background-color: white;\n\n border: 1px solid ${({ theme }) => theme.colors.textGreyLight};\n\n svg {\n display: inline-block;\n width: 56px;\n margin-bottom: 16px;\n }\n\n ${({ theme }) => `\n flex: 1;\n height: auto;\n width: auto;\n padding: 16px 8px;\n\n color: ${theme.brand.forest};\n background-color: white;\n border: 1px solid ${theme.brand.jungle};\n border-right: 0;\n\n svg {\n width: 42px;\n margin-bottom: 10px;\n }\n `}\n\n ${({ checked, theme }) =>\n checked &&\n `\n color: white;\n background-color: ${theme.brand.jungle};\n `}\n`\n\nexport const renderHomeSearchRadio = ({\n input,\n label,\n id,\n data,\n customIcon,\n readOnly,\n homeSearch,\n}: any) => {\n const icon = customIcon || mapSlugToIcon[id as keyof typeof mapSlugToIcon]\n return (\n input.onChange(data)}\n homeSearch={homeSearch}\n >\n {icon && icon()}
\n {label}
\n \n )\n}\n\nexport const renderIconRadio = ({\n input,\n label,\n id,\n data,\n customIcon,\n readOnly,\n homeSearch,\n}: any) => {\n const icon = customIcon || mapSlugToIcon[id as keyof typeof mapSlugToIcon]\n return (\n input.onChange(data)}\n homeSearch={homeSearch}\n >\n {icon && icon()}
\n {label}
\n \n )\n}\n\nconst Select = styled.select.withConfig({\n shouldForwardProp: (prop) => {\n const shouldForward =\n [\n 'rounded',\n 'error',\n 'readOnly',\n 'white',\n 'isPlaceholder',\n 'grey',\n ].includes(prop) !== true\n\n return shouldForward\n },\n})``\n\nexport const SelectField = styled.div.attrs<{ rounded?: boolean }>(\n ({ rounded = true }) => ({\n rounded,\n })\n)<{\n rounded?: boolean\n error?: boolean\n readOnly?: boolean\n white?: boolean\n disabled?: boolean\n isPlaceholder?: boolean\n grey?: boolean\n}>`\n position: relative;\n width: 100%;\n padding: 16px;\n margin: 8px 0 8px;\n border: 1px solid\n ${({ theme, error }) =>\n error ? theme?.['-ds-error-300']?.value : theme.colors.textGreyLight};\n\n background-color: ${({ white }) => (white ? 'white' : 'transparent')};\n\n &:focus {\n border-color: ${({ theme }) => theme.brand.jungle};\n }\n\n color: ${({ theme, readOnly, disabled }) =>\n readOnly || disabled ? theme.colors.labelGrey : 'black'};\n\n ${({ grey }) =>\n grey &&\n `\n color: #757575;\n `};\n\n ${({ isPlaceholder }) =>\n isPlaceholder &&\n `\n color: #757575;\n `};\n\n ${({ rounded = true }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n select {\n position: absolute;\n width: 100%;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n padding: 0 18px;\n padding-right: 48px;\n\n appearance: none;\n overflow: hidden;\n background: transparent;\n color: currentColor;\n border: 0;\n outline: 0;\n height: 100%;\n }\n\n span {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n pointer-events: none;\n top: 0;\n right: 0;\n\n height: 100%;\n padding: 0 18px;\n }\n\n svg {\n width: 13px;\n height: 6px;\n }\n`\n\nexport const renderDropdownField = (\n props: React.ComponentProps\n) => \n\nexport const renderSelectField = ({\n id,\n input,\n meta: { error, submitFailed },\n children,\n white,\n ...custom\n}: any) => (\n \n \n \n \n \n \n \n)\n\nexport const CheckboxGroup: React.FC = ({\n name,\n label,\n hint,\n fields,\n children,\n}) => (\n \n \n \n {fields &&\n fields.map((field: any) => (\n \n ))}\n \n {children}\n {hint && {hint}}\n \n)\n\nexport const Submit = styled(Button)`\n display: block;\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-sm']?.['font-size']?.value};\n`\n\nexport const Checkbox = styled.input.attrs({ type: 'checkbox' })`\n input[type='checkbox']& {\n margin-right: 8px;\n }\n`\n\ntype CheckboxToggleProps = {\n id: string\n name: string\n onChange: React.ChangeEventHandler\n isChecked?: boolean\n disabled?: boolean\n style?: React.CSSProperties\n ['aria-label']?: string\n}\n\nexport const CheckboxToggle: React.FC = React.memo(\n ({\n id,\n name,\n onChange,\n isChecked,\n disabled,\n style,\n 'aria-label': ariaLabel,\n }) => (\n \n \n \n
\n )\n)\n\nexport const ToggleInput = ({\n input,\n label,\n hint,\n bigLabel,\n ...custom\n}: any) => (\n \n \n {hint && {hint}}\n \n)\n\nconst OptionalTagWrapper = styled.span`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n color: ${({ theme }) => theme?.['-ds-neutral-500'].value};\n text-transform: capitalize;\n\n > span {\n margin: 0 0.5em;\n }\n`\n\nexport const OptionalTag = ({ children = 'optional' }) => (\n \n –\n {children}\n \n)\n","import moment from 'moment'\nimport * as Yup from 'yup'\nimport { isValidNumber } from 'libphonenumber-js'\n\nexport const validRequired = (value) =>\n !value ? 'This field is required' : undefined\n\nexport const validNumber = (value) =>\n value < 0 || value === undefined ? 'This field is required' : undefined\n\nexport const validTime = (value) => {\n const formats = [\n 'h:m',\n 'h:ma',\n 'h:m A',\n 'h:m a',\n 'h:m A',\n 'h:mm',\n 'h:mma',\n 'h:mmA',\n 'h:mm a',\n 'h:mm A',\n 'hh:m',\n 'hh:ma',\n 'hh:mA',\n 'hh:m a',\n 'hh:m A',\n 'H:m',\n 'H:ma',\n 'H:m A',\n 'H:m a',\n 'H:m A',\n 'H:mm',\n 'H:mma',\n 'H:mmA',\n 'H:mm a',\n 'H:mm A',\n 'HH:m',\n 'HH:ma',\n 'HH:mA',\n 'HH:m a',\n 'HH:m A',\n ]\n\n if (!moment(value, formats, true).isValid()) {\n return 'Not a valid time'\n }\n\n return undefined\n}\n\nexport const validDateOfBirth = (value) => {\n // Do not assume the year with only 2-digits.\n moment.parseTwoDigitYear = (yearString) => parseInt(yearString, 10)\n\n const birthday = moment(value, 'DD/MM/YYYY')\n const age = moment().diff(birthday, 'years')\n\n if (birthday.year() < 1900) {\n return 'Not a valid date'\n }\n\n if (age < 18) {\n return 'You need to be at least 18 years of age'\n }\n\n return undefined\n}\n\nexport const validEmail = (value) => {\n const schema = Yup.string().email()\n return schema.isValidSync(value) ? undefined : 'Not a valid email'\n}\n\nexport const validPassword = (_value, values) => {\n if (values.user.password && values.user.password.length < 8) {\n return 'Password should be at least 8+ characters'\n }\n\n if (values.user.password !== values.user.password_confirmation) {\n return 'Password confirmation should match password'\n }\n\n return undefined\n}\n\nexport const validURL = (value) => {\n const schema = Yup.string().url()\n return value && (schema.isValidSync(value) ? undefined : 'Not a valid URL')\n}\n\nexport const validVerifiedPhoneNumber = (value) =>\n !value ? 'You need to verify this number' : undefined\n\n/**\n * value can be either:\n * - a JSON upload result from uppy\n * - an image object from our API (included in form's initial values)\n */\nexport const validImage = (value) => {\n const errorMsg = 'Please upload an image'\n\n // handle when value is an image object form our API\n if (typeof value === 'object') {\n const objValues = Object.values(value)\n const nonEmptyFields = objValues.filter((v) => v?.length > 0)\n\n return nonEmptyFields.length > 0 ? undefined : errorMsg\n }\n\n /**\n * handle when value is a new upload result from uppy\n */\n try {\n JSON.parse(value)\n } catch (error) {\n return errorMsg\n }\n\n return undefined\n}\n\nexport const normalizeBoolean = (value) => {\n if (value === 'true') {\n return true\n }\n\n if (value === 'false') {\n return false\n }\n\n return value\n}\n\nexport const validBoolean = (value) =>\n typeof value !== 'boolean' ? 'This field is required' : undefined\n\nexport const validCheckboxGroup = (values) =>\n values && values.filter((k) => !!k).length < 1\n ? 'Please select at least one'\n : undefined\n\nexport const validArrayOfMinimumOneImage = (value) =>\n value && value.length < 1 ? 'Please upload at least one image' : undefined\n\nexport const validPhoneNumber = (value) => {\n if (value && !isValidNumber(value)) {\n return 'Not a valid phone number'\n }\n\n return undefined\n}\n","import React from 'react'\nimport { Controller, RegisterOptions, useFormContext } from 'react-hook-form'\n\nimport { formatPrice, unformat } from '../utils/pricing'\n\nimport StyledInput from './StyledInput'\nimport ErrorMessage from './ErrorMessage'\nimport { Label } from './Field'\n\ntype CurrencyFieldProps = {\n name: string\n label?: string\n precision?: 0 | 2\n placeholder?: string\n validationRules?: RegisterOptions\n formatValue?: (value: number, precision?: number) => string\n skipErrorMessage?: boolean\n 'aria-label'?: string\n onClick?: () => any\n setInputRef?: (e: HTMLInputElement) => any\n}\n\nconst CurrencyField = ({\n name,\n label,\n precision = 0,\n placeholder = '$',\n validationRules,\n formatValue = formatPrice,\n skipErrorMessage = false,\n 'aria-label': ariaLabel,\n onClick,\n setInputRef,\n}: CurrencyFieldProps) => {\n const { control } = useFormContext()\n\n return (\n {\n const handleChange = (e: React.ChangeEvent) => {\n const nextValue = unformat(e.target.value)\n return onChange(nextValue)\n }\n\n const formattedValue = formatValue(value, precision) || ''\n\n return (\n <>\n {\n ref(e)\n if (setInputRef) {\n setInputRef(e)\n }\n }}\n onClick={onClick}\n />\n {label && }\n {!skipErrorMessage && }\n >\n )\n }}\n />\n )\n}\n\nexport default CurrencyField\n","import React from 'react'\nimport styled from 'styled-components'\nimport { useFormContext } from 'react-hook-form'\nimport get from 'lodash/get'\n\nexport const ErrorLabel = styled.small`\n display: block;\n color: ${({ theme }) => theme?.['-ds-error-300']?.value};\n font-weight: normal;\n font-size: 12px;\n margin-bottom: 16px;\n margin-right: 16px;\n`\n\nconst ErrorMessage: React.FC<{ name: string }> = ({ name }) => {\n const {\n formState: { errors },\n } = useFormContext()\n const error = get(errors, name)\n if (!error) return null\n\n return {error.message}\n}\n\nexport default ErrorMessage\n","import React from 'react'\nimport styled from 'styled-components'\nimport { useFormContext } from 'react-hook-form'\nimport get from 'lodash/get'\nimport ErrorMessage from './ErrorMessage'\n\nconst FieldWrapper = styled.div`\n margin-bottom: 16px;\n`\n\nconst MessagesAndAnnotations = styled.div`\n display: flex;\n align-items: baseline;\n`\n\nexport const Label = styled.label<{ error?: boolean }>`\n display: block;\n line-height: 1;\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-sm']?.['font-size']?.value};\n font-weight: 400;\n margin-bottom: 8px;\n`\n\nexport type FieldProps = {\n name: string\n label?: React.ReactNode\n autocomplete?: boolean\n annotations?: React.ReactNode\n style?: React.CSSProperties\n}\n\nconst Field: React.FC = ({\n name,\n label,\n annotations,\n children,\n}) => {\n const {\n formState: { errors },\n } = useFormContext()\n const error = get(errors, name)\n return (\n \n {label && (\n \n )}\n {children}\n \n \n {annotations}
\n \n \n )\n}\n\nexport default Field\n","import React, { FormEvent } from 'react'\nimport styled from 'styled-components'\nimport { useFormContext, RegisterOptions } from 'react-hook-form'\nimport get from 'lodash/get'\n\nimport ChevronDown from 'components/icons/ChevronDown'\n\nimport FieldWrapper, { FieldProps } from './Field'\n\nexport const SelectFieldWrapper = styled.div<{\n error?: boolean\n isPlaceholder?: boolean\n rounded?: boolean\n}>`\n display: inline-block;\n position: relative;\n width: 100%;\n height: 60px;\n margin-top: 8px;\n\n background-color: transparent;\n\n ${({ isPlaceholder }) =>\n isPlaceholder &&\n `\n color: #757575;\n`};\n\n select {\n position: absolute;\n width: 100%;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n padding: 0 18px;\n padding-right: 48px;\n\n appearance: none;\n overflow: hidden;\n background: transparent;\n color: currentColor;\n border: 0;\n outline: 0;\n height: 100%;\n\n border: 1px solid\n ${({ theme, error }) =>\n error ? theme?.['-ds-error-300']?.value : theme.colors.textGreyLight};\n\n ${({ rounded }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n\n &:focus {\n border-color: ${({ theme }) => theme.brand.jungle};\n }\n }\n\n span {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n pointer-events: none;\n top: 0;\n right: 0;\n\n height: 100%;\n padding: 0 18px;\n }\n\n svg {\n width: 13px;\n height: 6px;\n }\n`\n\ntype Props = FieldProps & {\n placeholder?: string\n rounded?: boolean\n onChange?: (e: FormEvent) => any\n /**\n * Options to pass to the react-hook-form register function\n */\n registerOptions?: RegisterOptions\n}\n\nconst SelectField: React.FC = ({\n name,\n label,\n placeholder,\n rounded = true,\n children,\n registerOptions,\n ...props\n}) => {\n const {\n watch,\n formState: { errors },\n register,\n } = useFormContext()\n const error = get(errors, name)\n const value = watch(name)\n\n return (\n \n \n \n \n \n \n \n \n )\n}\n\nexport default SelectField\n","import styled from 'styled-components'\n\nexport default styled.input<{\n error?: boolean\n rounded?: boolean\n}>`\n width: 100%;\n padding: 18px;\n margin: 8px 0 8px;\n outline: 0;\n text-overflow: ellipsis;\n border: 1px solid\n ${({ theme, error }) =>\n error ? theme?.['-ds-error-300']?.value : theme.colors.textGreyLight};\n\n &:focus {\n border-color: ${({ theme }) => theme.brand.jungle};\n }\n\n ${({ rounded = true }) =>\n rounded &&\n `\n border-radius: 6px;\n `}\n`\n","import React from 'react'\nimport { useFormContext, RegisterOptions } from 'react-hook-form'\nimport get from 'lodash/get'\nimport StyledInput from './StyledInput'\n\nimport FieldWrapper, { FieldProps } from './Field'\n\ntype Props = FieldProps & {\n type?: string\n rounded?: boolean\n readOnly?: boolean\n\n /**\n * Options to pass to the react-hook-form register function\n */\n registerOptions?: RegisterOptions\n\n /**\n * Placeholder\n */\n placeholder?: string\n}\n\nconst TextField: React.FC = ({\n type = 'text',\n name,\n label,\n placeholder = '',\n autocomplete,\n rounded = true,\n readOnly,\n registerOptions,\n style,\n}) => {\n const {\n formState: { errors },\n register,\n } = useFormContext()\n const error = get(errors, name)\n\n return (\n \n \n \n )\n}\n\nexport default TextField\n","import React from 'react'\nimport styled from 'styled-components'\nimport { Controller, RegisterOptions, useFormContext } from 'react-hook-form'\n\nimport { Textarea } from '../form/Textarea'\n\nimport FieldWrapper from './Field'\n\nconst MaxLength = styled.span<{ error?: boolean }>`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n color: ${({ theme, error }) =>\n error\n ? theme?.['-ds-error-300']?.value\n : theme?.['-ds-neutral-500']?.value};\n`\n\ntype Props = {\n name: string\n label?: React.ReactNode\n placeholder?: string\n\n /**\n * Options to pass to the react-hook-form register function\n */\n validationRules?: RegisterOptions\n formatValue?: (value: string) => string\n rounded?: boolean\n showLength?: boolean\n noResize?: boolean\n}\n\nconst TextareaField = ({\n name,\n label,\n placeholder = '',\n validationRules,\n formatValue,\n rounded = true,\n showLength,\n noResize,\n}: Props) => {\n const { control } = useFormContext()\n\n return (\n {\n const handleChange = (e: React.ChangeEvent) => {\n if (formatValue != null) {\n const nextValue = formatValue(e.target.value)\n return onChange(nextValue)\n }\n\n return onChange(e.target.value)\n }\n\n const messageLength = field?.value?.length || 0\n\n const maxLength =\n // @ts-ignore -- types don't reflect that maxLength could be a number or an object of shape { value: number, message: string }\n validationRules?.maxLength?.value || validationRules?.maxLength\n\n return (\n <>\n \n {messageLength}\n {maxLength && <>/{maxLength}>}\n \n )\n }\n >\n \n \n >\n )\n }}\n />\n )\n}\n\nexport default TextareaField\n","import React from 'react'\n\nconst AirbnbClose = () => (\n \n)\n\nexport default AirbnbClose\n","import React from 'react'\n\nconst ArrowLeft = () => (\n \n)\n\nexport default ArrowLeft\n","import React from 'react'\n\nconst ArrowRight = (props) => (\n \n)\n\nexport default ArrowRight\n","import React from 'react'\n\nconst ArrowRightSlim = () => {\n return (\n \n )\n}\n\nexport default ArrowRightSlim\n","import React from 'react'\n\nconst SvgIconBucketlistHeartOff = (props) => (\n \n)\n\nexport default SvgIconBucketlistHeartOff\n","import React from 'react'\n\nconst SvgIconBucketlistHeartOn = (props) => (\n \n)\n\nexport default SvgIconBucketlistHeartOn\n","import React from 'react'\n\nconst SvgIconCabin = (props) => (\n \n)\n\nexport default SvgIconCabin\n","import React from 'react'\n\nconst CalendarBookingDetailed = () => {\n return (\n \n )\n}\n\nexport default CalendarBookingDetailed\n","import React from 'react'\n\nconst SvgIconCaretDownFilled = (props) => (\n \n)\n\nexport default SvgIconCaretDownFilled\n","import React from 'react'\n\nconst SvgIconCaretUpFilled = (props) => (\n \n)\n\nexport default SvgIconCaretUpFilled\n","import React from 'react'\n\nconst SvgIconCheck = (props) => (\n \n)\n\nexport default SvgIconCheck\n","import React from 'react'\n\nconst SvgIconCheckCircle = (props) => (\n \n)\n\nexport default SvgIconCheckCircle\n","import React from 'react'\n\nconst SvgIconCheveronRight = (props) => (\n \n)\n\nexport default SvgIconCheveronRight\n","import React from 'react'\n\nconst ChevronDown = (props) => (\n \n)\n\nexport default ChevronDown\n","import React from 'react'\n\nconst SvgIconChevronDown2 = (props) => (\n \n)\n\nexport default SvgIconChevronDown2\n","import React from 'react'\n\nconst SvgIconClock = (props) => (\n \n)\n\nexport default SvgIconClock\n","import React from 'react'\n\nconst CommunityMinded = (props: React.SVGProps) => {\n return (\n \n )\n}\n\nexport default CommunityMinded\n","import React from 'react'\n\nconst SvgIconCopy = (props) => (\n \n)\n\nexport default SvgIconCopy\n","import React from 'react'\n\nconst CrossOut = () => (\n \n)\n\nexport default CrossOut\n","import React from 'react'\n\nconst SvgIconFilters = (props) => (\n \n)\n\nexport default SvgIconFilters\n","import React from 'react'\n\nconst SvgIconGiftDetailed = ({ color = 'black', ...props }) => (\n /*\n * Copied directly from svg file, bypassing `npm run icons:generate` script -- it reduced the number of paths tags\n * but failed to maintain the correct colour fill (on the dollar sign part of the gift icon).\n */\n \n)\n\nexport default SvgIconGiftDetailed\n","import React from 'react'\n\nconst SvgIconHappy = (props) => (\n \n)\n\nexport default SvgIconHappy\n","import React from 'react'\n\nconst SvgIconHollowPin = (props) => (\n \n)\n\nexport default SvgIconHollowPin\n","import React from 'react'\n\nconst SvgIconIndifferent = (props) => (\n \n)\n\nexport default SvgIconIndifferent\n","import React from 'react'\n\nconst Info = () => (\n \n)\n\nexport default Info\n","import React from 'react'\n\nconst SvgIconInfoOutline = (props) => (\n \n)\n\nexport default SvgIconInfoOutline\n","import React from 'react'\n\nconst LocationPin = () => (\n \n)\n\nexport default LocationPin\n","import React from 'react'\n\nconst SvgIconMail = (props) => (\n \n)\n\nexport default SvgIconMail\n","import React from 'react'\n\nconst RiparideSmallLogo = (props) => (\n \n)\n\nexport default RiparideSmallLogo\n","import React from 'react'\n\nconst SvgIconStories = (props) => (\n \n)\n\nexport default SvgIconStories\n","import React from 'react'\n\nconst SvgIconUnhappy = (props) => (\n \n)\n\nexport default SvgIconUnhappy\n","import React from 'react'\n\nconst Valid = (props) => (\n \n)\n\nexport default Valid\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport { mediaMax } from 'styles/media'\n\ntype Options = {\n gutter?: number\n centered?: boolean\n firstGutter?: number\n}\n\nconst Inner = styled.div`\n display: flex;\n margin: 0 auto;\n\n ${({ centered, firstGutter }) =>\n centered === false &&\n `\n margin: 0 ${firstGutter || 0}px;\n `}\n\n ${mediaMax.xl`\n padding: 0 ${({ gutter }: Options) => gutter}px;\n `}\n\n & > * {\n margin-right: ${({ gutter }) => gutter}px;\n\n &:last-child {\n margin-right: 0;\n }\n }\n`\n\nconst Outer = styled.div`\n display: flex;\n\n ${mediaMax.xl`\n overflow-x: scroll;\n padding-bottom: 16px; /* accommodate horizontal scrollbar */\n `}\n`\n\ntype HorizontallyScrollableProps = Options\n\nconst HorizontallyScrollable: React.FC = ({\n gutter = 30,\n centered = true,\n firstGutter,\n children,\n}) => {\n return (\n \n \n {children}\n \n \n )\n}\n\nexport default HorizontallyScrollable\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport { media, mediaMax } from 'styles/media'\n\nconst Intro = styled.div<{ reducedMarginBottom?: boolean }>`\n text-align: center;\n max-width: 870px;\n\n margin-top: 80px;\n margin-bottom: ${({ reducedMarginBottom }) =>\n reducedMarginBottom ? '20px' : '40px'};\n\n ${mediaMax.md`\n text-align: left;\n `}\n\n ${media.md`\n margin-top: 180px;\n margin-bottom: 100px;\n margin-bottom: ${({\n reducedMarginBottom,\n }: {\n reducedMarginBottom?: boolean\n }) => (reducedMarginBottom ? '40px' : '100px')};\n `}\n\n & > * {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n h3 {\n font-size: ${({ theme }) => theme['-ds-font-size-md']['font-size'].value};\n font-weight: 200;\n line-height: 1.15;\n text-transform: uppercase;\n color: ${({ theme }) => theme.brand.jungle};\n margin-bottom: 20px;\n\n ${mediaMax.md`\n font-size: 16px;\n `}\n }\n\n h2 {\n font-size: ${({ theme }) => theme['-ds-font-size-xxl']['font-size'].value};\n font-weight: ${({ theme }) =>\n theme['-ds-font-size-xxl']['font-weight'].value};\n line-height: 1.1;\n color: ${({ theme }) => theme.brand.forest};\n margin-bottom: 16px;\n\n ${mediaMax.md`\n font-size: 32px;\n `}\n }\n\n p {\n font-size: ${({ theme }) => theme['-ds-font-size-lg']['font-size'].value};\n line-height: 1.7;\n font-weight: ${({ theme }) =>\n theme['-ds-font-size-lg']['font-weight'].value};\n color: ${({ theme }) => theme.colors.textGreyDarker};\n\n ${mediaMax.md`\n font-size: ${({ theme }) => theme['-ds-font-size-xs']['font-size'].value};\n `}\n }\n`\n\ntype SectionIntroProps = {\n primaryHeading: React.ReactNode\n secondaryHeading?: React.ReactNode\n paragraphText: React.ReactNode\n style?: React.CSSProperties\n reducedMarginBottom?: boolean\n}\n\nconst SectionIntro: React.FC = ({\n primaryHeading,\n secondaryHeading,\n paragraphText,\n style,\n reducedMarginBottom,\n}) => {\n return (\n \n {secondaryHeading && {secondaryHeading}
}\n {primaryHeading}
\n {paragraphText}
\n \n )\n}\n\nexport default SectionIntro\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport Theme from 'styles/theme'\nimport media from 'styles/media'\n\nimport Button from 'components/display/Button'\nimport ButtonLink from 'components/display/ButtonLink'\nimport LazyImage from 'components/display/LazyImage'\nimport UniformOverlay from 'components/display/Overlay/Uniform'\n\nconst Content = styled.div`\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n z-index: 2;\n padding: 30px;\n padding-top: 80px;\n\n ${media.md`\n padding: 80px 80px 40px 80px;\n `}\n\n ${media.xl`\n padding: 100px;\n width: 60%;\n `}\n\n & > * {\n max-width: 720px;\n }\n\n & > * + * {\n margin-bottom: 20px;\n }\n\n h1 {\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xl']?.['font-size']?.value};\n font-weight: ${({ theme }) =>\n theme?.['-ds-font-size-xl']?.['font-weight']?.value};\n line-height: 1.3;\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxxl']?.['font-size']?.value};\n font-weight: ${({ theme }) =>\n theme?.['-ds-font-size-xxxl']?.['font-weight']?.value};\n line-height: 1.2;\n `};\n }\n\n h2 {\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n font-weight: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-weight']?.value};\n line-height: 1.4;\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-lg']?.['font-size']?.value};\n font-weight: ${({ theme }) =>\n theme?.['-ds-font-size-lg']?.['font-weight']?.value};\n `}\n }\n\n ${Button}, ${ButtonLink}, a {\n margin-top: 50px;\n\n ${media.md`\n width: fit-content;\n `}\n }\n`\n\nconst HeaderInner = styled.div`\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: stretch;\n position: relative;\n width: 100%;\n max-width: 1920px;\n margin: 0 auto;\n\n color: white;\n\n ${media.xl`\n flex-direction: row;\n `}\n\n ${LazyImage} {\n position: absolute;\n object-position: bottom center;\n }\n\n h3 {\n z-index: 2;\n position: absolute;\n top: 20px;\n right: 20px;\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxl']?.['font-size']?.value};\n font-weight: ${({ theme }) =>\n theme?.['-ds-font-size-xxl']?.['font-weight']?.value};\n margin: 0;\n\n ${media.md`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxxl']?.['font-size']?.value};\n font-weight: ${({ theme }) =>\n theme?.['-ds-font-size-xxxl']?.['font-weight']?.value};\n `};\n }\n`\n\ntype HeaderProps = {\n h1Text?: React.ReactNode\n h2Text: React.ReactNode\n h3Text?: React.ReactNode\n cta?: React.ReactNode\n imageUrl?: string\n}\n\nconst SmallHeader: React.FC = ({\n h1Text,\n h2Text,\n h3Text,\n cta,\n imageUrl,\n}) => (\n \n \n \n {h3Text}
\n \n {h1Text}
\n {h2Text}
\n {cta}\n \n \n)\n\nexport default SmallHeader\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport { useMediaQueryContext } from 'contexts/MediaQueryContext'\nimport { media, mediaMax } from 'styles/media'\n\nimport Avatar from '../display/Avatar'\nimport LazyImage from '../display/LazyImage'\nimport LinkOrA from '../cards/shared/LinkOrA'\n\nimport HorizontallyScrollable from './HorizontallyScrollable'\n\nexport const Heading = styled.span`\n font-size: 20px;\n font-weight: 400;\n color: ${({ theme }) => theme.brand.jungle};\n\n ${media.md`\n font-size: 30px;\n `}\n`\n\nconst AffiliationWrapper = styled.div``\n\nconst AffiliationSpan = styled.span`\n font-weight: 400;\n color: ${({ theme }) => theme.colors.textGreyDarker};\n\n font-size: 18px;\n ${media.md`\n font-size: 20px;\n `}\n`\n\nconst CTAWrapper = styled.div``\n\nexport const Card = styled.div`\n min-width: 220px;\n max-width: 390px; /* to fit 3 in typical layout on desktop */\n\n ${mediaMax.phone`\n width: 66vw;\n `}\n\n flex-shrink: 0;\n\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n\n padding: 30px;\n border: 1px solid #dddddd;\n border-radius: 8px;\n\n ${Avatar} {\n margin-bottom: 16px;\n }\n\n ${Avatar} {\n height: 90px;\n width: 90px;\n flex-shrink: 0;\n\n ${media.md`\n height: 120px;\n width: 120px;\n `}\n }\n\n p {\n color: #000000;\n ${media.md`\n margin-bottom: 40px;\n `}\n }\n\n p,\n ${CTAWrapper} {\n font-size: 16px;\n line-height: 1.6;\n font-weight: 300;\n margin-top: 16px;\n\n ${media.md`\n font-size: 18px;\n `}\n }\n\n ${CTAWrapper} {\n margin-top: auto;\n a span {\n text-decoration: underline;\n }\n }\n`\n\ntype TestimonialData = {\n name: string\n avatar: Partial & { thumbMd: string }\n affiliation?: {\n text: string\n link?: string\n }\n text: React.ReactNode\n CTA?: React.ReactNode\n}\n\nconst Affiliation: React.FC<{\n text?: string\n link?: string\n}> = ({ text, link }) => {\n const { md: largerThanMd } = useMediaQueryContext()\n const isSmallerThanMd = !largerThanMd\n\n if (!text) {\n return null\n }\n\n if (link) {\n return (\n \n {text}\n \n )\n }\n\n return {text}\n}\n\ntype TestimonialsProps = {\n testimonials: TestimonialData[]\n}\n\nconst Testimonials: React.FC = ({\n testimonials: allTestimonials,\n}) => {\n const { md: largerThanMd } = useMediaQueryContext()\n const isSmallerThanMd = !largerThanMd\n\n const testimonials = isSmallerThanMd\n ? allTestimonials\n : allTestimonials.slice(0, 3)\n\n return (\n \n {testimonials.map(({ name, avatar, affiliation, text, CTA }) => {\n return (\n \n \n \n \n \n {name}\n {affiliation && (\n \n \n \n )}\n {text}
\n {CTA && {CTA}}\n \n )\n })}\n \n )\n}\n\nexport default Testimonials\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport { useMediaQueryContext } from 'contexts/MediaQueryContext'\nimport { media, mediaMax } from 'styles/media'\n\nimport ButtonLink from '../display/ButtonLink'\nimport BaseContainer from '../layout/Container'\nimport LinkOrA from '../cards/shared/LinkOrA'\n\nexport const Container = styled(BaseContainer)`\n margin: 60px auto;\n padding: 0 30px;\n\n & > * {\n margin-left: auto;\n margin-right: auto;\n }\n\n ${media.md`\n margin: 120px auto;\n `}\n`\n\nconst PageCTALinkOuter = styled.div<{ noMarginTop?: boolean }>`\n display: flex;\n flex-direction: column;\n align-items: center;\n\n margin: ${({ noMarginTop }) => (noMarginTop ? '0' : '60px')} 0 60px 0;\n\n ${media.md`\n margin: ${({ noMarginTop }: { noMarginTop?: boolean }) =>\n noMarginTop ? '0' : '100px'} 0 100px 0;\n `}\n\n & > *:not(:last-child) {\n margin-bottom: 30px;\n }\n`\n\nconst PageCTALinkInner = styled.div`\n display: flex;\n justify-content: center;\n\n & > * {\n font-size: 20px;\n }\n\n ${ButtonLink} {\n width: 100%;\n font-size: inherit;\n\n ${media.md`\n width: auto;\n `}\n }\n`\n\ntype PageCTALinkProps = {\n info?: React.ReactNode\n noMarginTop?: boolean\n} & React.ComponentProps\n\nexport const PageCTALink: React.FC = ({\n href,\n children,\n info,\n noMarginTop,\n ...props\n}) => {\n return (\n \n {info}\n \n \n {children}\n \n \n \n )\n}\n\nconst ComponentCTALinkInner = styled.span`\n color: ${({ theme }) => theme.brand.jungle};\n font-size: 16px;\n ${media.md`\n font-size: 18px;\n `}\n`\n\nexport const ComponentCTALink: React.FC<{ url: string }> = ({\n url,\n children,\n}) => {\n const { md: largerThanMd } = useMediaQueryContext()\n const isSmallerThanMd = !largerThanMd\n\n return (\n \n {children}\n \n )\n}\n\ntype ResTwoColProps = {\n columnMarginBottom?: number\n gutter?: number | string\n}\n\nexport const ResponsiveTwoColumnLayout = styled.div`\n display: flex;\n justify-content: center;\n\n ${mediaMax.md`\n flex-direction: column;\n `}\n\n & > * {\n width: 50%;\n display: flex;\n flex-direction: column;\n\n ${mediaMax.md`\n width: 100%;\n `}\n\n &:not(:last-child) {\n margin-bottom: ${({ columnMarginBottom = 20 }) =>\n `${columnMarginBottom}px`};\n }\n\n ${media.md`\n ${({ gutter }: ResTwoColProps) => {\n if (!gutter) {\n return ``\n }\n\n const value = typeof gutter === 'number' ? `${gutter}px` : gutter\n\n return `\n padding: 0 calc(${value}/2);\n `\n }}\n `}\n }\n`\n\nexport const SpacedColumn = styled.div`\n display: flex;\n flex-direction: column;\n align-items: center;\n\n & > *:not(:last-child) {\n margin-bottom: 40px;\n }\n`\n\nexport const ImageColumn = styled(SpacedColumn)`\n & > *:first-child {\n height: 90%;\n max-height: 780px;\n width: 100%;\n\n ${media.md`\n height: 100%;\n width: 85%;\n `}\n }\n`\n","import styled from 'styled-components'\n\nconst Container = styled.div<{\n noPadding?: boolean\n paddingY?: number\n width?: number\n overflowHidden?: boolean\n}>`\n box-sizing: border-box;\n width: 100%;\n max-width: ${({ width }) => (width ? `${width}px` : '1300px')};\n\n margin: 0 auto;\n padding: ${({ paddingY }) => (paddingY ? `${paddingY}px` : 0)} 16px;\n\n ${({ overflowHidden }) =>\n overflowHidden &&\n `\n overflow: hidden;\n`}\n\n ${({ noPadding }) =>\n noPadding &&\n `\n padding: 0;\n `}\n`\n\nContainer.defaultProps = {\n overflowHidden: true,\n}\n\nexport default Container\n","import styled from 'styled-components'\n\nimport { media, mediaMax } from 'styles/media'\n\nconst ITEM_SIDE_PADING_MOBILE = 16\nconst ITEM_SIDE_PADDING_DESKTOP = 14\n\ntype GridItemProps = {\n widthOverride?: {\n md?: string\n lg?: string\n xxxl?: string\n }\n}\n\nexport const defaultItemsPerBreakpoint = {\n md: 2,\n lg: 3,\n xxxl: 4,\n} as const\n\nexport const GridItem = styled.div.attrs({\n className: 'qa-grid-item',\n})`\n box-sizing: border-box;\n padding: 0 8px;\n padding: 0 ${ITEM_SIDE_PADING_MOBILE}px;\n\n ${media.md`\n padding: 0 ${ITEM_SIDE_PADDING_DESKTOP}px;\n `}\n\n width: 100%;\n\n /*\n Default widths by breakpoint; can be overridden in other contexts to suit specific use cases\n e.g. a grid that ocupies only part of a screen.\n */\n\n ${media.md`\n width: ${({ widthOverride }) =>\n widthOverride?.md || `${100 / defaultItemsPerBreakpoint.md}%`};\n `}\n\n ${media.lg`\n width: ${({ widthOverride }) =>\n widthOverride?.lg || `${100 / defaultItemsPerBreakpoint.lg}%`};\n `}\n\n ${media.xxxl`\n width: ${({ widthOverride }) =>\n widthOverride?.xxxl || `${100 / defaultItemsPerBreakpoint.xxxl}%`};\n `}\n`\n\ntype GridOptions = {\n mobileWidthOffset?: boolean\n}\n\nexport const Grid = styled.div`\n display: flex;\n flex-wrap: wrap;\n\n ${mediaMax.md`\n ${({ mobileWidthOffset }) =>\n mobileWidthOffset &&\n `\n margin: 0 -${ITEM_SIDE_PADING_MOBILE}px;\n `}\n `}\n\n ${media.md`\n margin: 0 -${ITEM_SIDE_PADDING_DESKTOP}px;\n `}\n`\n","import styled from 'styled-components'\n\nimport { media } from '../../../styles/media'\n\nimport { Grid, GridItem } from '../ItemGrid'\n\nconst RESULTS_MAP_RATIO = 1.61803398875\n\nexport const filterBarHeight = '80px'\n\nexport const Outerwrapper = styled.div``\n\nexport const FilterBarWrapper = styled.div`\n position: relative;\n display: flex;\n align-items: center;\n\n padding: 0 22px;\n width: 100%;\n min-height: ${filterBarHeight};\n\n & > button:first-child {\n margin-right: 16px;\n }\n`\n\nexport const ResultsArea = styled.div`\n padding: 24px 16px;\n width: calc(100% / ${RESULTS_MAP_RATIO});\n\n /* overriding grid item dimensions as results area is only part of screen width */\n\n ${Grid} {\n ${media.xl`\n margin: 0 -8px;\n `}\n\n ${GridItem} {\n width: 100%;\n\n ${media.xl`\n width: 50%;\n `}\n\n ${media.xxxl`\n width: 33.333%;\n `}\n\n ${media.xwide`\n width: 25%;\n `}\n }\n }\n`\n\nexport const MapContainer = styled.div`\n height: 100%;\n position: relative;\n background-color: #e1dfda;\n`\n\nexport const StickyBar = styled.div`\n position: sticky;\n top: 0;\n // If z-index is higher than 1 will obscure mini search dropdown, if lower the\n // filters will not sit above the search results:\n z-index: 1;\n\n > ${FilterBarWrapper} {\n background-color: white;\n border-bottom: 1px solid #e5e6e4;\n }\n\n > ${MapContainer} {\n // Make height equal to viewport height less the height of the bar area:\n height: calc(100vh - 100%);\n width: calc(100% - (100% / ${RESULTS_MAP_RATIO}));\n\n // Position at bottom right of filter-bar:\n position: absolute;\n top: 100%;\n right: 0;\n\n // Push behind filter bar:\n z-index: -1;\n }\n`\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport { media, mediaMax } from '../../../styles/media'\n\nimport PlaceholderCard from '../../cards/PlaceholderCard'\nimport { Content } from '../../cards/shared/styled'\nimport { Grid, GridItem } from '../ItemGrid'\n\nconst filterBarHeight = '80px'\nconst FilterBar = styled.div`\n position: relative;\n display: flex;\n align-items: center;\n\n padding: 0 22px;\n width: 100%;\n height: ${filterBarHeight};\n background-color: white;\n border-bottom: 1px solid;\n border-top: 1px solid;\n border-color: #e5e6e4;\n z-index: 1;\n`\n\nconst Wrapper = styled.div`\n height: 100vh;\n overflow: hidden;\n\n ${mediaMax.xl`\n ${FilterBar} {\n display: none;\n }\n `}\n`\n\nconst ContentWrapper = styled.div`\n display: flex;\n position: relative;\n`\n\n/*\n The loading component cannot decide between \"mobile\" and \"desktop\" layouts in JS -- it must instead accommodate\n the shape of both within a single wrapper via styled-components' css functions.\n\n This is because it gets server-side rendered, at which point it has no knowledge yet of whether it's going to be\n in \"mobile\" or \"desktop\" view, in the JS context. Our JS will only know once the contentful page mounts on the\n client (search, bucket list, itinerary search, etc.).\n\n But styled-components do support server-sider rendering and do have media queries avaiable in that context. This is\n why we can use css functions to switch width of the grid items within a single parent, but cannot decide via JS which\n parent to render as the wrapper around those grid items like we do for the contentful pages.\n*/\nconst ResultsWrapper = styled.div`\n padding: 24px 0;\n width: 100%;\n\n ${media.xl`\n width: calc(100% / 1.61803398875);\n padding: 24px 16px;\n `}\n\n ${Grid} {\n ${media.sm`\n margin: 0 8px;\n\n ${Content} {\n padding-left: 0 !important;\n padding-right: 0 !important;\n }\n `}\n\n ${GridItem} {\n width: 100%;\n\n ${media.sm`\n width: 50%;\n padding: 0 8px;\n `}\n\n ${media.lg`\n width: 33.333%;\n `}\n\n ${media.xl`\n width: 50%;\n `}\n\n ${media.xxxl`\n width: 33.333%;\n `}\n\n ${media.xwide`\n width: 25%;\n `}\n }\n }\n`\n\nconst MapWrapper = styled.div`\n flex: 1;\n height: 100vh;\n background-color: #e1dfdb;\n\n ${mediaMax.xl`\n display: none;\n `}\n`\n\ntype LoadingViewProps = {\n noFilters?: boolean\n}\n\nconst LoadingView = ({ noFilters }: LoadingViewProps) => (\n \n {!noFilters && }\n \n \n \n {[...Array(12)].map((e, i) => (\n // eslint-disable-next-line react/no-array-index-key\n \n \n \n ))}\n \n \n\n \n \n \n)\n\nexport default LoadingView\n","import styled from 'styled-components'\n\nimport { media, mediaMax } from '../../../styles/media'\n\nimport { Content } from '../../cards/shared/styled'\nimport {\n heightLarge as navbarHeightLarge,\n heightSmall as navbarHeightSmall,\n navbarSizeBreakpoint as navbarBreakpoint,\n} from '../../../layout/Navbar/constants'\n\nimport { Grid, GridItem } from '../ItemGrid'\n\nexport const Outerwrapper = styled.div`\n ${mediaMax[navbarBreakpoint]`\n padding-top: ${navbarHeightSmall}px;\n `}\n\n ${media[navbarBreakpoint]`\n padding-top: ${navbarHeightLarge}px;\n `}\n`\n\nexport const MobileSearchViewWrapper = styled.div`\n position: relative;\n padding-bottom: 88px;\n`\n\nexport const ResultsWrapper = styled.div`\n padding-top: 24px;\n\n ${Grid} {\n ${media.sm`\n margin: 0;\n padding-left: 8px;\n padding-right: 8px;\n\n ${Content} {\n padding-left: 0 !important;\n padding-right: 0 !important;\n }\n `}\n }\n\n ${GridItem} {\n width: 100%;\n\n ${media.sm`\n width: 50%;\n padding: 0 16px;\n `}\n\n ${media.lg`\n width: 33.333%;\n `}\n }\n`\n\ntype MapWrapperProps = {\n $offsetForNavbar?: boolean\n}\n\nexport const MapWrapper = styled.div`\n position: fixed;\n left: 0;\n\n ${mediaMax[navbarBreakpoint]`\n top: ${({ $offsetForNavbar }) =>\n $offsetForNavbar ? `${navbarHeightSmall}px` : '0px'};\n height: ${({ $offsetForNavbar }) =>\n `calc(100% - ${$offsetForNavbar ? navbarHeightSmall : 0}px)`};\n `}\n\n ${media[navbarBreakpoint]`\n top: ${({ $offsetForNavbar }) =>\n $offsetForNavbar ? `${navbarHeightLarge}px` : '0px'};\n height: ${({ $offsetForNavbar }) =>\n `calc(100% - ${$offsetForNavbar ? navbarHeightLarge : 0}px)`};\n `}\n\n width: 100%;\n`\n\nexport const MobileFilters = styled.div`\n width: 100%;\n background-color: white;\n\n z-index: 1;\n`\n\nexport const StickyMobileFilters = styled(MobileFilters)`\n position: -webkit-sticky;\n position: sticky;\n\n ${mediaMax[navbarBreakpoint]`\n top: ${navbarHeightSmall}px;\n `}\n\n ${media[navbarBreakpoint]`\n top: ${navbarHeightLarge}px;\n `}\n`\n\nexport const MobileFiltersOuter = styled.div`\n background-color: ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n border-bottom: 1px solid #d3d3d3;\n`\n\nexport const MobileFiltersInner = styled.div`\n display: flex;\n align-items: center;\n padding: 12px 0;\n overflow-x: auto;\n scrollbar-width: none;\n\n & > * {\n margin-right: 8px;\n flex: 0 0 auto;\n\n &:first-child:not(:last-child) {\n margin-left: 16px;\n }\n\n &:last-child {\n margin-right: 0;\n }\n }\n`\n","import { useMediaQueryContext } from 'contexts/MediaQueryContext'\n\nexport type MapMode = 'inline' | 'toggle'\n\nconst useWhichMapMode = (): MapMode => {\n const { xl } = useMediaQueryContext()\n\n return xl ? 'inline' : 'toggle'\n}\n\nexport default useWhichMapMode\n","import React from 'react'\nimport styled from 'styled-components'\n\ntype Props = {\n style?: React.CSSProperties\n}\n\nconst Outer = styled.div`\n font-size: 14px;\n text-align: center;\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n\n a {\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n }\n`\n\nconst Terms = ({ style }: Props) => (\n \n By signing up, you confirm that you accept the{' '}\n \n Terms of Service\n {' '}\n and{' '}\n \n Privacy Policy\n \n .\n \n)\n\nexport default Terms\n","import React from 'react'\nimport styled, { ThemeProvider } from 'styled-components'\n\nimport styledTheme from '../../../styles/theme'\nimport { trackAdventureViewed } from '../../../analytics/map'\n\nimport { MarkerPopupWrapper } from '../styled'\nimport WithSelectEscape from '../../SelectEscape/WithSelectEscape'\nimport AdventureCard from '../../../pages/listing/Adventures/AdventureCard'\n\nconst CalloutWrapper = styled.div`\n position: relative;\n height: 0;\n width: 0;\n font-family: 'GT Walsheim Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif !important;\n\n transition: transform 300ms ease-out;\n\n ${({ x, y }) => `\n transform: translate(${x}px, ${y}px);\n `}\n\n ${({ open }) =>\n open &&\n `\n z-index: 1;\n `}\n`\n\nexport default class AdventureCallout extends React.Component {\n constructor() {\n super()\n this.state = {\n transform: {\n x: 0,\n y: 0,\n },\n }\n this.isDragging = false\n this.calloutRef = React.createRef()\n this.analyticsTracked = false\n }\n\n componentDidMount() {\n const { transform } = this.props\n\n if (transform) {\n setTimeout(() => this.setState({ transform }), 0)\n }\n }\n\n componentDidUpdate() {\n const { open, mapContainerRef, adventure, source } = this.props\n\n if (adventure?.id && open && this.analyticsTracked !== true) {\n trackAdventureViewed({\n adventureId: adventure.id,\n source,\n })\n this.analyticsTracked = true\n }\n\n if (open && mapContainerRef.current) {\n mapContainerRef.current.addEventListener(\n 'mousedown',\n this.handleMouseDown\n )\n mapContainerRef.current.addEventListener(\n 'mousemove',\n this.handleMouseMove\n )\n mapContainerRef.current.addEventListener('mouseup', this.handleMouseUp)\n mapContainerRef.current.addEventListener('click', this.handleMouseUp)\n } else {\n this.removeListeners()\n }\n }\n\n componentWillUnmount() {\n this.removeListeners()\n }\n\n removeListeners = () => {\n const { mapContainerRef } = this.props\n if (mapContainerRef.current) {\n mapContainerRef.current.removeEventListener(\n 'mousedown',\n this.handleMouseDown\n )\n mapContainerRef.current.removeEventListener(\n 'mousemove',\n this.handleMouseMove\n )\n mapContainerRef.current.removeEventListener('mouseup', this.handleMouseUp)\n mapContainerRef.current.removeEventListener('click', this.handleMouseUp)\n }\n }\n\n handleMouseDown = () => {\n this.isDragging = false\n }\n\n handleMouseUp = (e) => {\n if (!this.isDragging) {\n const { onClose } = this.props\n if (!this.calloutRef.current.contains(e.target)) {\n onClose()\n }\n }\n }\n\n handleMouseMove = () => {\n this.isDragging = true\n }\n\n render() {\n const { transform } = this.state\n const {\n adventure,\n children,\n open,\n bookingAdventuresIndex,\n bucketListItemsIndex,\n onAddedToBucketList,\n onRemovedFromBucketList,\n onPopupInteractionStart,\n onPopupInteractionEnd,\n notBucketListable,\n } = this.props\n\n if (!adventure || !adventure?.id) {\n return null\n }\n\n return (\n \n \n \n {children}\n
\n {notBucketListable ? (\n \n ) : (\n \n \n \n )}\n \n
\n \n \n )\n }\n}\n","import React, { FunctionComponent } from 'react'\n\nimport Map, { Result } from '../Map'\nimport AdventureCallout from './AdventureCallout'\n\ntype MarkerCalloutProps = {\n type: 'Listing' | 'Adventure'\n}\n\nconst MarkerCallout: FunctionComponent = ({\n type,\n ...props\n}) => {\n switch (type) {\n case 'Adventure':\n return \n case 'Listing':\n return <>{props.children}>\n default:\n return null\n }\n}\n\nexport type ListingPopupData = {\n id: number | string\n location: {\n lat: number\n lng: number\n }\n listing_type: {\n slug: string\n }\n listing_subcategory?: {\n slug: string\n }\n}\n\ntype ListingResult = Result & {\n listing: ListingPopupData\n}\n\ntype AdventureResult = Result & {\n adventure: Omit\n}\n\ntype ListingMapProps = {\n listing?: ListingResult\n adventures?: AdventureResult[]\n analyticsSource: string\n hide?: boolean\n}\n\nconst ListingMap: FunctionComponent = ({\n listing,\n adventures,\n analyticsSource,\n hide,\n}) => {\n if (hide) {\n return null\n }\n\n const unclustered = listing ? [listing] : []\n const clustered = adventures?.length > 0 ? adventures : []\n\n return (\n \n )\n}\n\nexport default ListingMap\n","import React from 'react'\nimport styled, { ThemeProvider } from 'styled-components'\nimport styledTheme from '../../../styles/theme'\n\nimport Panel from '../../display/Panel'\nimport AdventureCard from '../../../pages/listing/Adventures/AdventureCard'\n\nexport const Marker = styled.button`\n width: 40px;\n height: 40px;\n margin-left: -20px;\n margin-top: -20px;\n padding: 0;\n\n appearance: none;\n outline: none;\n border: none;\n border-radius: 50%;\n\n font-size: 14px;\n font-weight: 500;\n text-align: center;\n\n color: ${({ theme }) => theme.brand.forest};\n background-color: ${({ theme }) => theme.brand.sunup};\n\n .icon,\n svg {\n display: inline-block;\n vertical-align: middle;\n font-size: 24px;\n line-height: 1;\n }\n\n ${({ big }) =>\n big &&\n `\n width: 80px;\n height: 80px;\n margin-left: -40px;\n margin-top: -40px;\n\n .icon,\n svg {\n font-size: 40px;\n }\n `}\n\n ${({ jungle, theme }) =>\n jungle &&\n `\n color: white;\n background-color: ${theme.brand.jungle};\n `}\n\n ${({ standalone }) =>\n standalone &&\n `\n margin: 0;\n `}\n`\n\nconst AdventureCardPopup = styled.div`\n position: absolute;\n width: 230px;\n left: 50%;\n top: 40px;\n\n text-align: left;\n border-radius: 5px;\n\n transform: translate(-50%, 0);\n\n box-shadow: 0 6px 2px 0 rgba(0, 0, 0, 0.1);\n\n z-index: 9;\n\n &:before,\n &:after {\n content: '';\n position: absolute;\n left: 50%;\n margin-left: -8px;\n transform: rotate(45deg);\n width: 16px;\n height: 16px;\n }\n\n &:before {\n top: -8px;\n background-color: #d1d1d1;\n }\n\n &:after {\n top: -7px;\n background-color: ${({ theme }) => theme.brand.sand};\n }\n`\n\nexport class AdventureMarker extends React.Component {\n state = {\n open: false,\n }\n\n handleOpen = () => {\n const { onClick } = this.props\n const { open } = this.state\n this.setState({ open: true })\n if (!open) {\n onClick()\n }\n }\n\n handleClose = () => {\n this.setState({ open: false })\n }\n\n render() {\n const { open } = this.state\n const { listing, adventure, children, ...props } = this.props\n return (\n \n \n {children}\n
\n \n \n \n \n \n \n
\n \n )\n }\n}\n","import React from 'react'\n\nconst SvgIconPlusThin = (props) => (\n \n)\n\nexport default SvgIconPlusThin\n","import React from 'react'\n\nconst SvgIconMinusThin = (props) => (\n \n)\n\nexport default SvgIconMinusThin\n","/* global analytics */\nimport React from 'react'\nimport isEqual from 'react-fast-compare'\nimport styled from 'styled-components'\nimport debounce from 'lodash/debounce'\nimport has from 'lodash/has'\n\nimport GoogleMapReact from 'google-map-react'\n// @ts-ignore -- need a way to type Google's coordinates interface\nimport LatLng from 'google-map-react/lib/utils/lib_geo/lat_lng.js'\nimport isBot from 'isbot'\n\nimport useDispatch from 'hooks/useDispatch'\nimport { mediaMax } from 'styles/media'\nimport RailsContext from '../../../contexts/RailsContext'\nimport DescendantOfMapContext from '../../../contexts/DescendantOfMapContext'\nimport { updateFilters } from '../../../actions/searchActions'\nimport useIsServer from '../../../hooks/useIsServer'\nimport { useGetSelectEscapeIndexesQuery } from '../../../hooks/useQueries'\n\nimport Button from '../../display/Button'\nimport InlineSpinner from '../../display/InlineSpinner'\nimport IconPlus from '../../icons/PlusThin'\nimport IconMinus from '../../icons/MinusThin'\nimport { Marker } from '../ListingMap/markers'\n\nimport { Bounds, boundsToFloat, generateSpiderParams } from './mapUtils'\n\nconst MapWrapper = styled.div`\n overflow: hidden;\n width: 100%;\n height: 100%;\n background-color: #e1dfda;\n position: relative;\n`\n\nconst LoadingOverlay = styled.div<{ show?: boolean }>`\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n background-color: black;\n opacity: 0;\n z-index: -1;\n transition: z-index 500ms ease-out, opacity 500ms ease-out;\n ${({ show }) =>\n show &&\n `\n z-index: 2;\n opacity: 0.4;\n `}\n`\n\nconst ReflectMapResults = styled(Button)`\n position: absolute;\n top: 16px;\n right: 0;\n left: 0;\n margin: 0 auto;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 40px;\n width: 160px;\n border-radius: 100px;\n\n font-size: 14px;\n text-transform: capitalize;\n line-height: 1;\n letter-spacing: 0.25px;\n\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n outline: 0;\n background-color: white;\n\n box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.1);\n\n &:hover {\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n }\n`\n\nconst CustomZoom = styled.div`\n position: absolute;\n z-index: 8;\n top: 50px;\n right: 0;\n margin: 10px;\n background-color: ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n color: ${({ theme }) => theme?.['-ds-neutral-600']?.value};\n border-radius: 2px;\n box-shadow: rgb(0 0 0 / 30%) 0px 1px 4px -1px;\n padding: 8px;\n\n ${mediaMax.md`\n display: none;\n `}\n\n > button {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n background: transparent;\n border: none;\n box-shadow: none;\n\n &:hover:not(:disabled) {\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n }\n\n &:disabled {\n color: ${({ theme }) => theme?.['-ds-neutral-400']?.value};\n }\n }\n\n svg {\n width: 24px;\n height: auto;\n }\n\n hr {\n margin-top: 8px;\n margin-bottom: 8px;\n border-color: ${({ theme }) => theme?.['-ds-neutral-600']?.value};\n }\n`\n\nconst resultIsAccommodation = (mapResultType: GQL_MapResult['type']) => {\n switch (mapResultType) {\n case 'Adventure':\n return false\n case 'Listing':\n default:\n return true\n }\n}\n\nconst panMapYByPx = () => {\n return 180 // approximately half of the typical popup height (which varies slightly, but simpler to keep this offset static for now)\n}\n\nconst shouldShowSearchThisArea = ({\n dragging,\n hasBeenZoomed,\n hasBeenDragged,\n markerIsOpen,\n}: {\n dragging: boolean\n hasBeenZoomed: boolean\n hasBeenDragged: boolean\n markerIsOpen: boolean\n}) => {\n if (dragging) {\n return true\n }\n\n if (hasBeenZoomed) {\n return true\n }\n\n if (markerIsOpen && !dragging && !hasBeenDragged) {\n return false\n }\n\n return hasBeenDragged\n}\n\ninterface Cluster {\n id?: number\n geometry: {\n coordinates: number[]\n type: string\n }\n properties: {\n cluster_id?: number\n point_count?: number\n id: number | string\n slug: string\n type: GQL_Searchable\n adventure_type?: {\n slug: string\n }\n cluster?: any\n notBucketListable?: boolean\n disablePopup?: boolean\n }\n}\n\nexport type Result = Omit<\n GQL_MapResult,\n 'coordinates' | 'markerCount' | '__typename'\n> & {\n location: number[]\n notBucketListable?: boolean // e.g. on-property adventures cannot be added to bucket list\n disablePopup?: boolean\n}\n\nconst DEFAULT_CENTER = [-37.814, 144.96332] // Melbourne\nconst DEFAULT_ZOOM = 14\n\nconst baseOptions = {\n maxZoom: 14,\n gestureHandling: 'greedy',\n zoomControl: false,\n clickableIcons: false,\n}\n\ntype SearchMapBaseProps = {\n results: Result[]\n unclusteredResults?: Result[] // to be rendered as separate markers at all zoom levels, that won't cluster with others\n loading?: boolean\n filters?: GQL_SearchFilters\n searchQuery?: string\n defaultCenter?: [number, number]\n defaultZoom?: number\n noSearchThisArea?: boolean\n mobile?: boolean\n analyticsSource: string // analytics events property\n PopupComponent: React.ComponentType\n}\n\ntype InjectedProps = {\n dispatch: (message: any) => void\n serverSide: boolean\n bookingAdventuresIndex: GQL_BookingAdventuresIndex\n bucketListItemsIndex: GQL_BucketListItemsIndex\n}\n\ntype MapFullProps = SearchMapBaseProps & InjectedProps\n\ntype MapState = {\n map?: any // Current Google Map Instance\n maps?: any // Google Maps JS API\n center: number[]\n zoom?: number\n bounds: Bounds\n makingClusters: boolean\n dragging: boolean\n hasBeenDragged: boolean\n hasBeenZoomed: boolean\n openedMarkerId?: number | string\n openedClusterId?: number | string\n clusters: Cluster[]\n leaves: Cluster[]\n fitToBounds: boolean\n}\n\nclass Map extends React.Component {\n fitBoundsToResultsDebounced: () => any\n\n mapContainer: React.RefObject\n\n ClusteringWorker: any\n\n static defaultProps: {\n defaultZoom: number\n }\n\n constructor(props: MapFullProps) {\n super(props)\n this.state = {\n map: null, // Current Google Map Instance\n maps: null, // Google Maps JS API\n center: props.defaultCenter || DEFAULT_CENTER,\n zoom: props.defaultZoom || DEFAULT_ZOOM,\n bounds: {\n nw: new LatLng(85, -180),\n ne: new LatLng(85, 180),\n sw: new LatLng(-85, -180),\n se: new LatLng(-85, 180),\n },\n openedMarkerId: null,\n openedClusterId: null,\n clusters: [],\n leaves: [],\n makingClusters: false,\n dragging: false,\n hasBeenDragged: false,\n hasBeenZoomed: false,\n fitToBounds: false,\n }\n\n this.fitBoundsToResultsDebounced = debounce(this.fitBoundsToResults, 300)\n this.mapContainer = React.createRef()\n }\n\n /**\n * We need to initialize the clustering web worker\n */\n componentDidMount() {\n // eslint-disable-next-line global-require\n const ClusteringWorker = require('./clustering-gql.worker')\n // @ts-ignore -- web worker interface needs typing\n this.ClusteringWorker = new ClusteringWorker()\n this.ClusteringWorker.addEventListener(\n 'message',\n ({ data }: { data: MapState }) => {\n requestAnimationFrame(() => {\n this.setState(data)\n })\n }\n )\n }\n\n componentDidUpdate(prevProps: MapFullProps) {\n const { results } = this.props\n\n const noNewResults = isEqual(prevProps.results, results)\n\n if (noNewResults !== true) {\n /**\n * We need to fit the bounds of the map to the listings we received\n * and initialize our clusters, but only when searchMapResults have been\n * fetched or refetched\n */\n this.fitBoundsToResultsDebounced()\n /**\n * We need to wait 500ms for the fitBounds animation to finish before\n * displaying our markers for the first time\n */\n setTimeout(() => {\n this.makeClusters()\n }, 600)\n }\n }\n\n componentWillUnmount() {\n this.ClusteringWorker.terminate()\n }\n\n /**\n * We need to build up clusters with the listings results coming in from the API\n */\n makeClusters = () => {\n const { results } = this.props\n\n this.setState({\n makingClusters: true,\n })\n\n /**\n * We need to be careful not to send `map` or `maps` objects\n * to the worker as this causes a JS error\n */\n const { map, maps, ...state } = this.state\n\n this.ClusteringWorker.postMessage({\n type: 'makeClusters',\n params: {\n results,\n ...state,\n },\n })\n }\n\n /**\n * We need to fit the bounds of the map to the results\n * we receive from the API\n */\n fitBoundsToResults = () => {\n const {\n results,\n noSearchThisArea,\n filters,\n unclusteredResults,\n } = this.props\n\n // If filtered by country/state or has prop noSearchThisArea\n if (noSearchThisArea || filters.country || filters.state) {\n const { map, maps, zoom } = this.state\n\n const combinedResults = [...results, ...(unclusteredResults || [])]\n\n if (!map || !maps || combinedResults.length === 0) {\n return\n }\n\n const bounds = new maps.LatLngBounds()\n combinedResults.forEach((result) => {\n const [lat, lng] = result.location\n const latLng = new maps.LatLng(lat, lng)\n bounds.extend(latLng)\n })\n\n this.setState({\n fitToBounds: true,\n hasBeenZoomed: false,\n hasBeenDragged: false,\n })\n\n map.fitBounds(bounds, 40)\n\n if (map.getZoom() === zoom) {\n this.setState({\n fitToBounds: false,\n })\n }\n }\n }\n\n /**\n * We need to send the map bounds as filters so they appear in the\n * URL parameters and update the listing results\n */\n handleReflectMapResults = () => {\n const { dispatch } = this.props\n const { bounds } = this.state\n\n dispatch(\n updateFilters({\n sw: boundsToFloat(bounds.sw),\n ne: boundsToFloat(bounds.ne),\n location: null,\n origin: null,\n country: null,\n })\n )\n analytics.track('Search by Map')\n\n this.setState({\n hasBeenZoomed: false,\n hasBeenDragged: false,\n })\n }\n\n handleClusterClick = ({ geometry, properties }: Cluster) => {\n const { zoom, openedClusterId } = this.state\n const clusterId = properties.cluster_id\n /**\n * We need to close a cluster if it is already opened\n */\n if (clusterId === openedClusterId) {\n this.setState({\n openedClusterId: null,\n leaves: [],\n })\n\n /**\n * We need to zoom and center to the next level of cluster extension\n * or expand the cluster to show its leaves if at MAX_ZOOM\n */\n } else {\n this.ClusteringWorker.postMessage({\n type: 'zoomUntilClusterExpands',\n params: {\n clusterId,\n center: geometry.coordinates.slice().reverse(),\n zoom,\n },\n })\n }\n }\n\n /**\n * We need to open a marker callout and fetch the data for display\n * when clicking on a marker\n */\n handleMarkerClick = (\n resultId: string | number,\n center: MapState['center'],\n disablePopup?: boolean\n ) => {\n const { map, openedMarkerId } = this.state\n\n this.setState(\n {\n center,\n openedMarkerId: disablePopup ? null : resultId,\n hasBeenDragged: false,\n },\n () => {\n if (openedMarkerId !== resultId && !disablePopup) {\n const panDownBy = panMapYByPx()\n map.panTo({ lat: center[0], lng: center[1] })\n map.panBy(0, -panDownBy)\n } else {\n this.handleCalloutClose()\n }\n }\n )\n }\n\n /**\n * Same but for a Leaf\n */\n handleLeafClick = (\n resultId: string | number,\n geometry: Cluster['geometry'],\n leafParams: { x: number; y: number },\n disablePopup?: boolean\n ) => {\n const { map, openedMarkerId } = this.state\n const leafParentCoordinates = geometry.coordinates.slice().reverse() as [\n number,\n number\n ]\n const panDownBy = panMapYByPx()\n\n this.setState(\n {\n center: leafParentCoordinates,\n openedMarkerId: disablePopup ? null : resultId,\n hasBeenDragged: false,\n },\n () => {\n if (openedMarkerId !== resultId) {\n // NB: panning is in pixels, not geo coordinates\n const { x: leafXOffset, y: leafYOffset } = leafParams\n map.panTo({\n lat: leafParentCoordinates[0],\n lng: leafParentCoordinates[1],\n })\n map.panBy(0 + leafXOffset, -panDownBy + leafYOffset)\n }\n }\n )\n }\n\n handleCalloutClose = () => {\n this.setState({\n openedMarkerId: null,\n })\n }\n\n handleGoogleApiLoaded = ({ map, maps }: { map: any; maps: any }) => {\n this.setState({\n map,\n maps,\n })\n this.fitBoundsToResultsDebounced()\n }\n\n /**\n * We need to make sure clusters are regenerated everytime we move\n * zoom or pan the map\n */\n handleOnChange = ({\n center,\n zoom,\n bounds,\n }: {\n center: [number, number]\n zoom: number\n bounds: Bounds\n }) => {\n this.setState(\n {\n center,\n zoom,\n bounds,\n },\n () => {\n this.makeClusters()\n }\n )\n }\n\n suspendGestureHandling = () => {\n const { map } = this.state\n map.setOptions({\n gestureHandling: 'none',\n })\n }\n\n restoreGestureHandling = () => {\n const { map } = this.state\n\n map.setOptions({\n gestureHandling: baseOptions.gestureHandling,\n })\n }\n\n createMapOptions = () => {\n const { mobile } = this.props\n\n if (mobile) {\n return {\n ...baseOptions,\n fullscreenControl: false,\n }\n }\n\n return {\n ...baseOptions,\n }\n }\n\n handleZoomClick = (newZoom: number) => {\n const { map } = this.state\n map.setZoom(newZoom)\n }\n\n handleZoomStart = (nextZoom: number) => {\n const { fitToBounds, zoom: prevZoom } = this.state\n\n if (nextZoom !== prevZoom) {\n if (fitToBounds) {\n this.setState({\n fitToBounds: false,\n })\n } else {\n this.setState({\n hasBeenZoomed: true,\n })\n }\n }\n }\n\n renderCluster = (c: Cluster) => {\n const hasAccommodationResults = has(c.properties, 'Listing')\n\n return (\n this.handleClusterClick(c)}\n jungle={hasAccommodationResults}\n >\n {c.properties.point_count}\n \n )\n }\n\n renderMarker = (c: Cluster) => {\n const {\n bookingAdventuresIndex,\n bucketListItemsIndex,\n filters,\n analyticsSource,\n PopupComponent,\n } = this.props\n const { openedMarkerId } = this.state\n const { id, type, slug, disablePopup } = c.properties\n\n return (\n \n \n this.handleMarkerClick(\n id,\n c.geometry.coordinates.slice().reverse(),\n disablePopup\n )\n }\n // @ts-ignore -- not typed yet\n jungle={resultIsAccommodation(type)}\n >\n \n \n \n )\n }\n\n renderLeaves = (leaves: Cluster[]) => {\n const {\n bookingAdventuresIndex,\n bucketListItemsIndex,\n filters,\n analyticsSource,\n PopupComponent,\n } = this.props\n const { openedMarkerId } = this.state\n const params = generateSpiderParams(leaves.length)\n return leaves.map((c, i) => {\n const leafParams = params[i]\n const { id, type, slug, disablePopup } = c.properties\n return (\n \n \n this.handleLeafClick(id, c.geometry, leafParams, disablePopup)\n }\n // @ts-ignore -- not typed yet\n jungle={resultIsAccommodation(c.properties.type)}\n >\n \n \n \n )\n })\n }\n\n renderClusters = (clusters: Cluster[]) => {\n return clusters.map((c) =>\n c.properties.cluster ? this.renderCluster(c) : this.renderMarker(c)\n )\n }\n\n renderUnclusteredResults = (results: MapFullProps['unclusteredResults']) => {\n return results.map((result) => {\n const { id, type, slug, disablePopup, location } = result\n return this.renderMarker({\n properties: {\n id,\n slug,\n type,\n disablePopup,\n ...result, // pass through additional properties that the popup component might need\n },\n geometry: {\n type: 'Point',\n coordinates: location.slice().reverse(), // [lat, lng] => [lng, lat]\n },\n })\n })\n }\n\n render() {\n if (isBot(navigator.userAgent)) return null\n\n const {\n unclusteredResults,\n serverSide,\n loading,\n noSearchThisArea,\n } = this.props\n const {\n bounds,\n center,\n clusters,\n dragging,\n hasBeenDragged,\n leaves,\n makingClusters,\n openedMarkerId,\n zoom,\n hasBeenZoomed,\n map,\n } = this.state\n\n const readying = loading || makingClusters\n\n const showSearchThisArea =\n !noSearchThisArea &&\n shouldShowSearchThisArea({\n markerIsOpen: !!openedMarkerId,\n hasBeenDragged,\n dragging,\n hasBeenZoomed,\n })\n\n return (\n // eslint-disable-next-line react/jsx-boolean-value -- deliberately explicit about all descendants being descendants of a map\n \n \n {({ env }) => (\n \n {!serverSide && (\n // @ts-ignore -- types around the coordinates data structure need to be fixed\n {\n this.setState({ dragging: true, hasBeenDragged: true })\n }}\n onDragEnd={() => this.setState({ dragging: false })}\n onZoomAnimationStart={this.handleZoomStart}\n yesIWantToUseGoogleMapApiInternals\n onGoogleApiLoaded={this.handleGoogleApiLoaded}\n >\n {!loading && this.renderClusters(clusters)}\n {!loading && this.renderLeaves(leaves)}\n {!loading &&\n unclusteredResults?.length > 0 &&\n this.renderUnclusteredResults(unclusteredResults)}\n \n )}\n {showSearchThisArea && (\n \n {readying ? : `Search this area`}\n \n )}\n \n\n {!loading && (\n \n \n
\n \n \n )}\n \n )}\n \n \n )\n }\n}\n\nMap.defaultProps = {\n defaultZoom: 7,\n}\n\nconst withBucketListableProps = (Component: typeof Map) => (\n props: SearchMapBaseProps\n) => {\n const dispatch = useDispatch()\n const serverSide = useIsServer()\n\n const { data } = useGetSelectEscapeIndexesQuery()\n\n const bucketListItemsIndex = data?.currentUser\n ?.bucketListItemsIndex as GQL_BucketListItemsIndex\n\n const bookingAdventuresIndex = data?.currentUser\n ?.bookingAdventuresIndex as GQL_BookingAdventuresIndex\n\n if (serverSide) {\n return null\n }\n\n return (\n \n )\n}\n\nexport default withBucketListableProps(Map)\n","// @ts-ignore -- need a way to type Google's coordinates interface\nimport LatLngBounds from 'google-map-react/lib/utils/lib_geo/lat_lng_bounds.js'\n// @ts-ignore -- need a way to type Google's coordinates interface\nimport LatLng from 'google-map-react/lib/utils/lib_geo/lat_lng.js'\n\nconst twoPi = Math.PI * 2\nconst circleSpiralSwitchover = 9\nconst circleFootSeparation = 56 // related to circumference of circle\nconst spiralFootSeparation = 56 // related to size of spiral (experiment!)\nconst spiralLengthStart = 56 // ditto\nconst spiralLengthFactor = 4 // ditto\n\ntype IteratorFn = (index: number) => any\ntype ItemIteratorFn = (item: any, index: number) => any\n\n/* eslint-disable */\nfunction eachFn(array: any[], iterator: ItemIteratorFn): [] | void {\n var i = 0\n if (!array || !array.length) {\n return []\n }\n for (i = 0; i < array.length; i++) {\n iterator(array[i], i)\n }\n}\n\nfunction eachTimesFn(count: number, iterator: IteratorFn): [] | void {\n if (!count) {\n return []\n }\n for (var i = 0; i < count; i++) {\n iterator(i)\n }\n}\n\nfunction mapFn(array: any[], iterator: ItemIteratorFn): any[] {\n var result: any[] = []\n eachFn(array, function (item, i) {\n result.push(iterator(item, i))\n })\n return result\n}\n\nfunction mapTimesFn(count: number, iterator: IteratorFn): any[] {\n var result: any[] = []\n eachTimesFn(count, function (i) {\n result.push(iterator(i))\n })\n return result\n}\n\nconst util = {\n each: eachFn,\n map: mapFn,\n mapTimes: mapTimesFn,\n eachTimes: eachTimesFn,\n}\n/* eslint-enable */\n\nexport function generateSpiralParams(count: number) {\n let legLength = spiralLengthStart\n let angle = 0\n return util.mapTimes(count, (index) => {\n angle += spiralFootSeparation / legLength + index * 0.0005\n const pt = {\n x: legLength * Math.cos(angle),\n y: legLength * Math.sin(angle),\n }\n legLength += (twoPi * spiralLengthFactor) / angle\n return pt\n })\n}\n\nexport function generateCircleParams(count: number) {\n const circumference = circleFootSeparation * (2 + count)\n const legLength = circumference / twoPi // = radius from circumference\n const angleStep = twoPi / count\n\n return util.mapTimes(count, (index) => {\n const angle = index * angleStep\n return {\n x: legLength * Math.cos(angle),\n y: legLength * Math.sin(angle),\n }\n })\n}\n\nexport function generateSpiderParams(count: number) {\n if (count >= circleSpiralSwitchover) {\n return generateSpiralParams(count)\n }\n return generateCircleParams(count)\n}\n\nexport const boundsToLatLngArray = (bounds: string[]) =>\n bounds\n .map((corner) => corner.split(','))\n .map(([lat, lng]) => [parseFloat(lat), parseFloat(lng)])\n .map(([lat, lng]) => ({ lat, lng }))\n\nexport const centerFromBounds = ({\n ne,\n sw,\n}: {\n ne: [number, number]\n sw: [number, number]\n}): [number, number] => {\n let center\n\n if (!ne || !sw) {\n return center\n }\n\n const bounds = new LatLngBounds(sw, ne)\n const { lat, lng } = bounds?.getCenter()\n\n if (lat && lng) {\n center = [lat, lng] as [number, number]\n }\n\n return center\n}\n\nexport interface Bounds {\n nw: LatLng\n ne: LatLng\n sw: LatLng\n se: LatLng\n}\n\nexport const boundsToFloat = (b: Bounds) =>\n Object.values(b).map((l) => parseFloat(l))\n","import React, { useState } from 'react'\n\nimport Modal from 'components/display/Modal'\nimport FadeIn from 'components/display/FadeIn'\nimport MobileViewToggle from 'search/filters/mobile/MobileViewToggle'\n\ntype MapModalProps = {\n mapComponent: React.ReactNode\n}\n\nconst MapModal = ({ mapComponent }: MapModalProps) => {\n const [showMap, setShowMap] = useState(false)\n const [hasToggledMap, setHasToggledMap] = useState(false)\n\n const handleOpenMap = () => {\n setHasToggledMap(true)\n setShowMap(true)\n }\n\n const handleCloseMap = () => setShowMap(false)\n\n return (\n <>\n \n\n \n {hasToggledMap && (\n \n \n {mapComponent}\n \n
\n )}\n \n \n >\n )\n}\n\nexport default MapModal\n","import styled from 'styled-components'\n\nexport const MarkerPopupWrapper = styled.div<{\n open?: boolean\n padded?: boolean\n}>`\n cursor: pointer; /* important for receiving correct mobile touch events */\n position: absolute;\n width: 280px;\n left: 50%;\n bottom: 28px;\n background-color: ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n padding: ${({ padded }) => (padded ? '8px' : '0')};\n text-align: left;\n border-radius: 6px;\n transform: translate(-50%, 0);\n z-index: 9;\n transition: opacity 300ms ease-out;\n visibility: hidden;\n opacity: 0;\n\n ${({ open }) =>\n open &&\n `\n opacity: 1;\n visibility: visible;\n `}\n\n &:before,\n &:after {\n content: '';\n position: absolute;\n left: 50%;\n margin-left: -8px;\n transform: rotate(45deg);\n width: 16px;\n height: 16px;\n }\n\n &:before {\n bottom: -8px;\n background-color: ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n }\n\n &:after {\n bottom: -7px;\n background-color: ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n }\n`\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\n\ntype MetaTagsProps = {\n title: string\n description?: string\n}\n\nconst MetaTags = ({ title, description }: MetaTagsProps) => {\n return (\n \n {title && {title} | Riparide}\n {description && }\n \n )\n}\n\nexport default MetaTags\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport { useMediaQueryContext } from 'contexts/MediaQueryContext'\n\nimport Modal from '../../display/Modal'\nimport InvisibleButton from '../../display/InvisibleButton'\nimport CloseIcon from '../../icons/AirbnbClose'\nimport { HeadingLg } from '../../display/Typography'\n\nconst Header = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n border-bottom: solid 1px #d3d3d3;\n position: sticky;\n top: 0;\n background-color: ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n z-index: 1;\n padding: 16px;\n`\n\nconst CloseButton = styled(InvisibleButton)`\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n\n svg {\n width: 14px;\n height: 14px;\n margin: 0;\n }\n`\n\nconst Content = styled.div`\n padding: 0 16px;\n`\n\ntype Props = React.ComponentProps & {\n title?: React.ReactNode\n narrowOnDesktop?: boolean\n}\n\nconst TrayModal: React.FC = ({\n title,\n children,\n isOpen,\n narrowOnDesktop,\n onRequestClose,\n}) => {\n const { md: largerThanMd } = useMediaQueryContext()\n\n const modalClassName = [\n 'ReactModal__Content',\n 'c-basic-modal__content',\n 'white',\n 'rounded',\n ...(!largerThanMd\n ? ['bottom-align', 'half-screen-max', 'rounded-top']\n : []),\n ...(largerThanMd && narrowOnDesktop ? ['narrow'] : []),\n ].join(' ')\n\n const modalOverlayClassName = [\n 'ReactModal__Overlay',\n 'c-basic-modal__overlay',\n ].join(' ')\n\n return (\n \n \n\n {children}\n \n )\n}\n\nexport default TrayModal\n","import React from 'react'\n\nimport { ParagraphXs } from 'components/display/Typography'\nimport { refundNotice, refundAmount } from '../utils/cancellationUtils'\nimport { isAccommodation } from '../utils/listingUtils'\n\ninterface ListingProps {\n listing_type: {\n slug: string\n }\n}\ninterface CancellationPolicyProps {\n listing: ListingProps\n policy: string\n short?: boolean\n}\n\nconst CancellationPolicy = ({\n listing,\n policy,\n short,\n}: CancellationPolicyProps) => {\n const firstSentence = () => (\n <>\n Receive a {refundAmount(policy)} refund{' '}\n {policy === 'partial' && 'of the total booking amount'} (minus service\n fee) up until {refundNotice(policy)} prior to{' '}\n {isAccommodation(listing) ? 'check-in' : 'the booking start date'}.\n >\n )\n\n const secondSentence = () => (\n <>\n No refunds will be given for cancellations with less than{' '}\n {refundNotice(policy)} notice.\n >\n )\n\n if (!policy) return null\n\n if (short) {\n return {firstSentence()}\n }\n\n return (\n <>\n \n {firstSentence()} {secondSentence()}\n \n >\n )\n}\n\nexport default CancellationPolicy\n","import React from 'react'\nimport pluralize from 'pluralize'\n\nimport { slugToNice } from '../utils/stringUtils'\nimport { formatPrice } from '../utils/pricing'\nimport { LineItemsProps, ListingProps } from './types'\n\nconst LineItemLabel = ({\n item,\n pricingSuffix,\n}: {\n item: Pick\n pricingSuffix: ListingProps['pricingSuffix']\n}) => {\n if (item.itemType === 'rental_fee') {\n return (\n \n {`${formatPrice(item.price)} x ${pluralize(\n pricingSuffix.split('_')[1],\n item.quantity,\n true\n )}`}\n \n )\n }\n\n return (\n \n {item.quantity > 1\n ? `${item.quantity} x ${slugToNice(item.itemType, true)}`\n : `${slugToNice(item.itemType, true)}`}\n \n )\n}\n\nexport default LineItemLabel\n","import React from 'react'\nimport { formatPrice } from '../utils/pricing'\n\nconst Price = ({ value }: { value: string | number }) => {\n const total = typeof value === 'string' ? parseFloat(value) : value\n\n return (\n \n {total < 0 ? `(${formatPrice(Math.abs(total))})` : formatPrice(total)}\n \n )\n}\n\nexport default Price\n","import React from 'react'\nimport styled from 'styled-components'\nimport pluralize from 'pluralize'\nimport accounting from 'accounting'\n\nimport InfoOutline from 'components/icons/InfoOutline'\nimport { formatPrice } from '../utils/pricing'\nimport { slugToNice } from '../utils/stringUtils'\nimport Tooltip from '../display/Tooltip'\nimport Price from './Price'\nimport LineItemLabel from './LineItemLabel'\nimport { Row, LabelColumn, PriceColumn } from './styles'\nimport { PricingProps, LineItemsProps, ListingProps } from './types'\n\nconst TooltipContent = styled.div`\n font-size: 14px;\n width: 200px;\n`\n\nconst Wrapper = styled.div`\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n font-weight: 300;\n padding-top: 16px;\n`\n\nconst PricingTotal = ({\n pricing,\n user,\n doNotShowPayoutTotal = false,\n}: {\n pricing: Pick<\n PricingProps,\n | 'status'\n | 'paymentStatus'\n | 'totalToPay'\n | 'currency'\n | 'payoutTotal'\n | 'total'\n >\n user: {\n firstName: string\n }\n doNotShowPayoutTotal: boolean\n}) => {\n const currencyLabel = pricing.currency ? `(${pricing.currency})` : ''\n\n if (pricing.totalToPay) {\n const label =\n pricing.status === 'initiated' || pricing.paymentStatus !== 'paid'\n ? 'Total'\n : 'Total paid'\n const paymentError =\n pricing.status === 'accepted' && pricing.paymentStatus === 'failed'\n return (\n \n \n {label} {currencyLabel}\n \n \n \n \n
\n )\n }\n if (!doNotShowPayoutTotal && user && pricing.payoutTotal && pricing.total) {\n return (\n \n \n {user.firstName} will pay\n \n \n \n
\n\n \n Your payout\n \n \n \n
\n \n )\n }\n if (!doNotShowPayoutTotal && pricing.payoutTotal) {\n return (\n \n Total payout\n \n \n \n
\n )\n }\n return (\n \n Total {currencyLabel}\n \n \n \n
\n )\n}\n\nconst CustomerServiceFee = ({ value }: { value?: string }) => {\n const serviceFee = parseFloat(value)\n const serviceFeeIncluded = serviceFee === 0\n\n return (\n \n \n Riparide service fee\n }>\n \n \n {serviceFeeIncluded ? (\n
\n The host will cover the guest service fee so there's\n nothing extra for you to pay 🙌\n
\n ) : (\n
\n This helps us pay the bills, run our platform and build cool\n new features. It includes tax.\n
\n )}\n
\n \n \n \n \n {serviceFeeIncluded ? 'FREE' : }\n \n
\n )\n}\n\nconst HostServiceFee = ({ value }: { value: number }) => (\n \n \n Riparide service fee\n }>\n \n \n
\n This helps us pay the bills, run our platform and build cool new\n features. It includes tax.\n
\n
\n \n \n \n \n \n \n
\n)\n\nconst Tax = ({\n value,\n details,\n}: {\n value: PricingProps['taxAmount']\n details: PricingProps['taxRateDetails']\n}) => (\n \n \n Tax\n {details && details.length > 0 && (\n }>\n \n \n {details\n .filter((d) => d.rate > 0)\n .map((detail) => (\n \n {detail.name}\n \n {accounting.toFixed(detail.rate * 100, 2)}%\n \n
\n ))}\n \n \n \n )}\n \n \n \n \n
\n)\n\nconst ItemDetails = ({ details }: { details: LineItemsProps['details'] }) => (\n \n {details.map((detail) => (\n \n {detail.label}\n \n \n \n
\n ))}\n \n)\n\nconst RentalFeeTip = ({\n item,\n hint,\n}: {\n item: Pick\n hint?: PricingProps['hint']\n}) =>\n (item.details && item.details.length > 1) || hint ? (\n }>\n \n {item.details.length > 1 && }\n {hint}
\n \n \n ) : null\n\nconst CleaningFeeTip = () => (\n }>\n \n A one-off fee for cleaning the property.\n \n \n)\n\nconst ExtraPersonFeeTip = ({\n item,\n listing,\n}: {\n item: Pick\n listing: Pick<\n ListingProps,\n 'extraPersonThreshold' | 'extraPersonFee' | 'pricingSuffix'\n >\n}) => (\n }>\n \n {!item.details && (\n \n The base price is for{' '}\n {pluralize('person', listing.extraPersonThreshold, true)}. A fee of{' '}\n {formatPrice(listing.extraPersonFee)} \n {slugToNice(listing.pricingSuffix)} applies for each additional guest.\n \n )}\n {item.details && }\n \n \n)\n\nconst DiscountTip = ({ item }: { item: Pick }) => (\n }>\n \n {item.details &&\n item.details.map((detail) => (\n {detail.label}\n ))}\n \n \n)\n\nconst GiftVouchersTip = ({\n vouchers,\n}: {\n vouchers: PricingProps['vouchers']\n}) => (\n }>\n \n \n {vouchers.map((voucher) => (\n \n {voucher.code}\n \n \n \n
\n ))}\n \n \n \n)\n\nconst PricingBreakdown = ({\n pricing,\n user,\n doNotShowPayoutTotal,\n showTax = true,\n}: {\n pricing: PricingProps\n user?: {\n id: string\n firstName: string\n }\n doNotShowPayoutTotal?: boolean\n showTax?: boolean\n}) => {\n const { lineItems, hint, listing } = pricing\n\n return (\n \n {lineItems.map((item) => (\n \n \n \n {(item.itemType === 'rental_fee' ||\n item.itemType === 'rental_fee') && (\n \n )}\n {item.itemType === 'discount' && }\n {item.itemType === 'cleaning_fee' && }\n {listing.extraPersonFee && item.itemType === 'extra_person_fee' && (\n \n )}\n \n\n \n \n \n
\n ))}\n {parseFloat(pricing.hostServiceFee) > 0 ? (\n \n ) : (\n \n )}\n {showTax && parseFloat(pricing.taxAmount) > 0 && (\n \n )}\n {parseFloat(pricing.voucherAmount) > 0 && (\n \n \n Gift voucher\n {pricing.vouchers && (\n \n )}\n \n \n \n \n
\n )}\n \n \n )\n}\n\nexport default PricingBreakdown\n","import styled from 'styled-components'\n\ninterface RowProps {\n highlight?: boolean\n error?: boolean\n bold?: boolean\n success?: boolean\n}\n\nexport const Row = styled.div`\n display: flex;\n justify-content: space-between;\n margin-bottom: 8px;\n\n ${({ error, theme }) =>\n error &&\n `\n font-weight: 400;\n color: ${theme?.['-ds-warning-300']?.value};\n `};\n\n ${({ bold }) =>\n bold &&\n `\n font-weight: 400;\n `};\n\n ${({ highlight, theme }) =>\n highlight &&\n `\n color: ${theme?.['-ds-core-400']?.value};\n font-weight: 400;\n `};\n`\n\nexport const LabelColumn = styled.div`\n width: 70%;\n`\n\nexport const PriceColumn = styled.div`\n width: 30%;\n text-align: right;\n`\n","import TextWithLineBreaks from 'components/TextWithLineBreaks'\nimport React from 'react'\n\nimport styled from 'styled-components'\n\nconst ReviewContentWrapper = styled.div`\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n overflow: hidden;\n`\n\nconst AnimatedText = styled.span<{ hide?: boolean }>`\n opacity: ${({ hide }) => (hide ? 0 : 1)};\n display: ${({ hide }) => (hide ? 'block' : 'inline')};\n height: ${({ hide }) => (hide ? 0 : 'auto')};\n transition: opacity 0.8s ease-in-out;\n`\n\nconst ReviewContent = ({\n content,\n showMore,\n truncateLength,\n}: {\n content: string\n showMore: boolean\n truncateLength: number\n}) => {\n const realTruncate = truncateLength - 100 // Makes sure that the truncate doesn't just show a couple of words\n return (\n \n {content.length > truncateLength ? (\n <>\n
\n \n {!showMore && '...'}\n \n \n \n \n >\n ) : (\n
{content}\n )}\n
\n )\n}\n\nexport default ReviewContent\n","import React from 'react'\n\nimport { rgba } from 'polished'\nimport styled from 'styled-components'\n\nconst MomentItem = styled.div<{ transitionDelay?: number; hide?: boolean }>`\n opacity: ${({ hide }) => (hide ? 0 : 1)};\n position: ${({ hide }) => (hide ? 'absolute' : 'static')};\n transform: ${({ hide }) => (hide ? 'translateY(10px)' : 'none')};\n transition: transform 0.6s;\n transition-delay: ${({ transitionDelay }) =>\n transitionDelay ? `0.${transitionDelay}8s` : 'unset'};\n\n div {\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n font-weight: 500;\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n background-color: ${({ theme }) =>\n rgba(theme?.['-ds-core-400']?.value, 0.09)};\n border-radius: 4px;\n padding: 8px;\n }\n`\n\nconst MomentsWrapper = styled.div`\n display: flex;\n flex-wrap: wrap;\n flex-direction: row;\n gap: 8px;\n`\n\ninterface ReviewMomentsProps {\n moments: {\n slug: string\n name: string\n }[]\n showMore: boolean\n truncateLength: number\n}\n\nconst ReviewMoments = ({\n moments,\n showMore,\n truncateLength,\n}: ReviewMomentsProps) => {\n return (\n \n {moments.slice(0, truncateLength).map((item) => (\n \n {item.name}
\n \n ))}\n\n {moments.length > truncateLength && !showMore && (\n \n +{moments.length - truncateLength}
\n \n )}\n\n {moments.slice(truncateLength, moments.length).map((item, index) => (\n \n {item.name}
\n \n ))}\n \n )\n}\n\nexport default ReviewMoments\n","import React, { useState } from 'react'\nimport moment from 'moment'\nimport styled from 'styled-components'\n\nimport { media } from 'styles/media'\nimport Avatar from 'components/display/Avatar'\nimport LazyImage from 'components/display/LazyImage'\nimport ReviewContent from './ReviewContent'\nimport ReviewMoments from './ReviewMoments'\n\nexport const CONTENT_TRUNCATE = 300\nexport const MOMENTS_TRUNCATE = 6\n\ninterface CondensedProp {\n condensed?: boolean\n}\n\nexport const ReviewWrapper = styled.div`\n display: grid;\n gap: 16px;\n grid-template-columns: 64px 1fr;\n align-items: center;\n min-height: 176px;\n padding: 24px;\n background-color: ${({ theme }) => theme?.['-ds-neutral-200']?.value};\n border-radius: 8px;\n\n ${media.lg`\n align-items: ${({ condensed }) => (!condensed ? 'flex-start' : 'center')};\n gap: ${({ condensed }) => (!condensed ? '16px 32px' : '16px')};\n grid-template-columns: ${({ condensed }) =>\n !condensed ? '88px 1fr' : '64px 1fr'};\n `}\n`\n\nconst AvatarIcon = styled(Avatar)`\n width: 64px;\n height: 64px;\n\n ${media.lg`\n width: ${({ condensed }) => (!condensed ? '88px' : '64px')};\n height: ${({ condensed }) => (!condensed ? '88px' : '64px')};\n grid-row-start: ${({ condensed }) => (!condensed ? '1' : 'auto')};\n grid-row-end: ${({ condensed }) => (!condensed ? '3' : 'auto')};\n `}\n`\n\nconst AuthorName = styled.h4`\n font-size: ${({ theme, condensed }) =>\n !condensed\n ? theme?.['-ds-font-size-lg']?.['font-size']?.value\n : theme?.['-ds-font-size-md']?.['font-size']?.value};\n line-height: 1.4;\n margin-bottom: ${({ condensed }) => (!condensed ? '4px' : '0')};\n`\n\nconst Date = styled.div`\n color: ${({ theme }) => theme?.['-ds-neutral-600']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n font-weight: 500;\n`\n\nconst Content = styled.div`\n grid-column-start: 1;\n grid-column-end: 3;\n letter-spacing: 0.01em;\n\n ${media.lg`\n grid-column-start: ${({ condensed }) => (!condensed ? '2' : '1')};\n `}\n`\n\nconst ShowMoreButton = styled.button<{ open?: boolean }>`\n display: flex;\n width: 100%;\n justify-content: center;\n align-items: center;\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n font-weight: 500;\n background-color: transparent;\n border: none;\n color: ${({ theme }) => theme?.['-ds-core-400'].value};\n transition: color 0.3s;\n position: relative;\n grid-column-start: 1;\n grid-column-end: 3;\n margin-top: 16px;\n\n &:hover,\n &:focus {\n color: ${({ theme }) => theme?.['-ds-core-300'].value};\n }\n\n svg {\n margin-left: 16px;\n transform: ${({ open }) => (open ? 'rotate(180deg)' : 'none')};\n }\n`\n\ntype ReviewProps = {\n review: GQL_ListingReviewFragment\n condensed?: boolean\n}\n\nconst Review = ({\n review: { reviewer, createdAt, content, fulfillingMoments },\n condensed,\n}: ReviewProps) => {\n const [showMore, setShowMore] = useState(false)\n\n const hasShowMore =\n content.length > CONTENT_TRUNCATE ||\n fulfillingMoments.length > MOMENTS_TRUNCATE\n\n const handleClick = (e: React.MouseEvent) => {\n e.preventDefault()\n setShowMore(!showMore)\n }\n\n return (\n \n \n \n \n \n\n \n
{reviewer.firstName}\n
{moment(createdAt).format('D MMM YYYY')}\n
\n\n \n {content && (\n \n )}\n\n {fulfillingMoments && (\n \n )}\n \n\n {hasShowMore && (\n \n Show {!showMore ? 'more' : 'less'}\n \n \n )}\n \n )\n}\n\nexport default Review\n","import React from 'react'\nimport styled from 'styled-components'\nimport { getConnectionNodes } from 'utils/api'\n\nimport Spinner from 'components/display/Spinner'\nimport Review, { ReviewWrapper } from '../Review'\n\nconst ReviewListWrapper = styled.div`\n > div {\n margin-bottom: 16px;\n }\n`\nconst ReviewPlaceholder = styled(ReviewWrapper)`\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 40px;\n`\n\ninterface ReviewListProps {\n loading?: boolean\n reviewsConnection: GQL_ListingReviewFragment[]\n condensed?: boolean\n}\n\nconst ReviewList = ({\n loading,\n reviewsConnection,\n condensed,\n}: ReviewListProps) => (\n \n {loading && (\n \n \n \n )}\n\n {!loading &&\n getConnectionNodes(reviewsConnection).map((review) => (\n \n ))}\n \n)\n\nexport default ReviewList\n","import React from 'react'\nimport styled from 'styled-components'\nimport pluralize from 'pluralize'\n\nimport { formatPercentage } from 'components/utils/numbers'\nimport SvgIconHappy from 'components/icons/Happy'\nimport SvgIconIndifferent from 'components/icons/Indifferent'\nimport SvgIconUnhappy from 'components/icons/Unhappy'\n\ntype SizeProp = 'compact' | 'small' | 'medium' | 'large'\n\ninterface ReviewScoreProps {\n score: number | string\n size?: SizeProp\n handleShowReviews?: () => any\n count?: number\n}\n\nconst ReviewScoreContainer = styled.div<{ size?: SizeProp }>`\n display: flex;\n align-items: center;\n color: ${({ size, theme }) =>\n size === 'compact'\n ? theme?.['-ds-success-300']?.value\n : theme?.['-ds-core-400']?.value};\n font-weight: ${({ size }) => (size === 'compact' ? '500' : '300')};\n font-size: ${({ size, theme }) => {\n switch (size) {\n case 'compact':\n return theme?.['-ds-font-size-xxxs']?.['font-size']?.value\n case 'small':\n return theme?.['-ds-font-size-xxs']?.['font-size']?.value\n case 'medium':\n return theme?.['-ds-font-size-xs']?.['font-size']?.value\n case 'large':\n return theme?.['-ds-font-size-sm']?.['font-size']?.value\n default:\n return theme?.['-ds-font-size-xs']?.['font-size']?.value\n }\n }};\n letter-spacing: ${({ size }) => (size === 'compact' ? '0.08em' : '0.01em')};\n background-color: ${({ size, theme }) =>\n size === 'compact' ? theme?.['-ds-success-100']?.value : 'transparent'};\n padding: ${({ size }) => (size === 'compact' ? '5px 7px' : '0')};\n border-radius: ${({ size }) => (size === 'compact' ? '80px' : '0')};\n\n svg {\n color: inherit;\n margin-right: ${({ size }) => {\n switch (size) {\n case 'compact':\n case 'small':\n return '6px'\n case 'medium':\n return '10px'\n case 'large':\n return '16px'\n default:\n return '10px'\n }\n }};\n width: ${({ size }) => {\n switch (size) {\n case 'compact':\n case 'small':\n return '16px'\n case 'medium':\n return '24px'\n case 'large':\n return '30px'\n default:\n return '24px'\n }\n }};\n }\n`\n\nconst ReviewScoreButton = styled.span`\n margin-left: 5px;\n\n button {\n background-color: transparent;\n border: none;\n text-decoration: underline;\n text-underline-offset: 1px;\n text-decoration-thickness: 1px;\n margin-left: 5px;\n padding: 0;\n }\n`\n\nconst parseReviewScore = (score: number | string) => {\n if (!score || score === '') return null\n\n const scoreFloat = typeof score === 'string' ? parseFloat(score) : score\n\n if (Number.isNaN(scoreFloat)) return null\n\n return scoreFloat\n}\n\nconst ScoreIcon = ({ score }: { score: number }) => {\n if (score > 0.65) return \n if (score > 0.32) return \n if (score > 0) return \n return \n}\n\nconst ReviewScore = ({\n handleShowReviews,\n size,\n score,\n count,\n}: ReviewScoreProps) => {\n const parsedScore = parseReviewScore(score)\n\n if (!parsedScore || parsedScore <= 0) {\n return null\n }\n\n return (\n \n \n {formatPercentage(parsedScore)}\n {size !== 'compact' && ' Recommended'}\n\n {handleShowReviews && count > 0 && (\n <>\n \n •\n \n \n >\n )}\n \n )\n}\n\nexport default ReviewScore\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport get from 'lodash/get'\n\nimport {\n useGetListingReviewsQuery,\n useGetAdventureReviewsQuery,\n} from 'hooks/useQueries'\nimport { fetchMoreFromCollection } from 'utils/api'\n\nimport Button from 'components/display/Button'\nimport DialogModal from '../../display/DialogModal'\nimport ReviewsList from '../ReviewList'\nimport ReviewScore from '../ReviewScore'\n\nconst Header = styled.div`\n margin-bottom: 33px;\n h3 {\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xl']?.['font-size']?.value};\n margin: 0 0 9px 0;\n }\n`\n\ntype ReviewsModalProps = {\n reviewType: 'listing' | 'adventure'\n typeId: string\n isOpen: boolean\n onRequestClose(): void\n reviewScore: number | string\n}\n\nconst ReviewsModal = ({\n reviewType,\n typeId,\n reviewScore,\n isOpen,\n onRequestClose,\n}: ReviewsModalProps) => {\n const { loading, data, fetchMore } =\n reviewType === 'listing'\n ? useGetListingReviewsQuery({\n variables: {\n listingId: typeId,\n },\n })\n : useGetAdventureReviewsQuery({\n variables: {\n id: typeId,\n },\n })\n const reviewsConnection = get(data, `${reviewType}.reviews`)\n const hasNextPage = get(data, `${reviewType}.reviews.pageInfo.hasNextPage`)\n const handleFetchMore = () =>\n fetchMoreFromCollection(data, fetchMore, `${reviewType}.reviews`)\n\n return (\n \n \n\n \n\n {hasNextPage && (\n \n )}\n \n )\n}\n\nexport default ReviewsModal\n","import axios from 'axios'\nimport { parseNumber, formatNumber } from 'libphonenumber-js'\nimport noCatchFetcher from './utils/noCatchFetcher'\n\nexport function verifyPhoneNumber(phone_number) {\n const formattedPhoneNumber = formatNumber(parseNumber(phone_number), 'E.164')\n return (dispatch) =>\n dispatch({\n type: 'CURRENT_USER_PHONE_NUMBER_VERIFY',\n payload: axios.post('/user/phone_number_verifications', {\n phone_number: formattedPhoneNumber,\n }),\n })\n}\n\nexport function verifySMSCode(formValues) {\n const formattedPhoneNumber = formatNumber(\n parseNumber(formValues.phone_number),\n 'E.164'\n )\n return (dispatch) =>\n dispatch({\n type: 'CURRENT_USER_SMS_CODE_VERIFY',\n payload: noCatchFetcher.post('/user/phone_number_verifications/verify', {\n ...formValues,\n phone_number: formattedPhoneNumber,\n }),\n })\n}\n","import React from 'react'\nimport styled from 'styled-components'\nimport { Field, reduxForm, SubmissionError, change, reset } from 'redux-form'\nimport { connect } from 'react-redux'\n\nimport { fetchCurrentUserSilent } from '../../actions/authActions'\nimport {\n verifySMSCode,\n verifyPhoneNumber,\n} from '../../actions/phoneNumberActions'\n\nimport { Label, InputGroup, renderTextInput, renderError, Hint } from '../form'\n\nimport Button from '../display/Button'\nimport Spinner from '../display/Spinner'\nimport Overlay from '../display/Overlay'\n\nconst Wrapper = styled.div`\n position: relative;\n margin: 15px 0;\n padding: 30px;\n background-color: ${({ theme }) => theme.colors.grey};\n`\n\nconst FlexWrapper = styled.div`\n display: flex;\n flex-direction: column;\n`\n\nconst InputFlexButtons = styled.div`\n display: flex;\n flex: 1;\n margin: 8px -8px;\n\n button {\n flex: 1;\n margin: 0 8px;\n }\n`\n\nconst normalizeCode = (value) => {\n if (!value) return value\n const onlyNums = value.replace(/[^\\d]/g, '')\n return onlyNums.slice(0, 4)\n}\n\nclass PhoneVerification extends React.Component {\n handleResend = () => {\n const { dispatch, phoneNumber } = this.props\n\n // Clear any Error\n dispatch(reset('PhoneVerification'))\n\n dispatch(verifyPhoneNumber(phoneNumber))\n }\n\n handleKeyPressEnter = (e) => {\n const { handleSubmit } = this.props\n if (e.key === 'Enter') {\n e.preventDefault()\n handleSubmit()\n }\n }\n\n render() {\n const { auth, handleSubmit, roundedInputs } = this.props\n return (\n \n \n \n \n We’ve sent you a verification code via SMS. Enter it here to\n verify your mobile number.\n \n
\n \n \n \n \n \n \n \n \n \n\n {(auth.verifyingSMSCode || auth.verifyingPhoneNumber) && (\n \n \n \n )}\n \n )\n }\n}\n\nconst PhoneVerificationForm = reduxForm({\n form: 'PhoneVerification',\n // validate,\n})(PhoneVerification)\n\n// mapStateToProps\n// mapDispatchToProps\nexport default connect(\n ({ auth, ...state }) => ({\n auth,\n state,\n }),\n (dispatch, props) => ({\n onSubmit: (formValues) =>\n dispatch(\n verifySMSCode({ phone_number: props.phoneNumber, ...formValues })\n )\n .then(() => {\n dispatch(fetchCurrentUserSilent())\n dispatch(change('ListingYourProfile', 'phone_number_verified', true))\n })\n .catch(() => {\n throw new SubmissionError({\n code: 'Invalid SMS verification code.',\n })\n }),\n })\n)(PhoneVerificationForm)\n","import React from 'react'\nimport styled from 'styled-components'\nimport { connect } from 'react-redux'\nimport { Field, reduxForm, getFormValues, getFormSyncErrors } from 'redux-form'\n\nimport { validRequired } from '../form/validate'\nimport { verifyPhoneNumber } from '../../actions/phoneNumberActions'\n\nimport { Label, InputGroup, renderError, Warning } from '../form'\nimport PhoneNumberField, { validPhoneNumber } from '../form/PhoneNumberField'\n\nimport PhoneVerificationForm from './PhoneVerificationForm'\nimport Button from '../display/Button'\n\nconst FieldFlexWrapper = styled.div`\n margin: 0 -8px;\n margin-bottom: 8px;\n`\n\nconst FieldFlex = styled.div`\n margin: 8px;\n`\n\nclass MobilePhoneNumber extends React.Component {\n handleKeyPressEnter = (e) => {\n const { handleSubmit } = this.props\n if (e.key === 'Enter') {\n e.preventDefault()\n handleSubmit()\n }\n }\n\n render() {\n const {\n auth,\n invalid,\n currentUser,\n formValues,\n handleSubmit,\n dirty,\n noMargin,\n } = this.props\n\n const isPhoneNumberVerified = !dirty && currentUser?.phone_number_verified\n\n return (\n \n \n \n \n \n \n {!isPhoneNumberVerified && (\n \n \n \n )}\n \n {dirty && (\n \n You will have to verify this phone number to save it.\n \n )}\n \n \n
\n {!isPhoneNumberVerified && auth.phoneNumberVerificationSent && (\n \n )}\n \n )\n }\n}\n\nconst MobilePhoneNumberForm = reduxForm({\n form: 'MobilePhoneNumber',\n enableReinitialize: true,\n keepDirtyOnReinitialize: true,\n})(MobilePhoneNumber)\n\nexport default connect(\n ({ auth, ...state }) => ({\n updating: auth.updating,\n currentUser: auth.currentUser,\n initialValues: {\n phone_number: auth.currentUser && auth.currentUser.phone_number,\n },\n formValues: getFormValues('MobilePhoneNumber')(state),\n formSyncErrors: getFormSyncErrors('MobilePhoneNumber')(state),\n auth,\n state,\n }),\n (dispatch) => ({\n onSubmit: ({ phone_number }) => {\n dispatch(verifyPhoneNumber(phone_number))\n },\n })\n)(MobilePhoneNumberForm)\n","import React from 'react'\nimport { loadStripe } from '@stripe/stripe-js/pure'\nimport { Elements, useStripe } from '@stripe/react-stripe-js'\n\nimport { useGetUserCountryAndStripeKeyQuery } from 'hooks/useQueries'\nimport { dispatchRollbarError } from 'utils/rollbar'\n\n/*\n This pattern was suggested by a stripe engineer as a way to avoid calling loadStripe() until\n Stripe was required, and to do so only once, to improve performance:\n https://github.com/stripe/stripe-js/issues/43#issuecomment-643840075\n*/\n\n/*\n The Elements provider accepts null but not undefined for its `stripe` prop. So passing null until\n the user's API key is retrieved from the server and can be used to load the stripe instance.\n*/\nlet stripePromise: ReturnType = null\n\nconst getStripePromise = (key: string) => {\n if (!stripePromise && key) {\n stripePromise = loadStripe(key)\n }\n\n return stripePromise\n}\n\nconst LazyStripeElements: React.FC<{}> = ({ children }) => {\n const { data } = useGetUserCountryAndStripeKeyQuery({\n fetchPolicy: 'cache-and-network',\n onError: (error) => {\n dispatchRollbarError(`Failed to fetch stripe public key for user`, {\n originalError: error?.toString(),\n })\n },\n })\n\n const key = data?.currentUser?.defaultCountry?.stripePlatform?.publicKey\n\n return {children}\n}\n\ninterface WithStripeProp {\n stripe: ReturnType\n}\n\nexport const withStripe = >(\n Component: React.JSXElementConstructor
& WithStripeProp\n) => (props: P) => {\n const stripe = useStripe()\n\n return \n}\n\nexport default LazyStripeElements\n","/*\n This whole component needs attention, linting included.\n*/\n\n/* eslint-disable no-useless-constructor */\n/* eslint-disable no-unused-vars */\n/* eslint-disable no-unused-expressions */\n/* eslint-disable react/destructuring-assignment */\n/* eslint-disable react/forbid-prop-types */\n/* eslint-disable react/sort-comp */\n\nimport React from 'react'\nimport actioncable from 'actioncable'\nimport PropTypes from 'prop-types'\n\nexport class ActionCableProvider extends React.Component {\n constructor(props, context) {\n super(props, context)\n // this.displayName = 'ActionCableProvider'\n }\n\n getChildContext() {\n return {\n cable: this.cable,\n }\n }\n\n UNSAFE_componentWillMount() {\n if (this.props.cable) {\n this.cable = this.props.cable\n } else {\n this.cable = actioncable.createConsumer(this.props.url)\n }\n }\n\n UNSAFE_componentWillUnmount() {\n if (!this.props.cable && this.cable) {\n this.cable.disconnect()\n }\n }\n\n UNSAFE_componentWillReceiveProps(nextProps) {\n // Props not changed\n if (\n this.props.cable === nextProps.cable &&\n this.props.url === nextProps.url\n ) {\n return\n }\n\n // cable is created by self, disconnect it\n this.componentWillUnmount()\n\n // create or assign cable\n this.componentWillMount()\n }\n\n render() {\n return this.props.children\n }\n}\n\nActionCableProvider.propTypes = {\n cable: PropTypes.object,\n url: PropTypes.string,\n children: PropTypes.any,\n}\n\nActionCableProvider.childContextTypes = {\n cable: PropTypes.object.isRequired,\n}\n\nActionCableProvider.displayName = 'ActionCableProvider'\n\nexport class ActionCable extends React.Component {\n constructor(props, context) {\n super(props, context)\n }\n\n componentDidMount() {\n const self = this\n const _props = this.props\n const onReceived = _props.onReceived\n const onInitialized = _props.onInitialized\n const onConnected = _props.onConnected\n const onDisconnected = _props.onDisconnected\n const onRejected = _props.onRejected\n this.cable = this.context.cable.subscriptions.create(this.props.channel, {\n received(data) {\n onReceived && onReceived(data)\n },\n initialized() {\n onInitialized && onInitialized()\n },\n connected() {\n onConnected && onConnected()\n },\n disconnect() {\n onDisconnected && onDisconnected()\n },\n rejected() {\n onRejected && onRejected()\n },\n })\n }\n\n componentWillUnmount() {\n if (this.cable) {\n this.context.cable.subscriptions.remove(this.cable)\n this.cable = null\n }\n }\n\n send(data) {\n if (!this.cable) {\n throw new Error('ActionCable component unloaded')\n }\n\n return this.cable.send(data)\n }\n\n perform(action, data) {\n if (!this.cable) {\n throw new Error('ActionCable component unloaded')\n }\n\n return this.cable.perform(action, data)\n }\n\n render() {\n return null\n }\n}\n\nActionCable.displayName = 'ActionCable'\n\nActionCable.propTypes = {\n onReceived: PropTypes.func,\n onInitialized: PropTypes.func,\n onConnected: PropTypes.func,\n onDisconnected: PropTypes.func,\n onRejected: PropTypes.func,\n}\nActionCable.contextTypes = {\n cable: PropTypes.object.isRequired,\n}\n","import { createGlobalStyle } from 'styled-components'\n\nconst DisableScrollAnchoring = createGlobalStyle`\n body {\n overflow-anchor: none;\n }\n`\n\nexport default DisableScrollAnchoring\n","import React from 'react'\nimport { useTrackVisibility } from 'react-intersection-observer-hook'\n\ntype Props = {\n /**\n * root margin as per IntersectionObserver API:\n * https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#how_intersection_is_calculated\n */\n rootMargin: string\n placeholder: React.ReactNode\n}\n\nconst RenderOnlyWhenVisbile: React.FC = ({\n children,\n rootMargin,\n placeholder,\n}) => {\n const [ref, { isVisible, wasEverVisible }] = useTrackVisibility({\n rootMargin,\n })\n\n const renderPlaceholder = isVisible !== true && wasEverVisible === true\n\n return (\n \n {renderPlaceholder ? <>{placeholder}> : <>{children}>}\n
\n )\n}\n\nexport default RenderOnlyWhenVisbile\n","import { useEffect } from 'react'\nimport { withRouter } from 'react-router-dom'\n\nconst ScrollTop = ({ children, location: { pathname } }) => {\n useEffect(() => {\n window.scrollTo(0, 0)\n }, [pathname])\n\n return children || null\n}\n\nexport default withRouter(ScrollTop)\n","import React, { useEffect } from 'react'\nimport { useTrackVisibility } from 'react-intersection-observer-hook'\n\ntype TrackVisibilityProps = {\n onChange: (isVisible: boolean) => any\n options?: Parameters[0]\n}\n\nconst TrackVisibility: React.FC = ({\n onChange,\n options,\n children,\n}) => {\n const [ref, { isVisible }] = useTrackVisibility(options)\n\n useEffect(() => {\n onChange(isVisible)\n }, [onChange, isVisible])\n\n return {children}
\n}\n\nexport default TrackVisibility\n","/**\n * Move element inside an array, return a new array\n * @param array Array to rearrange\n * @param from Current index of the element\n * @param to Destination index of the element\n */\n\nexport const arrayMove = (array: any[], from: number, to: number): any[] => {\n const arr = array.slice()\n arr.splice(to < 0 ? arr.length + to : to, 0, arr.splice(from, 1)[0])\n return arr\n}\n\nexport default arrayMove\n\nconst splicer = (array: any[], element: any, index: number) => {\n const nextArray = [...array]\n nextArray.splice(index * 2, 0, element)\n return nextArray\n}\n\n/**\n * Combine two arrays into one with their elements in alternating order:\n *\n * ['a', 'b'], [1, 2] => ['a', 1, 'b', 2]\n */\nexport const weave = (array1: any[], array2: any[]) => {\n return array1.reduce(splicer, array2.slice())\n}\n","export const refundNotice = (policy: string) => {\n if (policy === 'strict_partial') return '2 weeks'\n if (policy === 'strict_30') return '30 days'\n if (policy === 'strict_60') return '60 days'\n return '1 week'\n}\n\nexport const refundAmount = (policy: string) => {\n const fullPolicies = ['full', 'strict_30', 'strict_60']\n if (fullPolicies.includes(policy)) return 'full'\n return '50%'\n}\n","import moment from 'moment'\n\nexport const isoDateString = (value) => value.format('YYYY-MM-DD')\n\nexport const numberOfDaysUntil = (date) =>\n Math.max(0, moment(date).startOf('day').diff(moment().startOf('day'), 'days'))\n\nexport const shortTimeString = (value) => {\n const time = moment(value, 'HH:mm')\n if (time.minutes() === 0) {\n return time.format('ha')\n }\n return time.format('h:mma')\n}\n\nexport const shortTimeRangeString = (start, end) =>\n `${shortTimeString(start)} – ${shortTimeString(end)}`\n","export const isTouchDevice = () =>\n 'ontouchstart' in window ||\n navigator.MaxTouchPoints > 0 ||\n navigator.msMaxTouchPoints > 0\n","import { normalizeKeys } from './propsUtils'\n\nexport const isListingType = (listingData, slug) => {\n const listing = normalizeKeys(listingData)\n return listing && listing.listingType && listing.listingType.slug === slug\n}\n\nexport const isAccommodation = (listing) =>\n isListingType(listing, 'accommodation')\n\nexport const isEquipment = (listing) => isListingType(listing, 'equipment')\n\nexport const isExperience = (listing) => isListingType(listing, 'experiences')\n\nexport const isMotorVehicle = (listing) =>\n isListingType(listing, 'motor-vehicle')\n\nexport const hasProperty = (listing, key) =>\n ({}.hasOwnProperty.call(listing, key))\n\nexport const amenitiesForListingType = (listingData, listingFieldsData) => {\n if (!listingData || !listingFieldsData) {\n return null\n }\n\n const listing = normalizeKeys(listingData)\n const listingFields = normalizeKeys(listingFieldsData)\n\n const listingType = listingFields.listingTypes.find(\n (t) => t.slug === listing.listingType.slug\n )\n return listingType.amenities\n}\n\nexport const isOnAirBnb = (listing) => listing && listing.on_airbnb\n\nexport const adventureTypeIdToSlug = (adventureTypes, id) => {\n // eslint-disable-next-line eqeqeq\n const type = adventureTypes.find((t) => t.id == id)\n if (type) return type.slug\n return ''\n}\n\nexport const isListingStatus = (listing, status) =>\n listing && listing.status === status\n\nexport const isPublished = (listing) => isListingStatus(listing, 'published')\n","export const formatPercentage = (number) => `${Math.round(number * 100)}%`\n\nexport const onlyNums = (value) => value.replace(/[^\\d]/g, '')\n\nexport const formatNumber = (value) =>\n String(value).replace(/(.)(?=(\\d{3})+$)/g, '$1,')\n\nexport default formatPercentage\n","import { accounting } from 'accounting'\n\nexport const unformat = (value) => {\n if (!value) return value\n\n return accounting.unformat(value)\n}\n\nexport const formatPrice = (value, precision = value % 1 === 0 ? 0 : 2) => {\n // eslint-disable-next-line no-restricted-globals\n if (isNaN(value)) return value\n\n return accounting.formatMoney(unformat(value), { precision })\n}\n\nexport const formatPriceAsNumber = (\n value,\n precision = value % 1 === 0 ? 0 : 2\n) => {\n // eslint-disable-next-line no-restricted-globals\n if (isNaN(value)) return value\n\n return accounting.formatNumber(unformat(value), { precision })\n}\n\nexport const numberBetween = (min, max) => (value, previousValue) => {\n const parsedVal = parseFloat(value)\n return parsedVal >= min && parsedVal <= max ? value : previousValue\n}\n","import mapKeys from 'lodash/mapKeys'\nimport mapValues from 'lodash/mapValues'\nimport isObject from 'lodash/isObject'\nimport isArray from 'lodash/isArray'\nimport camelCase from 'lodash/camelCase'\nimport snakeCase from 'lodash/snakeCase'\n\ntype MapKeysDeep = (obj: object, cb: (v: string, k: string) => string) => object\n\nconst mapKeysDeep: MapKeysDeep = (obj, cb) => {\n if (isArray(obj)) {\n return obj.map((innerObj) => mapKeysDeep(innerObj, cb))\n }\n if (isObject(obj)) {\n return mapValues(mapKeys(obj, cb), (val) => mapKeysDeep(val, cb))\n }\n return obj\n}\n\n/**\n * Transform an object's keys to camelCase\n * @param props The object to transform\n */\nexport const normalizeKeys = (props: object): object =>\n props && mapKeysDeep(props, (v: string, k: string): string => camelCase(k))\n\n/**\n * Transform an object's keys to snake_case\n * @param props The object to transform\n */\nexport const snakeCaseKeys = (props: object): object =>\n props && mapKeysDeep(props, (v: string, k: string): string => snakeCase(k))\n\nexport default normalizeKeys\n","import { formatPercentage } from './numbers'\n\nexport const parseServiceRate = (rate: string) => {\n try {\n const decimal = parseFloat(rate)\n\n if (Number.isNaN(decimal)) {\n return undefined\n }\n\n return decimal\n } catch (error) {\n return undefined\n }\n}\n\nconst serviceRateToPercentage = (rate: string) => {\n if (!rate) {\n return undefined\n }\n\n const decimal = parseServiceRate(rate)\n\n if (!decimal) {\n return undefined\n }\n\n return formatPercentage(decimal)\n}\n\nexport default serviceRateToPercentage\n","import startCase from 'lodash/startCase'\nimport toLower from 'lodash/toLower'\n\nexport function slugToNice(slug, cap = false) {\n let string = slug\n if (slug === 'extra_person_fee') {\n string = slug.replace('person', 'people')\n }\n\n return (\n string &&\n string\n .split('_')\n .map((word, wordIndex) =>\n word\n .split('')\n .map((letter, index) =>\n wordIndex === 0 && index === 0 && cap\n ? letter.toUpperCase()\n : letter\n )\n .join('')\n )\n .join(' ')\n )\n}\n\nexport function capitalize(word) {\n return word\n .split('')\n .map((letter, index) => (index === 0 ? letter.toUpperCase() : letter))\n .join('')\n}\n\nexport function camelize(slug) {\n return slug\n .split('-')\n .map((word) =>\n word\n .split('')\n .map((letter, index) => (index === 0 ? letter.toUpperCase() : letter))\n .join('')\n )\n .join('')\n}\n\nexport const titleCase = (str) => startCase(toLower(str))\n\nexport default slugToNice\n","import { useTranslation } from 'react-i18next'\n\ntype Options = {\n yearFormat: 'YYYY' | 'YY'\n}\n\nexport const dateFormatForLanguage = (language: string, options?: Options) => {\n const yearFormat = options?.yearFormat || 'YYYY'\n\n const dateFormat = language.toLowerCase().includes('us') ? 'MM/DD' : 'DD/MM'\n\n return `${dateFormat}/${yearFormat}`\n}\n\nconst useDateDisplayFormat = (options?: Options) => {\n const [, { resolvedLanguage }] = useTranslation()\n\n return dateFormatForLanguage(resolvedLanguage, options)\n}\n\nexport default useDateDisplayFormat\n","import React, { useEffect, useState } from 'react'\n\nconst withRenderClientsideOnly = (\n Component: React.ComponentType
\n) => (props: P) => {\n const [show, setShowChildren] = useState(false)\n\n // delay showing component until after the client side JS loads and hydrates the component\n // works because useEffect will not run in SSR\n useEffect(() => {\n setShowChildren(true)\n }, [])\n\n if (!show) {\n return null\n }\n\n return \n}\n\nexport default withRenderClientsideOnly\n","import React from 'react'\n\nconst DescendantOfMapContext = React.createContext(false)\n\nexport default DescendantOfMapContext\n","import React, { createContext, useContext, useMemo } from 'react'\nimport useMedia from 'use-media'\n\nimport { breakpoints } from 'styles/media'\n\ntype MediaQueriesMatches = {\n [key in keyof typeof breakpoints]: boolean\n}\n\nexport const MediaQueryContext = createContext(null)\n\nconst mediaQueries = {\n giant: `(min-width: ${1250}px)`,\n desktop: `(min-width: ${1080}px)`,\n tablet: `(min-width: ${768}px)`,\n phone: `(min-width: ${450}px)`,\n phoneMd: `(min-width: ${375}px)`,\n sm: `(min-width: ${576}px)`,\n md: `(min-width: ${768}px)`,\n lg: `(min-width: ${992}px)`,\n xl: `(min-width: ${1200}px)`,\n xxl: `(min-width: ${1400}px)`,\n xxxl: `(min-width: ${1600}px)`,\n xwide: `(min-width: ${1920}px)`,\n}\n\nexport const MediaQueryProvider: React.FC = ({ children }) => {\n const giant = useMedia(mediaQueries.giant)\n const desktop = useMedia(mediaQueries.desktop)\n const tablet = useMedia(mediaQueries.tablet)\n const phone = useMedia(mediaQueries.phone)\n const phoneMd = useMedia(mediaQueries.phoneMd)\n const sm = useMedia(mediaQueries.sm)\n const md = useMedia(mediaQueries.md)\n const lg = useMedia(mediaQueries.lg)\n const xl = useMedia(mediaQueries.xl)\n const xxl = useMedia(mediaQueries.xxl)\n const xxxl = useMedia(mediaQueries.xxxl)\n const xwide = useMedia(mediaQueries.xwide)\n\n const value = useMemo(\n () => ({\n giant,\n desktop,\n tablet,\n phone,\n phoneMd,\n sm,\n md,\n lg,\n xl,\n xxl,\n xxxl,\n xwide,\n }),\n [giant, desktop, tablet, phone, phoneMd, sm, md, lg, xl, xxl, xxxl, xwide]\n )\n\n return (\n \n {children}\n \n )\n}\n\nconst defaultMockValues = {\n giant: true,\n desktop: true,\n tablet: true,\n phone: true,\n phoneMd: true,\n sm: true,\n md: true,\n lg: true,\n xl: true,\n xxl: true,\n xxxl: true,\n xwide: true,\n} as const\n\nexport const mockValuesMobile: MediaQueriesMatches = {\n giant: false,\n desktop: false,\n tablet: false,\n phone: true,\n phoneMd: true,\n sm: true,\n md: false,\n lg: false,\n xl: false,\n xxl: false,\n xxxl: false,\n xwide: false,\n} as const\n\nexport const MockMediaQueryProvider: React.FC<{\n value?: MediaQueriesMatches\n}> = ({ value = defaultMockValues, children }) => {\n return (\n \n {children}\n \n )\n}\n\nexport const useMediaQueryContext = () => useContext(MediaQueryContext)\n","import React from 'react'\n\nexport interface RailsContextInterface {\n // maybe type because the values get injected after context creation\n env?: {\n REACT_APP_GOOGLE_MAPS_API_KEY: string\n REACT_APP_RECAPTCHA_KEY: string\n }\n railsEnv?: 'test' | 'development' | 'production'\n serverSide?: boolean\n location?: string\n embedded?: boolean\n}\n\nconst RailsContext: React.Context = React.createContext(\n {}\n)\n\nexport default RailsContext\n","import React from 'react'\n\nconst ServerSideContext = React.createContext(true)\n\nexport default ServerSideContext\n","import React from 'react'\n\nconst TouchDeviceContext = React.createContext(true)\n\nexport default TouchDeviceContext\n","import React, { useCallback, useContext } from 'react'\n\nimport ButtonSmall from '../../../components/display/Button/Small'\n\nimport { BookingItineraryContext } from './contexts/BookingItineraryContext'\nimport { isAdventureInItinerary } from '../utils'\n\nconst AddRemoveButton = ({\n adventureId,\n addText = 'Add',\n removeText = 'Remove',\n ...props\n}) => {\n const {\n bookingAdventures,\n handleAddAdventureToBooking,\n handleRemoveAdventureFromBooking,\n } = useContext(BookingItineraryContext)\n\n const handleAdd = useCallback(\n () => handleAddAdventureToBooking(adventureId),\n [adventureId, handleAddAdventureToBooking]\n )\n\n const handleRemove = useCallback(\n () => handleRemoveAdventureFromBooking(adventureId),\n [adventureId, handleRemoveAdventureFromBooking]\n )\n\n return isAdventureInItinerary(bookingAdventures, adventureId) ? (\n \n {removeText}\n \n ) : (\n \n {addText}\n \n )\n}\n\nexport default React.memo(AddRemoveButton)\n","import React, { FunctionComponent, useCallback } from 'react'\n\nimport useDispatch from 'hooks/useDispatch'\nimport {\n AdventureCardFragmentFragmentDoc,\n GetBookingAdventuresQueryResult,\n GetBookingAdventuresDocument,\n useAddAdventureToBookingMutation,\n useGetBookingAdventuresQuery,\n useRemoveAdventureFromBookingMutation,\n} from '../../../../hooks/useQueries'\n\nimport { sendNotification } from '../../../../actions/notificationActions'\n\nexport const BookingItineraryContext = React.createContext<{\n bookingAdventures: GetBookingAdventuresQueryResult['data']['booking']['adventures']\n handleAddAdventureToBooking: (adventureId: string) => any\n handleRemoveAdventureFromBooking: (adventureId: string) => any\n}>({\n bookingAdventures: undefined,\n handleAddAdventureToBooking: undefined,\n handleRemoveAdventureFromBooking: undefined,\n})\n\ninterface BookingItineraryProviderProps {\n bookingId: string\n onUpdate?: () => any\n analyticsSource: string\n}\n\nconst BookingItineraryProvider: FunctionComponent = ({\n bookingId,\n onUpdate,\n children,\n analyticsSource: source,\n}) => {\n const dispatch = useDispatch()\n const { data } = useGetBookingAdventuresQuery({\n variables: { bookingId },\n })\n const bookingAdventures = data?.booking?.adventures\n\n const [addAdventureToBooking] = useAddAdventureToBookingMutation()\n const handleAddAdventureToBooking = useCallback(\n (adventureId: string) =>\n addAdventureToBooking({\n variables: {\n bookingId,\n adventureId,\n source,\n },\n optimisticResponse: {\n createBookingAdventure: {\n __typename: 'CreateBookingAdventurePayload',\n adventure: {\n __typename: 'StoryAdventure',\n id: adventureId,\n },\n },\n },\n update(cache, mutationRes) {\n const addedAdventureId =\n mutationRes.data.createBookingAdventure.adventure.id\n\n const adventureFragment = cache.readFragment<\n GQL_AdventureCardFragmentFragment\n >({\n fragment: AdventureCardFragmentFragmentDoc,\n id: `StoryAdventure:${addedAdventureId}`,\n })\n\n // Using writeFragment instead of readFragment because the former returns a reference to the cache object,\n // rather than the object itself. The field we are updating in cache contains references.\n const adventureFragmentRef = cache.writeFragment({\n fragment: AdventureCardFragmentFragmentDoc,\n id: `StoryAdventure:${addedAdventureId}`,\n data: adventureFragment,\n })\n\n cache.modify({\n id: cache.identify({\n __typename: 'Booking',\n id: bookingId,\n }),\n fields: {\n adventures(cachedAdventures = []) {\n return [...cachedAdventures, adventureFragmentRef]\n },\n },\n })\n },\n }).then(() => {\n if (onUpdate) onUpdate()\n dispatch(sendNotification(`Added to your itinerary!`))\n }),\n [bookingId, bookingAdventures, onUpdate, addAdventureToBooking]\n )\n\n const [removeAdventureFromBooking] = useRemoveAdventureFromBookingMutation()\n\n const handleRemoveAdventureFromBooking = useCallback(\n (adventureId: string) =>\n removeAdventureFromBooking({\n variables: {\n bookingId,\n adventureId,\n },\n optimisticResponse: {\n destroyBookingAdventure: {\n __typename: 'DestroyBookingAdventurePayload',\n adventures: bookingAdventures.filter(\n (adventure) => adventure.id !== adventureId\n ),\n },\n },\n update(cache) {\n cache.writeQuery({\n query: GetBookingAdventuresDocument,\n data: {\n booking: {\n __typename: 'Booking',\n id: bookingId,\n adventures: bookingAdventures.filter(\n (adventure) => adventure.id !== adventureId\n ),\n },\n },\n })\n },\n }).then(() => {\n if (onUpdate) onUpdate()\n dispatch(sendNotification(`Removed from your itinerary!`))\n }),\n [bookingId, bookingAdventures, onUpdate, removeAdventureFromBooking]\n )\n\n const value = {\n bookingAdventures,\n handleAddAdventureToBooking,\n handleRemoveAdventureFromBooking,\n }\n\n return (\n \n {children}\n \n )\n}\n\nexport const BookingItineraryConsumer = BookingItineraryContext.Consumer\nexport default BookingItineraryProvider\n","import map from 'lodash/fp/map'\nimport flow from 'lodash/fp/flow'\nimport indexOf from 'lodash/fp/indexOf'\nimport { RootState } from 'typedRedux/configureStoreWithHistory'\n\nexport const isAdventureInItinerary = (\n adventures: {\n id: string\n }[],\n adventureId: string\n) => flow(map('id'), indexOf(adventureId))(adventures) > -1\n\nexport const getPricingAdjustmentData = (\n changeRequest: RootState['changeRequest']['data']\n) => {\n if (!changeRequest) return null\n if (!changeRequest.changed?.length) return null // Do not show adjustment if nothing has changed\n\n return {\n originalPrice: changeRequest?.original_price,\n newPrice: changeRequest.new_price,\n totalPaid: changeRequest.total_paid,\n deferredPaymentEligible: changeRequest.deferred_payment_eligible,\n dueNowAmount: changeRequest.due_now_amount,\n dueOnAmount: changeRequest.due_on_amount,\n dueOnDate: changeRequest.due_on_date,\n refundAmount: changeRequest.calculated_refund?.total_refund,\n voucherRefundAmount: changeRequest.calculated_refund?.voucher_refund_amount,\n }\n}\n","import cloneDeep from 'lodash/cloneDeep'\nimport {\n MutationUpdaterFunction,\n DefaultContext,\n ApolloCache,\n} from '@apollo/client'\n\nimport { GetBucketListItemsIndexDocument } from '../../../hooks/useQueries'\n\nexport type BucketListHandlerInput = {\n itemId: string\n itemType: GQL_Searchable\n bucketListId: string\n}\n\nexport const makeItemKey = ({\n itemId,\n itemType,\n}: Pick): string => {\n switch (itemType) {\n case 'Adventure':\n case 'Listing':\n case 'Story':\n return `${itemType}:${itemId}`\n default:\n throw new Error(`Unexpected itemType ${itemType} received`)\n }\n}\n\nexport const mapGQLTypenameToGQLSearchable = (\n typename:\n | GQL_StoryAdventure['__typename']\n | GQL_ListingAdventure['__typename']\n | GQL_Story['__typename']\n | GQL_Listing['__typename']\n): GQL_Searchable => {\n switch (typename) {\n case 'StoryAdventure':\n case 'ListingAdventure':\n return 'Adventure'\n case 'Story':\n return 'Story'\n case 'Listing':\n return 'Listing'\n default:\n throw new Error(`Unhandled search result with __typename: ${typename}`)\n }\n}\n\ntype MutationReturnBucketListItem =\n | 'Listing'\n | 'Story'\n | 'StoryAdventure'\n | 'ListingAdventure'\n\ntype BuildUpdateFnArgs = {\n itemId: string\n itemType: GQL_Searchable\n bucketListId: string\n}\n\nconst buildAddToBucketListMutationUpdateFn = ({\n itemId,\n itemType,\n bucketListId,\n}: BuildUpdateFnArgs): MutationUpdaterFunction<\n GQL_AddToBucketListMutation,\n Exact<{\n bucketListId: string\n itemId: string\n itemType: GQL_Searchable\n source: string\n }>,\n DefaultContext,\n ApolloCache\n> => (cache) => {\n const prevData = cache.readQuery({\n query: GetBucketListItemsIndexDocument,\n })\n\n const nextData = cloneDeep(prevData)\n\n const itemKey = makeItemKey({ itemId, itemType })\n\n cache.writeQuery({\n query: GetBucketListItemsIndexDocument,\n data: {\n ...nextData,\n currentUser: {\n ...(nextData?.currentUser || {}),\n bucketListItemsIndex: {\n ...(nextData?.currentUser?.bucketListItemsIndex || {}),\n [itemKey]: [\n ...(nextData?.currentUser?.bucketListItemsIndex?.[itemKey] || []),\n bucketListId,\n ],\n },\n },\n },\n })\n}\n\nconst buildRemoveFromBucketListMutationUpdateFn = ({\n itemId,\n itemType,\n bucketListId,\n}: BuildUpdateFnArgs): MutationUpdaterFunction<\n GQL_RemoveFromBucketListMutation,\n Exact<{\n bucketListId: string\n itemId: string\n itemType: GQL_Searchable\n source: string\n }>,\n DefaultContext,\n ApolloCache\n> => (cache) => {\n const prevData = cache.readQuery({\n query: GetBucketListItemsIndexDocument,\n })\n\n const nextData = cloneDeep(prevData)\n\n const itemKey = makeItemKey({ itemId, itemType })\n\n cache.writeQuery({\n query: GetBucketListItemsIndexDocument,\n data: {\n ...nextData,\n currentUser: {\n ...(nextData?.currentUser || {}),\n bucketListItemsIndex: {\n ...(nextData?.currentUser?.bucketListItemsIndex || {}),\n [itemKey]: [\n ...(nextData?.currentUser?.bucketListItemsIndex?.[itemKey]?.filter(\n (id: string) => id !== bucketListId\n ) || []),\n ],\n },\n },\n },\n })\n}\n\nconst buildAddToBucketListOptimisticResponse = ({\n itemId,\n itemType,\n}: BuildUpdateFnArgs) =>\n ({\n __typename: 'Mutation',\n addToBucketList: {\n __typename: 'AddToBucketListPayload',\n bucketListItem: {\n __typename: 'BucketListItem',\n item: {\n __typename: itemType as MutationReturnBucketListItem,\n id: itemId,\n },\n },\n },\n } as const)\n\nconst buildRemoveFromBucketListOptimisticResponse = ({\n itemId,\n itemType,\n}: BuildUpdateFnArgs) =>\n ({\n __typename: 'Mutation',\n removeFromBucketList: {\n __typename: 'RemoveFromBucketListPayload',\n bucketListItem: {\n __typename: 'BucketListItem',\n item: {\n __typename: itemType as MutationReturnBucketListItem,\n id: itemId,\n },\n },\n },\n } as const)\n\n/*\n For mutations to add/remove items to/from bucket lists, specifying both an optimisticResponse and update\n function ensures that:\n\n 1) The bucket list items index in the apollo cache is updated correctly following the mutation, so UI can update\n 2) This happens immediately on user input (i.e. before server responds)\n\n As per apollo docs, the update function in this case is called twice: once for the optimistic response, and once\n for the actual response from the server.\n*/\n\nexport const buildMutationOptionsAddToBucketList = ({\n itemId,\n itemType,\n bucketListId,\n}: BuildUpdateFnArgs) => ({\n update: buildAddToBucketListMutationUpdateFn({\n itemId,\n itemType,\n bucketListId,\n }),\n optimisticResponse: buildAddToBucketListOptimisticResponse({\n itemId,\n itemType,\n bucketListId,\n }),\n})\n\nexport const buildMutationOptionsRemoveFromBucketList = ({\n itemId,\n itemType,\n bucketListId,\n}: BuildUpdateFnArgs) => ({\n update: buildRemoveFromBucketListMutationUpdateFn({\n itemId,\n itemType,\n bucketListId,\n }),\n optimisticResponse: buildRemoveFromBucketListOptimisticResponse({\n itemId,\n itemType,\n bucketListId,\n }),\n})\n","/* eslint-disable no-param-reassign */\nimport axios from 'axios'\nimport { createAsyncThunk, createSlice } from '@reduxjs/toolkit'\n\nimport type { FetchStatusCommon } from '../../../restApi/types'\nimport type { RestEditListingFormData } from './useFormCompletionEndpoint'\n\ntype AxiosData = { data: RestEditListingFormData }\ntype RejectError = Error\ntype ListingId = string\ntype ThunkAPI = {\n rejectValue: RejectError\n}\n\nexport const fetchFormCompletionData = createAsyncThunk<\n AxiosData,\n ListingId,\n ThunkAPI\n>('MY_LISTING_FORM_COMPLETION_FETCH', async (listingId) => {\n try {\n const payload = await axios.get(\n `/user/listings/${listingId}/forms`\n )\n return payload\n } catch (error) {\n return error\n }\n})\n\ntype FormCompletionState = FetchStatusCommon & {\n data: RestEditListingFormData\n}\n\nconst initialState: FormCompletionState = {\n data: [],\n fetching: false,\n fetched: false,\n updating: false,\n updated: false,\n submitting: false,\n error: null,\n}\n\nexport const formCompletionSlice = createSlice({\n name: 'myListingFormCompletion',\n initialState,\n reducers: {},\n extraReducers: (builder) => {\n builder.addCase(fetchFormCompletionData.pending, (state) => {\n state.fetching = true\n })\n\n builder.addCase(fetchFormCompletionData.rejected, (state, action) => {\n state.error = action.payload\n state.fetching = false\n })\n\n builder.addCase(fetchFormCompletionData.fulfilled, (state, action) => {\n state.data = action.payload.data\n state.fetched = true\n state.fetching = false\n })\n },\n})\n\nexport default formCompletionSlice.reducer\n","export const promotionBanner = 'promotion_banner'\n\nexport const simplifiedCardTitle = 'simplified_card_title'\n\nexport const inviteTravelCrew = 'invite_travel_crew'\n","const dateOptions = {\n day: 'numeric',\n month: 'short',\n} as const\n\nexport default function formatDateRange(\n startDate: string,\n endDate: string,\n options: Intl.DateTimeFormatOptions = dateOptions\n) {\n const formattedStart = new Date(startDate).toLocaleDateString('en', options)\n const formattedEnd = new Date(endDate).toLocaleDateString('en', options)\n\n return `${formattedStart} - ${formattedEnd}`\n}\n","export const isServer = !(\n typeof window !== 'undefined' &&\n window.document &&\n window.document.createElement &&\n window.document.addEventListener\n)\n\nexport const isClient = !isServer\n\nexport const renderNull = () => null\n","/* eslint-disable @typescript-eslint/no-unused-vars */\nimport { isClient } from '../../components/utils/envUtils'\n\nlet enableBodyScroll = (_: Element) => ({})\nlet disableBodyScroll = (_: Element) => ({})\nlet clearAllBodyScrollLocks = () => ({})\n\nif (isClient) {\n // eslint-disable-next-line global-require\n const bodyScrollLock = require('body-scroll-lock')\n enableBodyScroll = bodyScrollLock.enableBodyScroll\n disableBodyScroll = bodyScrollLock.disableBodyScroll\n clearAllBodyScrollLocks = bodyScrollLock.clearAllBodyScrollLocks\n}\n\nconst useBodyScrollLock = () => {\n return {\n enableBodyScroll,\n disableBodyScroll,\n clearAllBodyScrollLocks,\n }\n}\n\nexport default useBodyScrollLock\n","import { useDispatch } from 'react-redux'\n\nimport configureStore from '../typedRedux/configureStoreWithHistory'\n\ntype AppDispatch = ReturnType['store']['dispatch']\n\nconst useTypedDispatch = () => useDispatch()\n\nexport default useTypedDispatch\n","import { useEffect } from 'react'\n\nconst useDocumentClick = (onClick: EventListenerOrEventListenerObject) => {\n useEffect(() => {\n document.addEventListener('click', onClick, { capture: true })\n\n return () => {\n document.removeEventListener('click', onClick, { capture: true })\n }\n }, [onClick])\n}\n\nexport default useDocumentClick\n","import { useMemo } from 'react'\n\nimport useReduxSelector from './useReduxSelector'\n\nconst useFeatureFlag = (flag: string) => {\n const data = useReduxSelector((state) => state.featureFlags.data)\n\n const featureFlags = data || []\n\n const hasFeatureFlag = useMemo(() => featureFlags.indexOf(flag) > -1, [\n flag,\n featureFlags,\n ])\n return hasFeatureFlag\n}\n\nexport default useFeatureFlag\n","import { useEffect, useRef, useState } from 'react'\n\ntype OnLoadCallback = () => void\n\n/**\n * Google Maps api script loading is deferred, which means our react app and\n * its component may load and mount before the google maps api is available\n * under the `google` global variable. This hooks returns a ref with a boolean\n * value reflecting whether the google script has loaded yet or not.\n */\n\nconst useGoogleMapsScriptLoadedRef = (onLoad?: OnLoadCallback) => {\n const loaded = useRef(false)\n\n if (window.google) {\n loaded.current = true\n if (onLoad) {\n onLoad()\n }\n }\n\n const onLoadListener = () => {\n loaded.current = true\n if (onLoad) {\n onLoad()\n }\n }\n\n useEffect(() => {\n if (loaded.current !== true) {\n // this ID attribute is set in application.html.slim\n const googleScript = document.getElementById('google-maps-script')\n googleScript.addEventListener('load', onLoadListener)\n }\n\n return () => {\n const googleScript = document.getElementById('google-maps-script')\n googleScript.removeEventListener('load', onLoadListener)\n }\n }, [])\n\n return loaded\n}\n\nexport const useGoogleMapsScriptReady = () => {\n const loadedRef = useGoogleMapsScriptLoadedRef()\n const [ready, setReady] = useState(false)\n\n useEffect(() => {\n if (loadedRef.current === true) {\n setReady(true)\n }\n }, [loadedRef.current])\n\n return ready\n}\n\nexport default useGoogleMapsScriptLoadedRef\n","import { useContext } from 'react'\n\nimport ServerSideContext from '../contexts/ServerSideContext'\n\nconst useIsServer = () => {\n const isServerSide = useContext(ServerSideContext)\n return isServerSide\n}\n\nexport default useIsServer\n","import { useContext } from 'react'\n\nimport ServerSideContext from '../contexts/ServerSideContext'\n\nconst useIsServerSide = () => {\n const isServerSide = useContext(ServerSideContext)\n return isServerSide\n}\n\nexport default useIsServerSide\n","import { useSelector } from 'react-redux'\n\ninterface Auth {\n isSignedIn: boolean\n loading: boolean\n}\n\nconst useIsUserSignedIn = () => {\n const { isSignedIn, loading } = useSelector(\n (state: { auth: Auth }) => state.auth\n )\n return {\n isSignedIn,\n loading,\n }\n}\n\nexport default useIsUserSignedIn\n","import useDispatch from 'hooks/useDispatch'\nimport { showAuthModal, hideAuthModal } from '../actions/authActions'\n\nimport useIsUserSignedIn from './useIsUserSignedIn'\n\nconst useLoginModalState = () => {\n const dispatch = useDispatch()\n const { isSignedIn, loading } = useIsUserSignedIn()\n\n const openLoginModal = () => dispatch(showAuthModal())\n const closeLoginModal = () => dispatch(hideAuthModal())\n\n return {\n currentUserSignedIn: isSignedIn,\n currentUserLoading: loading,\n openLoginModal,\n closeLoginModal,\n }\n}\n\nexport default useLoginModalState\n","/* eslint-disable */\nimport { gql } from '@apollo/client'\nimport * as Apollo from '@apollo/client'\nconst defaultOptions = {} as const\nexport const VideoFragmentDoc = gql`\n fragment Video on Video {\n id\n status\n streamUrl\n thumbnailUrl\n }\n`\nexport const CalendarPartsFragmentDoc = gql`\n fragment CalendarParts on Calendar {\n maxStartDate\n listing {\n id\n concurrentBookings\n snoozed\n listingType {\n slug\n }\n }\n days {\n date\n available\n customPrice\n minimumNights\n price\n requested\n weekendPrice\n discount {\n id\n name\n percentage\n startDate\n endDate\n }\n }\n }\n`\nexport const AdventureFragmentFragmentDoc = gql`\n fragment AdventureFragment on StoryAdventure {\n id\n title\n location {\n name\n lat\n lng\n }\n photos(first: 1) {\n image {\n medium\n }\n }\n }\n`\nexport const BankAccountFragmentFragmentDoc = gql`\n fragment BankAccountFragment on BankAccount {\n id\n bankName\n country\n currency\n default\n last4\n listings {\n id\n title\n }\n }\n`\nexport const CreditCardFieldsFragmentDoc = gql`\n fragment CreditCardFields on CreditCard {\n id\n name\n brand\n last4\n expMonth\n expYear\n country\n default\n expired\n }\n`\nexport const AssignmentListingsFieldFragmentDoc = gql`\n fragment AssignmentListingsField on Assignment {\n id\n listings {\n id\n state\n title\n capacity\n city\n url\n pricingSuffix\n promoImage {\n medium\n large\n }\n }\n }\n`\nexport const AssignmentBookingFieldFragmentDoc = gql`\n fragment AssignmentBookingField on Assignment {\n id\n booking {\n id\n adults\n children\n startDate\n endDate\n totalGuests\n total\n status\n lineItems {\n id\n itemType\n price\n quantity\n amount\n }\n listing {\n id\n pricingSuffix\n extraPersonFee\n city\n state\n }\n conversation {\n id\n }\n }\n }\n`\nexport const AssignmentFragmentDoc = gql`\n fragment Assignment on Assignment {\n id\n status\n statusLabel\n startDate\n endDate\n adultGuests: adults\n childrenGuests: children\n totalGuests\n submittedAt\n invitationExpiresAt\n role\n listing {\n id\n capacity\n state\n title\n city\n url\n pricingSuffix\n promoImage {\n medium\n large\n }\n }\n story {\n id\n status\n }\n storyteller {\n id\n firstName\n lastName\n url\n instagram\n avatar {\n original\n thumbMd\n }\n }\n }\n`\nexport const EditListingAdventureFragmentFragmentDoc = gql`\n fragment EditListingAdventureFragment on Adventure {\n id\n title\n description\n adventureType {\n id\n slug\n name\n }\n photos(first: 1) {\n id\n image {\n medium\n large\n }\n }\n location {\n name\n lat\n lng\n }\n locationType\n }\n`\nexport const ConversationItemFragmentFragmentDoc = gql`\n fragment ConversationItemFragment on Conversation {\n id\n archivable\n archivedAt\n lastMessage {\n id\n body\n createdAt\n }\n booking {\n id\n status\n pendingChangeRequest {\n id\n }\n storytellerBooking\n }\n listing {\n id\n title\n }\n correspondent {\n id\n firstName\n lastName\n avatar {\n original\n thumbMd\n }\n }\n }\n`\nexport const ConversationConnectionFragmentFragmentDoc = gql`\n fragment ConversationConnectionFragment on ConversationConnection {\n totalCount\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n ...ConversationItemFragment\n }\n }\n }\n ${ConversationItemFragmentFragmentDoc}\n`\nexport const BucketListThemeFragmentDoc = gql`\n fragment BucketListTheme on BucketListTheme {\n id\n name\n image {\n hero\n large\n medium\n thumb\n }\n }\n`\nexport const BucketListFragmentFragmentDoc = gql`\n fragment BucketListFragment on BucketList {\n id\n name\n includesAccommodation\n theme {\n ...BucketListTheme\n }\n }\n ${BucketListThemeFragmentDoc}\n`\nexport const ListingCardFragmentFragmentDoc = gql`\n fragment ListingCardFragment on Listing {\n id\n url\n title\n price\n pricingSuffix\n nicePricingSuffix\n capacity\n city\n location {\n name\n lat\n lng\n }\n reviewScore\n promoImage {\n medium\n large\n }\n instantBookEnabled\n subcategory {\n id\n name\n }\n }\n`\nexport const StoryCardFragmentFragmentDoc = gql`\n fragment StoryCardFragment on Story {\n id\n title\n url\n videoUrl\n user {\n avatar {\n original\n thumbLg\n }\n firstName\n }\n promoImage {\n medium\n large\n }\n featuredListingImage {\n medium\n large\n }\n }\n`\nexport const StoryFeaturedListingFragmentFragmentDoc = gql`\n fragment StoryFeaturedListingFragment on Listing {\n id\n title\n price\n pricingSuffix\n nicePricingSuffix\n reviewScore\n instantBookEnabled\n url\n capacity\n city\n location {\n name\n lat\n lng\n }\n }\n`\nexport const AdventureCardFragmentFragmentDoc = gql`\n fragment AdventureCardFragment on StoryAdventure {\n id\n title\n description\n adventureType {\n id\n slug\n name\n }\n photos(first: 5) {\n id\n image {\n medium\n large\n }\n }\n location {\n name\n lat\n lng\n }\n locationType\n reviewScore\n story {\n id\n title\n url\n active\n }\n storyteller {\n id\n firstName\n url\n avatar {\n original\n thumb\n thumbLg\n }\n }\n storyUrl\n url\n }\n`\nexport const ListingAdventureFragmentDoc = gql`\n fragment ListingAdventure on ListingAdventure {\n id\n title\n description\n adventureType {\n id\n slug\n }\n photos(first: 5) {\n image {\n medium\n }\n }\n location {\n name\n lat\n lng\n }\n locationType\n reviewScore\n url\n }\n`\nexport const BucketListItemConnectionFragmentDoc = gql`\n fragment BucketListItemConnection on BucketListItemConnection {\n edges {\n node {\n pricing {\n total\n customerServiceFee\n lineItems {\n itemType\n quantity\n price\n amount\n }\n }\n item {\n ... on Listing {\n ...ListingCardFragment\n stories {\n ...StoryCardFragment\n }\n }\n ... on Story {\n ...StoryCardFragment\n featuredListing {\n ...StoryFeaturedListingFragment\n }\n }\n ... on StoryAdventure {\n ...AdventureCardFragment\n }\n ... on ListingAdventure {\n ...ListingAdventure\n }\n }\n }\n }\n }\n ${ListingCardFragmentFragmentDoc}\n ${StoryCardFragmentFragmentDoc}\n ${StoryFeaturedListingFragmentFragmentDoc}\n ${AdventureCardFragmentFragmentDoc}\n ${ListingAdventureFragmentDoc}\n`\nexport const MapResultFragmentFragmentDoc = gql`\n fragment MapResultFragment on MapResult {\n id\n slug\n type\n location: coordinates\n }\n`\nexport const CollectionFragmentDoc = gql`\n fragment Collection on Collection {\n id\n name\n slug\n image {\n medium\n large\n }\n markets {\n id\n code\n name\n }\n }\n`\nexport const ListingNearbyAdventureFragmentDoc = gql`\n fragment ListingNearbyAdventure on Adventure {\n id\n title\n description\n title\n url\n photos {\n id\n image {\n medium\n thumb\n }\n }\n adventureType {\n id\n name\n slug\n category\n }\n ... on StoryAdventure {\n story {\n id\n title\n }\n storyUrl\n storyteller {\n id\n firstName\n avatar {\n original\n thumb\n thumbLg\n }\n }\n }\n }\n`\nexport const ListingReviewFragmentDoc = gql`\n fragment ListingReview on ListingReview {\n id\n createdAt\n reviewer {\n firstName\n avatar {\n original\n thumbLg\n }\n }\n content\n fulfillingMoments {\n slug\n name\n }\n }\n`\nexport const CustomerReferralFragmentDoc = gql`\n fragment CustomerReferral on CustomerReferral {\n id\n recipientFirstName\n recipientLastName\n recipientEmail\n message\n status\n createdAt\n sentAt\n completedAt\n shareUrl\n rewardVoucher {\n code\n amount\n balance\n expiresAt\n }\n referralVoucher {\n amount\n }\n }\n`\nexport const AddToBucketListDocument = gql`\n mutation addToBucketList(\n $bucketListId: ID!\n $itemId: ID!\n $itemType: Searchable!\n $source: String!\n ) {\n addToBucketList(\n bucketListId: $bucketListId\n itemId: $itemId\n itemType: $itemType\n source: $source\n ) {\n bucketListItem {\n item {\n ... on Listing {\n id\n }\n ... on StoryAdventure {\n id\n }\n ... on Story {\n id\n }\n }\n }\n }\n }\n`\nexport type GQL_AddToBucketListMutationFn = Apollo.MutationFunction<\n GQL_AddToBucketListMutation,\n GQL_AddToBucketListMutationVariables\n>\n\n/**\n * __useAddToBucketListMutation__\n *\n * To run a mutation, you first call `useAddToBucketListMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useAddToBucketListMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [addToBucketListMutation, { data, loading, error }] = useAddToBucketListMutation({\n * variables: {\n * bucketListId: // value for 'bucketListId'\n * itemId: // value for 'itemId'\n * itemType: // value for 'itemType'\n * source: // value for 'source'\n * },\n * });\n */\nexport function useAddToBucketListMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_AddToBucketListMutation,\n GQL_AddToBucketListMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_AddToBucketListMutation,\n GQL_AddToBucketListMutationVariables\n >(AddToBucketListDocument, options)\n}\nexport type AddToBucketListMutationHookResult = ReturnType<\n typeof useAddToBucketListMutation\n>\nexport type AddToBucketListMutationResult = Apollo.MutationResult<\n GQL_AddToBucketListMutation\n>\nexport type AddToBucketListMutationOptions = Apollo.BaseMutationOptions<\n GQL_AddToBucketListMutation,\n GQL_AddToBucketListMutationVariables\n>\nexport const GetMyBucketListsWithItemDocument = gql`\n query getMyBucketListsWithItem($itemId: ID!, $itemType: Searchable!) {\n currentUser {\n id\n allBucketLists: bucketLists {\n ...BucketListFragment\n }\n bucketListsWithItem: bucketLists(itemId: $itemId, itemType: $itemType) {\n ...BucketListFragment\n }\n }\n }\n ${BucketListFragmentFragmentDoc}\n`\n\n/**\n * __useGetMyBucketListsWithItemQuery__\n *\n * To run a query within a React component, call `useGetMyBucketListsWithItemQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyBucketListsWithItemQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyBucketListsWithItemQuery({\n * variables: {\n * itemId: // value for 'itemId'\n * itemType: // value for 'itemType'\n * },\n * });\n */\nexport function useGetMyBucketListsWithItemQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetMyBucketListsWithItemQuery,\n GQL_GetMyBucketListsWithItemQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyBucketListsWithItemQuery,\n GQL_GetMyBucketListsWithItemQueryVariables\n >(GetMyBucketListsWithItemDocument, options)\n}\nexport function useGetMyBucketListsWithItemLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyBucketListsWithItemQuery,\n GQL_GetMyBucketListsWithItemQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyBucketListsWithItemQuery,\n GQL_GetMyBucketListsWithItemQueryVariables\n >(GetMyBucketListsWithItemDocument, options)\n}\nexport type GetMyBucketListsWithItemQueryHookResult = ReturnType<\n typeof useGetMyBucketListsWithItemQuery\n>\nexport type GetMyBucketListsWithItemLazyQueryHookResult = ReturnType<\n typeof useGetMyBucketListsWithItemLazyQuery\n>\nexport type GetMyBucketListsWithItemQueryResult = Apollo.QueryResult<\n GQL_GetMyBucketListsWithItemQuery,\n GQL_GetMyBucketListsWithItemQueryVariables\n>\nexport const GetMyUpcomingBookingsWithAdventuresAndListingDocument = gql`\n query getMyUpcomingBookingsWithAdventuresAndListing {\n currentUser {\n id\n upcomingBookings {\n id\n startDate\n endDate\n listing {\n id\n title\n promoImage {\n medium\n thumb\n }\n }\n story {\n id\n promoImage {\n medium\n thumb\n }\n }\n adventures {\n id\n }\n }\n }\n }\n`\n\n/**\n * __useGetMyUpcomingBookingsWithAdventuresAndListingQuery__\n *\n * To run a query within a React component, call `useGetMyUpcomingBookingsWithAdventuresAndListingQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyUpcomingBookingsWithAdventuresAndListingQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyUpcomingBookingsWithAdventuresAndListingQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetMyUpcomingBookingsWithAdventuresAndListingQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQuery,\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQuery,\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQueryVariables\n >(GetMyUpcomingBookingsWithAdventuresAndListingDocument, options)\n}\nexport function useGetMyUpcomingBookingsWithAdventuresAndListingLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQuery,\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQuery,\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQueryVariables\n >(GetMyUpcomingBookingsWithAdventuresAndListingDocument, options)\n}\nexport type GetMyUpcomingBookingsWithAdventuresAndListingQueryHookResult = ReturnType<\n typeof useGetMyUpcomingBookingsWithAdventuresAndListingQuery\n>\nexport type GetMyUpcomingBookingsWithAdventuresAndListingLazyQueryHookResult = ReturnType<\n typeof useGetMyUpcomingBookingsWithAdventuresAndListingLazyQuery\n>\nexport type GetMyUpcomingBookingsWithAdventuresAndListingQueryResult = Apollo.QueryResult<\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQuery,\n GQL_GetMyUpcomingBookingsWithAdventuresAndListingQueryVariables\n>\nexport const GetSelectEscapeIndexesDocument = gql`\n query getSelectEscapeIndexes {\n currentUser {\n id\n bucketListItemsIndex\n bookingAdventuresIndex\n }\n }\n`\n\n/**\n * __useGetSelectEscapeIndexesQuery__\n *\n * To run a query within a React component, call `useGetSelectEscapeIndexesQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetSelectEscapeIndexesQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetSelectEscapeIndexesQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetSelectEscapeIndexesQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetSelectEscapeIndexesQuery,\n GQL_GetSelectEscapeIndexesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetSelectEscapeIndexesQuery,\n GQL_GetSelectEscapeIndexesQueryVariables\n >(GetSelectEscapeIndexesDocument, options)\n}\nexport function useGetSelectEscapeIndexesLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetSelectEscapeIndexesQuery,\n GQL_GetSelectEscapeIndexesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetSelectEscapeIndexesQuery,\n GQL_GetSelectEscapeIndexesQueryVariables\n >(GetSelectEscapeIndexesDocument, options)\n}\nexport type GetSelectEscapeIndexesQueryHookResult = ReturnType<\n typeof useGetSelectEscapeIndexesQuery\n>\nexport type GetSelectEscapeIndexesLazyQueryHookResult = ReturnType<\n typeof useGetSelectEscapeIndexesLazyQuery\n>\nexport type GetSelectEscapeIndexesQueryResult = Apollo.QueryResult<\n GQL_GetSelectEscapeIndexesQuery,\n GQL_GetSelectEscapeIndexesQueryVariables\n>\nexport const RemoveFromBucketListDocument = gql`\n mutation removeFromBucketList(\n $bucketListId: ID!\n $itemId: ID!\n $itemType: Searchable!\n $source: String!\n ) {\n removeFromBucketList(\n bucketListId: $bucketListId\n itemId: $itemId\n itemType: $itemType\n source: $source\n ) {\n bucketListItem {\n item {\n ... on Listing {\n id\n }\n ... on StoryAdventure {\n id\n }\n ... on Story {\n id\n }\n }\n }\n }\n }\n`\nexport type GQL_RemoveFromBucketListMutationFn = Apollo.MutationFunction<\n GQL_RemoveFromBucketListMutation,\n GQL_RemoveFromBucketListMutationVariables\n>\n\n/**\n * __useRemoveFromBucketListMutation__\n *\n * To run a mutation, you first call `useRemoveFromBucketListMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useRemoveFromBucketListMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [removeFromBucketListMutation, { data, loading, error }] = useRemoveFromBucketListMutation({\n * variables: {\n * bucketListId: // value for 'bucketListId'\n * itemId: // value for 'itemId'\n * itemType: // value for 'itemType'\n * source: // value for 'source'\n * },\n * });\n */\nexport function useRemoveFromBucketListMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_RemoveFromBucketListMutation,\n GQL_RemoveFromBucketListMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_RemoveFromBucketListMutation,\n GQL_RemoveFromBucketListMutationVariables\n >(RemoveFromBucketListDocument, options)\n}\nexport type RemoveFromBucketListMutationHookResult = ReturnType<\n typeof useRemoveFromBucketListMutation\n>\nexport type RemoveFromBucketListMutationResult = Apollo.MutationResult<\n GQL_RemoveFromBucketListMutation\n>\nexport type RemoveFromBucketListMutationOptions = Apollo.BaseMutationOptions<\n GQL_RemoveFromBucketListMutation,\n GQL_RemoveFromBucketListMutationVariables\n>\nexport const GetCurrentUserDocument = gql`\n query getCurrentUser {\n currentUser {\n id\n deleteRequestedAt\n incompleteBookings {\n id\n startDate\n endDate\n promoImage {\n thumb\n }\n listing {\n id\n title\n }\n }\n }\n }\n`\n\n/**\n * __useGetCurrentUserQuery__\n *\n * To run a query within a React component, call `useGetCurrentUserQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetCurrentUserQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetCurrentUserQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetCurrentUserQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetCurrentUserQuery,\n GQL_GetCurrentUserQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetCurrentUserQuery,\n GQL_GetCurrentUserQueryVariables\n >(GetCurrentUserDocument, options)\n}\nexport function useGetCurrentUserLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetCurrentUserQuery,\n GQL_GetCurrentUserQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetCurrentUserQuery,\n GQL_GetCurrentUserQueryVariables\n >(GetCurrentUserDocument, options)\n}\nexport type GetCurrentUserQueryHookResult = ReturnType<\n typeof useGetCurrentUserQuery\n>\nexport type GetCurrentUserLazyQueryHookResult = ReturnType<\n typeof useGetCurrentUserLazyQuery\n>\nexport type GetCurrentUserQueryResult = Apollo.QueryResult<\n GQL_GetCurrentUserQuery,\n GQL_GetCurrentUserQueryVariables\n>\nexport const GetBookingInvitationDocument = gql`\n query getBookingInvitation($token: ID!) {\n bookingInvitation(token: $token) {\n id\n bookingCustomerId\n promoImage {\n thumb\n }\n listing {\n id\n title\n location {\n name\n lat\n lng\n }\n }\n }\n }\n`\n\n/**\n * __useGetBookingInvitationQuery__\n *\n * To run a query within a React component, call `useGetBookingInvitationQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBookingInvitationQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBookingInvitationQuery({\n * variables: {\n * token: // value for 'token'\n * },\n * });\n */\nexport function useGetBookingInvitationQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBookingInvitationQuery,\n GQL_GetBookingInvitationQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBookingInvitationQuery,\n GQL_GetBookingInvitationQueryVariables\n >(GetBookingInvitationDocument, options)\n}\nexport function useGetBookingInvitationLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBookingInvitationQuery,\n GQL_GetBookingInvitationQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBookingInvitationQuery,\n GQL_GetBookingInvitationQueryVariables\n >(GetBookingInvitationDocument, options)\n}\nexport type GetBookingInvitationQueryHookResult = ReturnType<\n typeof useGetBookingInvitationQuery\n>\nexport type GetBookingInvitationLazyQueryHookResult = ReturnType<\n typeof useGetBookingInvitationLazyQuery\n>\nexport type GetBookingInvitationQueryResult = Apollo.QueryResult<\n GQL_GetBookingInvitationQuery,\n GQL_GetBookingInvitationQueryVariables\n>\nexport const JoinTravelCrewDocument = gql`\n mutation joinTravelCrew($bookingId: ID!, $hashid: String!) {\n joinTravelCrew(bookingId: $bookingId, hashid: $hashid) {\n booking {\n id\n travelCrew {\n id\n firstName\n lastName\n }\n }\n }\n }\n`\nexport type GQL_JoinTravelCrewMutationFn = Apollo.MutationFunction<\n GQL_JoinTravelCrewMutation,\n GQL_JoinTravelCrewMutationVariables\n>\n\n/**\n * __useJoinTravelCrewMutation__\n *\n * To run a mutation, you first call `useJoinTravelCrewMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useJoinTravelCrewMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [joinTravelCrewMutation, { data, loading, error }] = useJoinTravelCrewMutation({\n * variables: {\n * bookingId: // value for 'bookingId'\n * hashid: // value for 'hashid'\n * },\n * });\n */\nexport function useJoinTravelCrewMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_JoinTravelCrewMutation,\n GQL_JoinTravelCrewMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_JoinTravelCrewMutation,\n GQL_JoinTravelCrewMutationVariables\n >(JoinTravelCrewDocument, options)\n}\nexport type JoinTravelCrewMutationHookResult = ReturnType<\n typeof useJoinTravelCrewMutation\n>\nexport type JoinTravelCrewMutationResult = Apollo.MutationResult<\n GQL_JoinTravelCrewMutation\n>\nexport type JoinTravelCrewMutationOptions = Apollo.BaseMutationOptions<\n GQL_JoinTravelCrewMutation,\n GQL_JoinTravelCrewMutationVariables\n>\nexport const ApplyVoucherBalanceDocument = gql`\n mutation applyVoucherBalance($bookingId: ID!) {\n applyVoucherBalance(bookingId: $bookingId) {\n booking {\n id\n }\n }\n }\n`\nexport type GQL_ApplyVoucherBalanceMutationFn = Apollo.MutationFunction<\n GQL_ApplyVoucherBalanceMutation,\n GQL_ApplyVoucherBalanceMutationVariables\n>\n\n/**\n * __useApplyVoucherBalanceMutation__\n *\n * To run a mutation, you first call `useApplyVoucherBalanceMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useApplyVoucherBalanceMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [applyVoucherBalanceMutation, { data, loading, error }] = useApplyVoucherBalanceMutation({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useApplyVoucherBalanceMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_ApplyVoucherBalanceMutation,\n GQL_ApplyVoucherBalanceMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_ApplyVoucherBalanceMutation,\n GQL_ApplyVoucherBalanceMutationVariables\n >(ApplyVoucherBalanceDocument, options)\n}\nexport type ApplyVoucherBalanceMutationHookResult = ReturnType<\n typeof useApplyVoucherBalanceMutation\n>\nexport type ApplyVoucherBalanceMutationResult = Apollo.MutationResult<\n GQL_ApplyVoucherBalanceMutation\n>\nexport type ApplyVoucherBalanceMutationOptions = Apollo.BaseMutationOptions<\n GQL_ApplyVoucherBalanceMutation,\n GQL_ApplyVoucherBalanceMutationVariables\n>\nexport const DestroyBookingVoucherDocument = gql`\n mutation destroyBookingVoucher($bookingId: ID!, $voucherId: ID!) {\n destroyBookingVoucher(bookingId: $bookingId, voucherId: $voucherId) {\n booking {\n id\n }\n }\n }\n`\nexport type GQL_DestroyBookingVoucherMutationFn = Apollo.MutationFunction<\n GQL_DestroyBookingVoucherMutation,\n GQL_DestroyBookingVoucherMutationVariables\n>\n\n/**\n * __useDestroyBookingVoucherMutation__\n *\n * To run a mutation, you first call `useDestroyBookingVoucherMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDestroyBookingVoucherMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [destroyBookingVoucherMutation, { data, loading, error }] = useDestroyBookingVoucherMutation({\n * variables: {\n * bookingId: // value for 'bookingId'\n * voucherId: // value for 'voucherId'\n * },\n * });\n */\nexport function useDestroyBookingVoucherMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DestroyBookingVoucherMutation,\n GQL_DestroyBookingVoucherMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DestroyBookingVoucherMutation,\n GQL_DestroyBookingVoucherMutationVariables\n >(DestroyBookingVoucherDocument, options)\n}\nexport type DestroyBookingVoucherMutationHookResult = ReturnType<\n typeof useDestroyBookingVoucherMutation\n>\nexport type DestroyBookingVoucherMutationResult = Apollo.MutationResult<\n GQL_DestroyBookingVoucherMutation\n>\nexport type DestroyBookingVoucherMutationOptions = Apollo.BaseMutationOptions<\n GQL_DestroyBookingVoucherMutation,\n GQL_DestroyBookingVoucherMutationVariables\n>\nexport const GetBookingSuccessDocument = gql`\n query getBookingSuccess($id: ID!) {\n booking(id: $id) {\n id\n status\n paymentStatus\n storytellerBooking\n startDate\n endDate\n role\n joinUrl\n listing {\n id\n title\n url\n city\n state\n checkIn\n checkOut\n }\n story {\n id\n title\n url\n }\n promoImage {\n medium\n }\n }\n }\n`\n\n/**\n * __useGetBookingSuccessQuery__\n *\n * To run a query within a React component, call `useGetBookingSuccessQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBookingSuccessQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBookingSuccessQuery({\n * variables: {\n * id: // value for 'id'\n * },\n * });\n */\nexport function useGetBookingSuccessQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBookingSuccessQuery,\n GQL_GetBookingSuccessQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBookingSuccessQuery,\n GQL_GetBookingSuccessQueryVariables\n >(GetBookingSuccessDocument, options)\n}\nexport function useGetBookingSuccessLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBookingSuccessQuery,\n GQL_GetBookingSuccessQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBookingSuccessQuery,\n GQL_GetBookingSuccessQueryVariables\n >(GetBookingSuccessDocument, options)\n}\nexport type GetBookingSuccessQueryHookResult = ReturnType<\n typeof useGetBookingSuccessQuery\n>\nexport type GetBookingSuccessLazyQueryHookResult = ReturnType<\n typeof useGetBookingSuccessLazyQuery\n>\nexport type GetBookingSuccessQueryResult = Apollo.QueryResult<\n GQL_GetBookingSuccessQuery,\n GQL_GetBookingSuccessQueryVariables\n>\nexport const GetPhotosForListingDocument = gql`\n query getPhotosForListing($id: ID) {\n photos(ownerId: $id, ownerType: \"Listing\") {\n image {\n medium\n large\n }\n }\n }\n`\n\n/**\n * __useGetPhotosForListingQuery__\n *\n * To run a query within a React component, call `useGetPhotosForListingQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetPhotosForListingQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetPhotosForListingQuery({\n * variables: {\n * id: // value for 'id'\n * },\n * });\n */\nexport function useGetPhotosForListingQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetPhotosForListingQuery,\n GQL_GetPhotosForListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetPhotosForListingQuery,\n GQL_GetPhotosForListingQueryVariables\n >(GetPhotosForListingDocument, options)\n}\nexport function useGetPhotosForListingLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetPhotosForListingQuery,\n GQL_GetPhotosForListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetPhotosForListingQuery,\n GQL_GetPhotosForListingQueryVariables\n >(GetPhotosForListingDocument, options)\n}\nexport type GetPhotosForListingQueryHookResult = ReturnType<\n typeof useGetPhotosForListingQuery\n>\nexport type GetPhotosForListingLazyQueryHookResult = ReturnType<\n typeof useGetPhotosForListingLazyQuery\n>\nexport type GetPhotosForListingQueryResult = Apollo.QueryResult<\n GQL_GetPhotosForListingQuery,\n GQL_GetPhotosForListingQueryVariables\n>\nexport const GetStoryMediaDocument = gql`\n query getStoryMedia($storyId: ID!) {\n story(id: $storyId) {\n id\n portraitCoverImage {\n w400\n w800\n w1200\n }\n promoImage {\n medium\n large\n }\n featuredListingImage {\n medium\n large\n }\n photos {\n id\n image {\n medium\n large\n }\n }\n videos {\n ...Video\n }\n }\n }\n ${VideoFragmentDoc}\n`\n\n/**\n * __useGetStoryMediaQuery__\n *\n * To run a query within a React component, call `useGetStoryMediaQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetStoryMediaQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetStoryMediaQuery({\n * variables: {\n * storyId: // value for 'storyId'\n * },\n * });\n */\nexport function useGetStoryMediaQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetStoryMediaQuery,\n GQL_GetStoryMediaQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetStoryMediaQuery,\n GQL_GetStoryMediaQueryVariables\n >(GetStoryMediaDocument, options)\n}\nexport function useGetStoryMediaLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetStoryMediaQuery,\n GQL_GetStoryMediaQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetStoryMediaQuery,\n GQL_GetStoryMediaQueryVariables\n >(GetStoryMediaDocument, options)\n}\nexport type GetStoryMediaQueryHookResult = ReturnType<\n typeof useGetStoryMediaQuery\n>\nexport type GetStoryMediaLazyQueryHookResult = ReturnType<\n typeof useGetStoryMediaLazyQuery\n>\nexport type GetStoryMediaQueryResult = Apollo.QueryResult<\n GQL_GetStoryMediaQuery,\n GQL_GetStoryMediaQueryVariables\n>\nexport const GetIncompleteBookingsDocument = gql`\n query getIncompleteBookings {\n currentUser {\n id\n incompleteBookings {\n id\n startDate\n endDate\n listing {\n id\n }\n }\n }\n }\n`\n\n/**\n * __useGetIncompleteBookingsQuery__\n *\n * To run a query within a React component, call `useGetIncompleteBookingsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetIncompleteBookingsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetIncompleteBookingsQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetIncompleteBookingsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetIncompleteBookingsQuery,\n GQL_GetIncompleteBookingsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetIncompleteBookingsQuery,\n GQL_GetIncompleteBookingsQueryVariables\n >(GetIncompleteBookingsDocument, options)\n}\nexport function useGetIncompleteBookingsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetIncompleteBookingsQuery,\n GQL_GetIncompleteBookingsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetIncompleteBookingsQuery,\n GQL_GetIncompleteBookingsQueryVariables\n >(GetIncompleteBookingsDocument, options)\n}\nexport type GetIncompleteBookingsQueryHookResult = ReturnType<\n typeof useGetIncompleteBookingsQuery\n>\nexport type GetIncompleteBookingsLazyQueryHookResult = ReturnType<\n typeof useGetIncompleteBookingsLazyQuery\n>\nexport type GetIncompleteBookingsQueryResult = Apollo.QueryResult<\n GQL_GetIncompleteBookingsQuery,\n GQL_GetIncompleteBookingsQueryVariables\n>\nexport const GetListingAvailabilityAlertsDocument = gql`\n query getListingAvailabilityAlerts($listingId: ID!) {\n listing(id: $listingId) {\n id\n popular\n promotionalDiscounts {\n id\n name\n percentage\n startDate\n endDate\n }\n weekendAvailabilities {\n available\n startDate\n endDate\n }\n }\n }\n`\n\n/**\n * __useGetListingAvailabilityAlertsQuery__\n *\n * To run a query within a React component, call `useGetListingAvailabilityAlertsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetListingAvailabilityAlertsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetListingAvailabilityAlertsQuery({\n * variables: {\n * listingId: // value for 'listingId'\n * },\n * });\n */\nexport function useGetListingAvailabilityAlertsQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetListingAvailabilityAlertsQuery,\n GQL_GetListingAvailabilityAlertsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetListingAvailabilityAlertsQuery,\n GQL_GetListingAvailabilityAlertsQueryVariables\n >(GetListingAvailabilityAlertsDocument, options)\n}\nexport function useGetListingAvailabilityAlertsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetListingAvailabilityAlertsQuery,\n GQL_GetListingAvailabilityAlertsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetListingAvailabilityAlertsQuery,\n GQL_GetListingAvailabilityAlertsQueryVariables\n >(GetListingAvailabilityAlertsDocument, options)\n}\nexport type GetListingAvailabilityAlertsQueryHookResult = ReturnType<\n typeof useGetListingAvailabilityAlertsQuery\n>\nexport type GetListingAvailabilityAlertsLazyQueryHookResult = ReturnType<\n typeof useGetListingAvailabilityAlertsLazyQuery\n>\nexport type GetListingAvailabilityAlertsQueryResult = Apollo.QueryResult<\n GQL_GetListingAvailabilityAlertsQuery,\n GQL_GetListingAvailabilityAlertsQueryVariables\n>\nexport const GetCalendarDaysForBookingDocument = gql`\n query getCalendarDaysForBooking(\n $bookingId: ID!\n $startDate: ISO8601Date!\n $endDate: ISO8601Date!\n ) {\n booking(id: $bookingId) {\n id\n calendar(startDate: $startDate, endDate: $endDate) {\n ...CalendarParts\n }\n }\n }\n ${CalendarPartsFragmentDoc}\n`\n\n/**\n * __useGetCalendarDaysForBookingQuery__\n *\n * To run a query within a React component, call `useGetCalendarDaysForBookingQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetCalendarDaysForBookingQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetCalendarDaysForBookingQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * startDate: // value for 'startDate'\n * endDate: // value for 'endDate'\n * },\n * });\n */\nexport function useGetCalendarDaysForBookingQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetCalendarDaysForBookingQuery,\n GQL_GetCalendarDaysForBookingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetCalendarDaysForBookingQuery,\n GQL_GetCalendarDaysForBookingQueryVariables\n >(GetCalendarDaysForBookingDocument, options)\n}\nexport function useGetCalendarDaysForBookingLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetCalendarDaysForBookingQuery,\n GQL_GetCalendarDaysForBookingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetCalendarDaysForBookingQuery,\n GQL_GetCalendarDaysForBookingQueryVariables\n >(GetCalendarDaysForBookingDocument, options)\n}\nexport type GetCalendarDaysForBookingQueryHookResult = ReturnType<\n typeof useGetCalendarDaysForBookingQuery\n>\nexport type GetCalendarDaysForBookingLazyQueryHookResult = ReturnType<\n typeof useGetCalendarDaysForBookingLazyQuery\n>\nexport type GetCalendarDaysForBookingQueryResult = Apollo.QueryResult<\n GQL_GetCalendarDaysForBookingQuery,\n GQL_GetCalendarDaysForBookingQueryVariables\n>\nexport const GetCalendarDaysForListingDocument = gql`\n query getCalendarDaysForListing(\n $listingId: ID!\n $startDate: ISO8601Date!\n $endDate: ISO8601Date!\n ) {\n listing(id: $listingId) {\n id\n calendar(startDate: $startDate, endDate: $endDate) {\n ...CalendarParts\n }\n }\n }\n ${CalendarPartsFragmentDoc}\n`\n\n/**\n * __useGetCalendarDaysForListingQuery__\n *\n * To run a query within a React component, call `useGetCalendarDaysForListingQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetCalendarDaysForListingQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetCalendarDaysForListingQuery({\n * variables: {\n * listingId: // value for 'listingId'\n * startDate: // value for 'startDate'\n * endDate: // value for 'endDate'\n * },\n * });\n */\nexport function useGetCalendarDaysForListingQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetCalendarDaysForListingQuery,\n GQL_GetCalendarDaysForListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetCalendarDaysForListingQuery,\n GQL_GetCalendarDaysForListingQueryVariables\n >(GetCalendarDaysForListingDocument, options)\n}\nexport function useGetCalendarDaysForListingLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetCalendarDaysForListingQuery,\n GQL_GetCalendarDaysForListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetCalendarDaysForListingQuery,\n GQL_GetCalendarDaysForListingQueryVariables\n >(GetCalendarDaysForListingDocument, options)\n}\nexport type GetCalendarDaysForListingQueryHookResult = ReturnType<\n typeof useGetCalendarDaysForListingQuery\n>\nexport type GetCalendarDaysForListingLazyQueryHookResult = ReturnType<\n typeof useGetCalendarDaysForListingLazyQuery\n>\nexport type GetCalendarDaysForListingQueryResult = Apollo.QueryResult<\n GQL_GetCalendarDaysForListingQuery,\n GQL_GetCalendarDaysForListingQueryVariables\n>\nexport const GetUserCountryAndStripeKeyDocument = gql`\n query getUserCountryAndStripeKey {\n currentUser {\n id\n defaultCountry {\n id\n code\n name\n defaultCurrency\n stripePlatform {\n name\n publicKey\n }\n }\n }\n }\n`\n\n/**\n * __useGetUserCountryAndStripeKeyQuery__\n *\n * To run a query within a React component, call `useGetUserCountryAndStripeKeyQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetUserCountryAndStripeKeyQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetUserCountryAndStripeKeyQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetUserCountryAndStripeKeyQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetUserCountryAndStripeKeyQuery,\n GQL_GetUserCountryAndStripeKeyQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetUserCountryAndStripeKeyQuery,\n GQL_GetUserCountryAndStripeKeyQueryVariables\n >(GetUserCountryAndStripeKeyDocument, options)\n}\nexport function useGetUserCountryAndStripeKeyLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetUserCountryAndStripeKeyQuery,\n GQL_GetUserCountryAndStripeKeyQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetUserCountryAndStripeKeyQuery,\n GQL_GetUserCountryAndStripeKeyQueryVariables\n >(GetUserCountryAndStripeKeyDocument, options)\n}\nexport type GetUserCountryAndStripeKeyQueryHookResult = ReturnType<\n typeof useGetUserCountryAndStripeKeyQuery\n>\nexport type GetUserCountryAndStripeKeyLazyQueryHookResult = ReturnType<\n typeof useGetUserCountryAndStripeKeyLazyQuery\n>\nexport type GetUserCountryAndStripeKeyQueryResult = Apollo.QueryResult<\n GQL_GetUserCountryAndStripeKeyQuery,\n GQL_GetUserCountryAndStripeKeyQueryVariables\n>\nexport const GetCountriesDocument = gql`\n query getCountries {\n defaults {\n countries {\n id\n code\n name\n discoverable\n }\n }\n }\n`\n\n/**\n * __useGetCountriesQuery__\n *\n * To run a query within a React component, call `useGetCountriesQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetCountriesQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetCountriesQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetCountriesQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetCountriesQuery,\n GQL_GetCountriesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n GetCountriesDocument,\n options\n )\n}\nexport function useGetCountriesLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetCountriesQuery,\n GQL_GetCountriesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetCountriesQuery,\n GQL_GetCountriesQueryVariables\n >(GetCountriesDocument, options)\n}\nexport type GetCountriesQueryHookResult = ReturnType<\n typeof useGetCountriesQuery\n>\nexport type GetCountriesLazyQueryHookResult = ReturnType<\n typeof useGetCountriesLazyQuery\n>\nexport type GetCountriesQueryResult = Apollo.QueryResult<\n GQL_GetCountriesQuery,\n GQL_GetCountriesQueryVariables\n>\nexport const GetCountryDocument = gql`\n query getCountry($code: Countries!) {\n country(code: $code) {\n id\n code\n name\n officialName\n defaultCurrency\n }\n }\n`\n\n/**\n * __useGetCountryQuery__\n *\n * To run a query within a React component, call `useGetCountryQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetCountryQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetCountryQuery({\n * variables: {\n * code: // value for 'code'\n * },\n * });\n */\nexport function useGetCountryQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetCountryQuery,\n GQL_GetCountryQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n GetCountryDocument,\n options\n )\n}\nexport function useGetCountryLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetCountryQuery,\n GQL_GetCountryQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery(\n GetCountryDocument,\n options\n )\n}\nexport type GetCountryQueryHookResult = ReturnType\nexport type GetCountryLazyQueryHookResult = ReturnType<\n typeof useGetCountryLazyQuery\n>\nexport type GetCountryQueryResult = Apollo.QueryResult<\n GQL_GetCountryQuery,\n GQL_GetCountryQueryVariables\n>\nexport const AdventuresReviewDocument = gql`\n query adventuresReview($bookingId: ID!) {\n booking(id: $bookingId) {\n id\n adventures {\n ...AdventureFragment\n }\n story {\n id\n title\n featuredListing {\n title\n }\n storyteller: user {\n firstName\n }\n }\n adventureReviews {\n id\n adventure {\n ...AdventureFragment\n }\n rating\n content\n fulfillingMomentIds\n }\n }\n fulfillingMoments {\n id\n slug\n name\n }\n }\n ${AdventureFragmentFragmentDoc}\n`\n\n/**\n * __useAdventuresReviewQuery__\n *\n * To run a query within a React component, call `useAdventuresReviewQuery` and pass it any options that fit your needs.\n * When your component renders, `useAdventuresReviewQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useAdventuresReviewQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useAdventuresReviewQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_AdventuresReviewQuery,\n GQL_AdventuresReviewQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_AdventuresReviewQuery,\n GQL_AdventuresReviewQueryVariables\n >(AdventuresReviewDocument, options)\n}\nexport function useAdventuresReviewLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_AdventuresReviewQuery,\n GQL_AdventuresReviewQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_AdventuresReviewQuery,\n GQL_AdventuresReviewQueryVariables\n >(AdventuresReviewDocument, options)\n}\nexport type AdventuresReviewQueryHookResult = ReturnType<\n typeof useAdventuresReviewQuery\n>\nexport type AdventuresReviewLazyQueryHookResult = ReturnType<\n typeof useAdventuresReviewLazyQuery\n>\nexport type AdventuresReviewQueryResult = Apollo.QueryResult<\n GQL_AdventuresReviewQuery,\n GQL_AdventuresReviewQueryVariables\n>\nexport const CreateAdventureReviewDocument = gql`\n mutation createAdventureReview(\n $bookingId: ID!\n $adventureReviewInput: AdventureReviewInput!\n ) {\n createAdventureReview(\n bookingId: $bookingId\n adventureReviewInput: $adventureReviewInput\n ) {\n adventureReview {\n id\n rating\n content\n fulfillingMomentIds\n }\n }\n }\n`\nexport type GQL_CreateAdventureReviewMutationFn = Apollo.MutationFunction<\n GQL_CreateAdventureReviewMutation,\n GQL_CreateAdventureReviewMutationVariables\n>\n\n/**\n * __useCreateAdventureReviewMutation__\n *\n * To run a mutation, you first call `useCreateAdventureReviewMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateAdventureReviewMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createAdventureReviewMutation, { data, loading, error }] = useCreateAdventureReviewMutation({\n * variables: {\n * bookingId: // value for 'bookingId'\n * adventureReviewInput: // value for 'adventureReviewInput'\n * },\n * });\n */\nexport function useCreateAdventureReviewMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateAdventureReviewMutation,\n GQL_CreateAdventureReviewMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateAdventureReviewMutation,\n GQL_CreateAdventureReviewMutationVariables\n >(CreateAdventureReviewDocument, options)\n}\nexport type CreateAdventureReviewMutationHookResult = ReturnType<\n typeof useCreateAdventureReviewMutation\n>\nexport type CreateAdventureReviewMutationResult = Apollo.MutationResult<\n GQL_CreateAdventureReviewMutation\n>\nexport type CreateAdventureReviewMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateAdventureReviewMutation,\n GQL_CreateAdventureReviewMutationVariables\n>\nexport const UpdateAdventureReviewDocument = gql`\n mutation updateAdventureReview(\n $adventureReviewId: ID!\n $adventureReviewInput: AdventureReviewInput!\n ) {\n updateAdventureReview(\n adventureReviewId: $adventureReviewId\n adventureReviewInput: $adventureReviewInput\n ) {\n adventureReview {\n id\n rating\n content\n fulfillingMomentIds\n }\n }\n }\n`\nexport type GQL_UpdateAdventureReviewMutationFn = Apollo.MutationFunction<\n GQL_UpdateAdventureReviewMutation,\n GQL_UpdateAdventureReviewMutationVariables\n>\n\n/**\n * __useUpdateAdventureReviewMutation__\n *\n * To run a mutation, you first call `useUpdateAdventureReviewMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateAdventureReviewMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateAdventureReviewMutation, { data, loading, error }] = useUpdateAdventureReviewMutation({\n * variables: {\n * adventureReviewId: // value for 'adventureReviewId'\n * adventureReviewInput: // value for 'adventureReviewInput'\n * },\n * });\n */\nexport function useUpdateAdventureReviewMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdateAdventureReviewMutation,\n GQL_UpdateAdventureReviewMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdateAdventureReviewMutation,\n GQL_UpdateAdventureReviewMutationVariables\n >(UpdateAdventureReviewDocument, options)\n}\nexport type UpdateAdventureReviewMutationHookResult = ReturnType<\n typeof useUpdateAdventureReviewMutation\n>\nexport type UpdateAdventureReviewMutationResult = Apollo.MutationResult<\n GQL_UpdateAdventureReviewMutation\n>\nexport type UpdateAdventureReviewMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdateAdventureReviewMutation,\n GQL_UpdateAdventureReviewMutationVariables\n>\nexport const GetFulfillmentDataDocument = gql`\n query getFulfillmentData($bookingId: ID!) {\n booking(id: $bookingId) {\n id\n adventures {\n id\n }\n }\n fulfillingMoments {\n id\n slug\n name\n }\n }\n`\n\n/**\n * __useGetFulfillmentDataQuery__\n *\n * To run a query within a React component, call `useGetFulfillmentDataQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetFulfillmentDataQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetFulfillmentDataQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useGetFulfillmentDataQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetFulfillmentDataQuery,\n GQL_GetFulfillmentDataQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetFulfillmentDataQuery,\n GQL_GetFulfillmentDataQueryVariables\n >(GetFulfillmentDataDocument, options)\n}\nexport function useGetFulfillmentDataLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetFulfillmentDataQuery,\n GQL_GetFulfillmentDataQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetFulfillmentDataQuery,\n GQL_GetFulfillmentDataQueryVariables\n >(GetFulfillmentDataDocument, options)\n}\nexport type GetFulfillmentDataQueryHookResult = ReturnType<\n typeof useGetFulfillmentDataQuery\n>\nexport type GetFulfillmentDataLazyQueryHookResult = ReturnType<\n typeof useGetFulfillmentDataLazyQuery\n>\nexport type GetFulfillmentDataQueryResult = Apollo.QueryResult<\n GQL_GetFulfillmentDataQuery,\n GQL_GetFulfillmentDataQueryVariables\n>\nexport const BusinessLookupDocument = gql`\n query businessLookup($registrationNumber: String!, $country: Countries!) {\n businessLookup(registrationNumber: $registrationNumber, country: $country) {\n addressCity\n addressCountry\n addressLine1\n addressLine2\n addressPostcode\n addressState\n entityName\n entityType\n gstRegistered\n registrationNumber\n taxId\n tradingName\n }\n }\n`\n\n/**\n * __useBusinessLookupQuery__\n *\n * To run a query within a React component, call `useBusinessLookupQuery` and pass it any options that fit your needs.\n * When your component renders, `useBusinessLookupQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useBusinessLookupQuery({\n * variables: {\n * registrationNumber: // value for 'registrationNumber'\n * country: // value for 'country'\n * },\n * });\n */\nexport function useBusinessLookupQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_BusinessLookupQuery,\n GQL_BusinessLookupQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_BusinessLookupQuery,\n GQL_BusinessLookupQueryVariables\n >(BusinessLookupDocument, options)\n}\nexport function useBusinessLookupLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_BusinessLookupQuery,\n GQL_BusinessLookupQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_BusinessLookupQuery,\n GQL_BusinessLookupQueryVariables\n >(BusinessLookupDocument, options)\n}\nexport type BusinessLookupQueryHookResult = ReturnType<\n typeof useBusinessLookupQuery\n>\nexport type BusinessLookupLazyQueryHookResult = ReturnType<\n typeof useBusinessLookupLazyQuery\n>\nexport type BusinessLookupQueryResult = Apollo.QueryResult<\n GQL_BusinessLookupQuery,\n GQL_BusinessLookupQueryVariables\n>\nexport const CreateBankAccountDocument = gql`\n mutation createBankAccount($stripeToken: String!, $listingId: ID) {\n createBankAccount(stripeToken: $stripeToken, listingId: $listingId) {\n bankAccount {\n ...BankAccountFragment\n }\n }\n }\n ${BankAccountFragmentFragmentDoc}\n`\nexport type GQL_CreateBankAccountMutationFn = Apollo.MutationFunction<\n GQL_CreateBankAccountMutation,\n GQL_CreateBankAccountMutationVariables\n>\n\n/**\n * __useCreateBankAccountMutation__\n *\n * To run a mutation, you first call `useCreateBankAccountMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateBankAccountMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createBankAccountMutation, { data, loading, error }] = useCreateBankAccountMutation({\n * variables: {\n * stripeToken: // value for 'stripeToken'\n * listingId: // value for 'listingId'\n * },\n * });\n */\nexport function useCreateBankAccountMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateBankAccountMutation,\n GQL_CreateBankAccountMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateBankAccountMutation,\n GQL_CreateBankAccountMutationVariables\n >(CreateBankAccountDocument, options)\n}\nexport type CreateBankAccountMutationHookResult = ReturnType<\n typeof useCreateBankAccountMutation\n>\nexport type CreateBankAccountMutationResult = Apollo.MutationResult<\n GQL_CreateBankAccountMutation\n>\nexport type CreateBankAccountMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateBankAccountMutation,\n GQL_CreateBankAccountMutationVariables\n>\nexport const CreateCreditCardDocument = gql`\n mutation createCreditCard($stripeToken: String!) {\n createCreditCard(stripeToken: $stripeToken) {\n creditCard {\n ...CreditCardFields\n }\n }\n }\n ${CreditCardFieldsFragmentDoc}\n`\nexport type GQL_CreateCreditCardMutationFn = Apollo.MutationFunction<\n GQL_CreateCreditCardMutation,\n GQL_CreateCreditCardMutationVariables\n>\n\n/**\n * __useCreateCreditCardMutation__\n *\n * To run a mutation, you first call `useCreateCreditCardMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateCreditCardMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createCreditCardMutation, { data, loading, error }] = useCreateCreditCardMutation({\n * variables: {\n * stripeToken: // value for 'stripeToken'\n * },\n * });\n */\nexport function useCreateCreditCardMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateCreditCardMutation,\n GQL_CreateCreditCardMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateCreditCardMutation,\n GQL_CreateCreditCardMutationVariables\n >(CreateCreditCardDocument, options)\n}\nexport type CreateCreditCardMutationHookResult = ReturnType<\n typeof useCreateCreditCardMutation\n>\nexport type CreateCreditCardMutationResult = Apollo.MutationResult<\n GQL_CreateCreditCardMutation\n>\nexport type CreateCreditCardMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateCreditCardMutation,\n GQL_CreateCreditCardMutationVariables\n>\nexport const DeleteAccountDocument = gql`\n mutation DeleteAccount {\n deleteAccount {\n user {\n id\n }\n }\n }\n`\nexport type GQL_DeleteAccountMutationFn = Apollo.MutationFunction<\n GQL_DeleteAccountMutation,\n GQL_DeleteAccountMutationVariables\n>\n\n/**\n * __useDeleteAccountMutation__\n *\n * To run a mutation, you first call `useDeleteAccountMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteAccountMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteAccountMutation, { data, loading, error }] = useDeleteAccountMutation({\n * variables: {\n * },\n * });\n */\nexport function useDeleteAccountMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DeleteAccountMutation,\n GQL_DeleteAccountMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DeleteAccountMutation,\n GQL_DeleteAccountMutationVariables\n >(DeleteAccountDocument, options)\n}\nexport type DeleteAccountMutationHookResult = ReturnType<\n typeof useDeleteAccountMutation\n>\nexport type DeleteAccountMutationResult = Apollo.MutationResult<\n GQL_DeleteAccountMutation\n>\nexport type DeleteAccountMutationOptions = Apollo.BaseMutationOptions<\n GQL_DeleteAccountMutation,\n GQL_DeleteAccountMutationVariables\n>\nexport const DeleteCreditCardDocument = gql`\n mutation deleteCreditCard($creditCardId: ID!) {\n destroyCreditCard(creditCardId: $creditCardId) {\n creditCards {\n id\n }\n }\n }\n`\nexport type GQL_DeleteCreditCardMutationFn = Apollo.MutationFunction<\n GQL_DeleteCreditCardMutation,\n GQL_DeleteCreditCardMutationVariables\n>\n\n/**\n * __useDeleteCreditCardMutation__\n *\n * To run a mutation, you first call `useDeleteCreditCardMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteCreditCardMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteCreditCardMutation, { data, loading, error }] = useDeleteCreditCardMutation({\n * variables: {\n * creditCardId: // value for 'creditCardId'\n * },\n * });\n */\nexport function useDeleteCreditCardMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DeleteCreditCardMutation,\n GQL_DeleteCreditCardMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DeleteCreditCardMutation,\n GQL_DeleteCreditCardMutationVariables\n >(DeleteCreditCardDocument, options)\n}\nexport type DeleteCreditCardMutationHookResult = ReturnType<\n typeof useDeleteCreditCardMutation\n>\nexport type DeleteCreditCardMutationResult = Apollo.MutationResult<\n GQL_DeleteCreditCardMutation\n>\nexport type DeleteCreditCardMutationOptions = Apollo.BaseMutationOptions<\n GQL_DeleteCreditCardMutation,\n GQL_DeleteCreditCardMutationVariables\n>\nexport const DestroyBankAccountDocument = gql`\n mutation destroyBankAccount($bankAccountId: ID!) {\n destroyBankAccount(bankAccountId: $bankAccountId) {\n bankAccounts {\n id\n }\n }\n }\n`\nexport type GQL_DestroyBankAccountMutationFn = Apollo.MutationFunction<\n GQL_DestroyBankAccountMutation,\n GQL_DestroyBankAccountMutationVariables\n>\n\n/**\n * __useDestroyBankAccountMutation__\n *\n * To run a mutation, you first call `useDestroyBankAccountMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDestroyBankAccountMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [destroyBankAccountMutation, { data, loading, error }] = useDestroyBankAccountMutation({\n * variables: {\n * bankAccountId: // value for 'bankAccountId'\n * },\n * });\n */\nexport function useDestroyBankAccountMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DestroyBankAccountMutation,\n GQL_DestroyBankAccountMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DestroyBankAccountMutation,\n GQL_DestroyBankAccountMutationVariables\n >(DestroyBankAccountDocument, options)\n}\nexport type DestroyBankAccountMutationHookResult = ReturnType<\n typeof useDestroyBankAccountMutation\n>\nexport type DestroyBankAccountMutationResult = Apollo.MutationResult<\n GQL_DestroyBankAccountMutation\n>\nexport type DestroyBankAccountMutationOptions = Apollo.BaseMutationOptions<\n GQL_DestroyBankAccountMutation,\n GQL_DestroyBankAccountMutationVariables\n>\nexport const GetMyBankAccountsDocument = gql`\n query getMyBankAccounts {\n currentUser {\n id\n bankAccounts {\n ...BankAccountFragment\n }\n }\n }\n ${BankAccountFragmentFragmentDoc}\n`\n\n/**\n * __useGetMyBankAccountsQuery__\n *\n * To run a query within a React component, call `useGetMyBankAccountsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyBankAccountsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyBankAccountsQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetMyBankAccountsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetMyBankAccountsQuery,\n GQL_GetMyBankAccountsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyBankAccountsQuery,\n GQL_GetMyBankAccountsQueryVariables\n >(GetMyBankAccountsDocument, options)\n}\nexport function useGetMyBankAccountsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyBankAccountsQuery,\n GQL_GetMyBankAccountsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyBankAccountsQuery,\n GQL_GetMyBankAccountsQueryVariables\n >(GetMyBankAccountsDocument, options)\n}\nexport type GetMyBankAccountsQueryHookResult = ReturnType<\n typeof useGetMyBankAccountsQuery\n>\nexport type GetMyBankAccountsLazyQueryHookResult = ReturnType<\n typeof useGetMyBankAccountsLazyQuery\n>\nexport type GetMyBankAccountsQueryResult = Apollo.QueryResult<\n GQL_GetMyBankAccountsQuery,\n GQL_GetMyBankAccountsQueryVariables\n>\nexport const SetDefaultBankAccountDocument = gql`\n mutation setDefaultBankAccount($bankAccountId: ID!) {\n setDefaultBankAccount(bankAccountId: $bankAccountId) {\n bankAccount {\n id\n default\n }\n }\n }\n`\nexport type GQL_SetDefaultBankAccountMutationFn = Apollo.MutationFunction<\n GQL_SetDefaultBankAccountMutation,\n GQL_SetDefaultBankAccountMutationVariables\n>\n\n/**\n * __useSetDefaultBankAccountMutation__\n *\n * To run a mutation, you first call `useSetDefaultBankAccountMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useSetDefaultBankAccountMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [setDefaultBankAccountMutation, { data, loading, error }] = useSetDefaultBankAccountMutation({\n * variables: {\n * bankAccountId: // value for 'bankAccountId'\n * },\n * });\n */\nexport function useSetDefaultBankAccountMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_SetDefaultBankAccountMutation,\n GQL_SetDefaultBankAccountMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_SetDefaultBankAccountMutation,\n GQL_SetDefaultBankAccountMutationVariables\n >(SetDefaultBankAccountDocument, options)\n}\nexport type SetDefaultBankAccountMutationHookResult = ReturnType<\n typeof useSetDefaultBankAccountMutation\n>\nexport type SetDefaultBankAccountMutationResult = Apollo.MutationResult<\n GQL_SetDefaultBankAccountMutation\n>\nexport type SetDefaultBankAccountMutationOptions = Apollo.BaseMutationOptions<\n GQL_SetDefaultBankAccountMutation,\n GQL_SetDefaultBankAccountMutationVariables\n>\nexport const SetDefaultCreditCardDocument = gql`\n mutation setDefaultCreditCard($creditCardId: ID!) {\n setDefaultCreditCard(creditCardId: $creditCardId) {\n creditCard {\n id\n default\n }\n }\n }\n`\nexport type GQL_SetDefaultCreditCardMutationFn = Apollo.MutationFunction<\n GQL_SetDefaultCreditCardMutation,\n GQL_SetDefaultCreditCardMutationVariables\n>\n\n/**\n * __useSetDefaultCreditCardMutation__\n *\n * To run a mutation, you first call `useSetDefaultCreditCardMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useSetDefaultCreditCardMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [setDefaultCreditCardMutation, { data, loading, error }] = useSetDefaultCreditCardMutation({\n * variables: {\n * creditCardId: // value for 'creditCardId'\n * },\n * });\n */\nexport function useSetDefaultCreditCardMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_SetDefaultCreditCardMutation,\n GQL_SetDefaultCreditCardMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_SetDefaultCreditCardMutation,\n GQL_SetDefaultCreditCardMutationVariables\n >(SetDefaultCreditCardDocument, options)\n}\nexport type SetDefaultCreditCardMutationHookResult = ReturnType<\n typeof useSetDefaultCreditCardMutation\n>\nexport type SetDefaultCreditCardMutationResult = Apollo.MutationResult<\n GQL_SetDefaultCreditCardMutation\n>\nexport type SetDefaultCreditCardMutationOptions = Apollo.BaseMutationOptions<\n GQL_SetDefaultCreditCardMutation,\n GQL_SetDefaultCreditCardMutationVariables\n>\nexport const UpdatePasswordDocument = gql`\n mutation updatePassword(\n $currentPassword: String!\n $newPassword: String!\n $confirmPassword: String!\n ) {\n updatePassword(\n currentPassword: $currentPassword\n newPassword: $newPassword\n confirmPassword: $confirmPassword\n ) {\n user {\n id\n }\n }\n }\n`\nexport type GQL_UpdatePasswordMutationFn = Apollo.MutationFunction<\n GQL_UpdatePasswordMutation,\n GQL_UpdatePasswordMutationVariables\n>\n\n/**\n * __useUpdatePasswordMutation__\n *\n * To run a mutation, you first call `useUpdatePasswordMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdatePasswordMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updatePasswordMutation, { data, loading, error }] = useUpdatePasswordMutation({\n * variables: {\n * currentPassword: // value for 'currentPassword'\n * newPassword: // value for 'newPassword'\n * confirmPassword: // value for 'confirmPassword'\n * },\n * });\n */\nexport function useUpdatePasswordMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdatePasswordMutation,\n GQL_UpdatePasswordMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdatePasswordMutation,\n GQL_UpdatePasswordMutationVariables\n >(UpdatePasswordDocument, options)\n}\nexport type UpdatePasswordMutationHookResult = ReturnType<\n typeof useUpdatePasswordMutation\n>\nexport type UpdatePasswordMutationResult = Apollo.MutationResult<\n GQL_UpdatePasswordMutation\n>\nexport type UpdatePasswordMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdatePasswordMutation,\n GQL_UpdatePasswordMutationVariables\n>\nexport const UserCreditCardsDocument = gql`\n query userCreditCards {\n currentUser {\n id\n creditCards {\n ...CreditCardFields\n }\n }\n }\n ${CreditCardFieldsFragmentDoc}\n`\n\n/**\n * __useUserCreditCardsQuery__\n *\n * To run a query within a React component, call `useUserCreditCardsQuery` and pass it any options that fit your needs.\n * When your component renders, `useUserCreditCardsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useUserCreditCardsQuery({\n * variables: {\n * },\n * });\n */\nexport function useUserCreditCardsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_UserCreditCardsQuery,\n GQL_UserCreditCardsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_UserCreditCardsQuery,\n GQL_UserCreditCardsQueryVariables\n >(UserCreditCardsDocument, options)\n}\nexport function useUserCreditCardsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_UserCreditCardsQuery,\n GQL_UserCreditCardsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_UserCreditCardsQuery,\n GQL_UserCreditCardsQueryVariables\n >(UserCreditCardsDocument, options)\n}\nexport type UserCreditCardsQueryHookResult = ReturnType<\n typeof useUserCreditCardsQuery\n>\nexport type UserCreditCardsLazyQueryHookResult = ReturnType<\n typeof useUserCreditCardsLazyQuery\n>\nexport type UserCreditCardsQueryResult = Apollo.QueryResult<\n GQL_UserCreditCardsQuery,\n GQL_UserCreditCardsQueryVariables\n>\nexport const AcceptAssignmentDocument = gql`\n mutation acceptAssignment(\n $id: ID!\n $assignmentInput: AcceptAssignmentInput!\n ) {\n acceptAssignment(assignmentId: $id, assignmentInput: $assignmentInput) {\n assignment {\n ...Assignment\n ...AssignmentBookingField\n ...AssignmentListingsField\n }\n }\n }\n ${AssignmentFragmentDoc}\n ${AssignmentBookingFieldFragmentDoc}\n ${AssignmentListingsFieldFragmentDoc}\n`\nexport type GQL_AcceptAssignmentMutationFn = Apollo.MutationFunction<\n GQL_AcceptAssignmentMutation,\n GQL_AcceptAssignmentMutationVariables\n>\n\n/**\n * __useAcceptAssignmentMutation__\n *\n * To run a mutation, you first call `useAcceptAssignmentMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useAcceptAssignmentMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [acceptAssignmentMutation, { data, loading, error }] = useAcceptAssignmentMutation({\n * variables: {\n * id: // value for 'id'\n * assignmentInput: // value for 'assignmentInput'\n * },\n * });\n */\nexport function useAcceptAssignmentMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_AcceptAssignmentMutation,\n GQL_AcceptAssignmentMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_AcceptAssignmentMutation,\n GQL_AcceptAssignmentMutationVariables\n >(AcceptAssignmentDocument, options)\n}\nexport type AcceptAssignmentMutationHookResult = ReturnType<\n typeof useAcceptAssignmentMutation\n>\nexport type AcceptAssignmentMutationResult = Apollo.MutationResult<\n GQL_AcceptAssignmentMutation\n>\nexport type AcceptAssignmentMutationOptions = Apollo.BaseMutationOptions<\n GQL_AcceptAssignmentMutation,\n GQL_AcceptAssignmentMutationVariables\n>\nexport const DeclineAssignmentDocument = gql`\n mutation declineAssignment($id: ID!, $reason: String, $explanation: String) {\n declineAssignment(\n assignmentId: $id\n reason: $reason\n explanation: $explanation\n ) {\n assignment {\n ...Assignment\n }\n }\n }\n ${AssignmentFragmentDoc}\n`\nexport type GQL_DeclineAssignmentMutationFn = Apollo.MutationFunction<\n GQL_DeclineAssignmentMutation,\n GQL_DeclineAssignmentMutationVariables\n>\n\n/**\n * __useDeclineAssignmentMutation__\n *\n * To run a mutation, you first call `useDeclineAssignmentMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeclineAssignmentMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [declineAssignmentMutation, { data, loading, error }] = useDeclineAssignmentMutation({\n * variables: {\n * id: // value for 'id'\n * reason: // value for 'reason'\n * explanation: // value for 'explanation'\n * },\n * });\n */\nexport function useDeclineAssignmentMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DeclineAssignmentMutation,\n GQL_DeclineAssignmentMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DeclineAssignmentMutation,\n GQL_DeclineAssignmentMutationVariables\n >(DeclineAssignmentDocument, options)\n}\nexport type DeclineAssignmentMutationHookResult = ReturnType<\n typeof useDeclineAssignmentMutation\n>\nexport type DeclineAssignmentMutationResult = Apollo.MutationResult<\n GQL_DeclineAssignmentMutation\n>\nexport type DeclineAssignmentMutationOptions = Apollo.BaseMutationOptions<\n GQL_DeclineAssignmentMutation,\n GQL_DeclineAssignmentMutationVariables\n>\nexport const GetMyAssignmentsDocument = gql`\n query getMyAssignments {\n currentUser {\n id\n assignments {\n ...Assignment\n ...AssignmentBookingField\n ...AssignmentListingsField\n }\n }\n }\n ${AssignmentFragmentDoc}\n ${AssignmentBookingFieldFragmentDoc}\n ${AssignmentListingsFieldFragmentDoc}\n`\n\n/**\n * __useGetMyAssignmentsQuery__\n *\n * To run a query within a React component, call `useGetMyAssignmentsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyAssignmentsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyAssignmentsQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetMyAssignmentsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetMyAssignmentsQuery,\n GQL_GetMyAssignmentsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyAssignmentsQuery,\n GQL_GetMyAssignmentsQueryVariables\n >(GetMyAssignmentsDocument, options)\n}\nexport function useGetMyAssignmentsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyAssignmentsQuery,\n GQL_GetMyAssignmentsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyAssignmentsQuery,\n GQL_GetMyAssignmentsQueryVariables\n >(GetMyAssignmentsDocument, options)\n}\nexport type GetMyAssignmentsQueryHookResult = ReturnType<\n typeof useGetMyAssignmentsQuery\n>\nexport type GetMyAssignmentsLazyQueryHookResult = ReturnType<\n typeof useGetMyAssignmentsLazyQuery\n>\nexport type GetMyAssignmentsQueryResult = Apollo.QueryResult<\n GQL_GetMyAssignmentsQuery,\n GQL_GetMyAssignmentsQueryVariables\n>\nexport const GuestListDocument = gql`\n query guestList($bookingId: ID!) {\n booking(id: $bookingId) {\n id\n totalGuests\n guests {\n firstName\n lastName\n phoneNumber\n postcode\n }\n }\n }\n`\n\n/**\n * __useGuestListQuery__\n *\n * To run a query within a React component, call `useGuestListQuery` and pass it any options that fit your needs.\n * When your component renders, `useGuestListQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGuestListQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useGuestListQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GuestListQuery,\n GQL_GuestListQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n GuestListDocument,\n options\n )\n}\nexport function useGuestListLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GuestListQuery,\n GQL_GuestListQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery(\n GuestListDocument,\n options\n )\n}\nexport type GuestListQueryHookResult = ReturnType\nexport type GuestListLazyQueryHookResult = ReturnType<\n typeof useGuestListLazyQuery\n>\nexport type GuestListQueryResult = Apollo.QueryResult<\n GQL_GuestListQuery,\n GQL_GuestListQueryVariables\n>\nexport const HpcFailedDocument = gql`\n query hpcFailed($bookingId: ID!) {\n booking(id: $bookingId) {\n id\n listing {\n id\n title\n }\n guests {\n hpcStatus\n }\n conversation {\n id\n }\n }\n }\n`\n\n/**\n * __useHpcFailedQuery__\n *\n * To run a query within a React component, call `useHpcFailedQuery` and pass it any options that fit your needs.\n * When your component renders, `useHpcFailedQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useHpcFailedQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useHpcFailedQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_HpcFailedQuery,\n GQL_HpcFailedQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n HpcFailedDocument,\n options\n )\n}\nexport function useHpcFailedLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_HpcFailedQuery,\n GQL_HpcFailedQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery(\n HpcFailedDocument,\n options\n )\n}\nexport type HpcFailedQueryHookResult = ReturnType\nexport type HpcFailedLazyQueryHookResult = ReturnType<\n typeof useHpcFailedLazyQuery\n>\nexport type HpcFailedQueryResult = Apollo.QueryResult<\n GQL_HpcFailedQuery,\n GQL_HpcFailedQueryVariables\n>\nexport const UpdateGuestListDocument = gql`\n mutation updateGuestList($bookingId: ID!, $guestsInputs: [GuestInput!]!) {\n updateGuestList(bookingId: $bookingId, guestInputs: $guestsInputs) {\n booking {\n id\n totalGuests\n guests {\n firstName\n lastName\n phoneNumber\n postcode\n }\n hpcStatus\n }\n }\n }\n`\nexport type GQL_UpdateGuestListMutationFn = Apollo.MutationFunction<\n GQL_UpdateGuestListMutation,\n GQL_UpdateGuestListMutationVariables\n>\n\n/**\n * __useUpdateGuestListMutation__\n *\n * To run a mutation, you first call `useUpdateGuestListMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateGuestListMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateGuestListMutation, { data, loading, error }] = useUpdateGuestListMutation({\n * variables: {\n * bookingId: // value for 'bookingId'\n * guestsInputs: // value for 'guestsInputs'\n * },\n * });\n */\nexport function useUpdateGuestListMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdateGuestListMutation,\n GQL_UpdateGuestListMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdateGuestListMutation,\n GQL_UpdateGuestListMutationVariables\n >(UpdateGuestListDocument, options)\n}\nexport type UpdateGuestListMutationHookResult = ReturnType<\n typeof useUpdateGuestListMutation\n>\nexport type UpdateGuestListMutationResult = Apollo.MutationResult<\n GQL_UpdateGuestListMutation\n>\nexport type UpdateGuestListMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdateGuestListMutation,\n GQL_UpdateGuestListMutationVariables\n>\nexport const CopyBookingAdventuresDocument = gql`\n mutation copyBookingAdventures(\n $bookingId: ID!\n $bucketListId: ID!\n $source: String\n ) {\n copyBookingAdventures(\n bookingId: $bookingId\n bucketListId: $bucketListId\n source: $source\n ) {\n adventures {\n id\n }\n }\n }\n`\nexport type GQL_CopyBookingAdventuresMutationFn = Apollo.MutationFunction<\n GQL_CopyBookingAdventuresMutation,\n GQL_CopyBookingAdventuresMutationVariables\n>\n\n/**\n * __useCopyBookingAdventuresMutation__\n *\n * To run a mutation, you first call `useCopyBookingAdventuresMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCopyBookingAdventuresMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [copyBookingAdventuresMutation, { data, loading, error }] = useCopyBookingAdventuresMutation({\n * variables: {\n * bookingId: // value for 'bookingId'\n * bucketListId: // value for 'bucketListId'\n * source: // value for 'source'\n * },\n * });\n */\nexport function useCopyBookingAdventuresMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CopyBookingAdventuresMutation,\n GQL_CopyBookingAdventuresMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CopyBookingAdventuresMutation,\n GQL_CopyBookingAdventuresMutationVariables\n >(CopyBookingAdventuresDocument, options)\n}\nexport type CopyBookingAdventuresMutationHookResult = ReturnType<\n typeof useCopyBookingAdventuresMutation\n>\nexport type CopyBookingAdventuresMutationResult = Apollo.MutationResult<\n GQL_CopyBookingAdventuresMutation\n>\nexport type CopyBookingAdventuresMutationOptions = Apollo.BaseMutationOptions<\n GQL_CopyBookingAdventuresMutation,\n GQL_CopyBookingAdventuresMutationVariables\n>\nexport const UpdateBookingPromptedToAddAdventuresDocument = gql`\n mutation updateBookingPromptedToAddAdventures($bookingId: ID!) {\n updateBooking(\n bookingId: $bookingId\n bookingInput: { promptedToAddAdventures: true }\n ) {\n booking {\n id\n promptedToAddAdventures\n }\n }\n }\n`\nexport type GQL_UpdateBookingPromptedToAddAdventuresMutationFn = Apollo.MutationFunction<\n GQL_UpdateBookingPromptedToAddAdventuresMutation,\n GQL_UpdateBookingPromptedToAddAdventuresMutationVariables\n>\n\n/**\n * __useUpdateBookingPromptedToAddAdventuresMutation__\n *\n * To run a mutation, you first call `useUpdateBookingPromptedToAddAdventuresMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateBookingPromptedToAddAdventuresMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateBookingPromptedToAddAdventuresMutation, { data, loading, error }] = useUpdateBookingPromptedToAddAdventuresMutation({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useUpdateBookingPromptedToAddAdventuresMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdateBookingPromptedToAddAdventuresMutation,\n GQL_UpdateBookingPromptedToAddAdventuresMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdateBookingPromptedToAddAdventuresMutation,\n GQL_UpdateBookingPromptedToAddAdventuresMutationVariables\n >(UpdateBookingPromptedToAddAdventuresDocument, options)\n}\nexport type UpdateBookingPromptedToAddAdventuresMutationHookResult = ReturnType<\n typeof useUpdateBookingPromptedToAddAdventuresMutation\n>\nexport type UpdateBookingPromptedToAddAdventuresMutationResult = Apollo.MutationResult<\n GQL_UpdateBookingPromptedToAddAdventuresMutation\n>\nexport type UpdateBookingPromptedToAddAdventuresMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdateBookingPromptedToAddAdventuresMutation,\n GQL_UpdateBookingPromptedToAddAdventuresMutationVariables\n>\nexport const AddAdventureToBookingDocument = gql`\n mutation addAdventureToBooking(\n $bookingId: ID!\n $adventureId: ID!\n $source: String\n ) {\n createBookingAdventure(\n bookingId: $bookingId\n adventureId: $adventureId\n source: $source\n ) {\n adventure {\n id\n }\n }\n }\n`\nexport type GQL_AddAdventureToBookingMutationFn = Apollo.MutationFunction<\n GQL_AddAdventureToBookingMutation,\n GQL_AddAdventureToBookingMutationVariables\n>\n\n/**\n * __useAddAdventureToBookingMutation__\n *\n * To run a mutation, you first call `useAddAdventureToBookingMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useAddAdventureToBookingMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [addAdventureToBookingMutation, { data, loading, error }] = useAddAdventureToBookingMutation({\n * variables: {\n * bookingId: // value for 'bookingId'\n * adventureId: // value for 'adventureId'\n * source: // value for 'source'\n * },\n * });\n */\nexport function useAddAdventureToBookingMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_AddAdventureToBookingMutation,\n GQL_AddAdventureToBookingMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_AddAdventureToBookingMutation,\n GQL_AddAdventureToBookingMutationVariables\n >(AddAdventureToBookingDocument, options)\n}\nexport type AddAdventureToBookingMutationHookResult = ReturnType<\n typeof useAddAdventureToBookingMutation\n>\nexport type AddAdventureToBookingMutationResult = Apollo.MutationResult<\n GQL_AddAdventureToBookingMutation\n>\nexport type AddAdventureToBookingMutationOptions = Apollo.BaseMutationOptions<\n GQL_AddAdventureToBookingMutation,\n GQL_AddAdventureToBookingMutationVariables\n>\nexport const GetAdventureDocument = gql`\n query getAdventure($adventureId: ID!) {\n adventure(id: $adventureId) {\n id\n description\n locationType\n title\n reviewScore\n location {\n name\n lat\n lng\n }\n adventureType {\n id\n name\n slug\n category\n }\n ...AdventureCardFragment\n }\n }\n ${AdventureCardFragmentFragmentDoc}\n`\n\n/**\n * __useGetAdventureQuery__\n *\n * To run a query within a React component, call `useGetAdventureQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetAdventureQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetAdventureQuery({\n * variables: {\n * adventureId: // value for 'adventureId'\n * },\n * });\n */\nexport function useGetAdventureQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetAdventureQuery,\n GQL_GetAdventureQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n GetAdventureDocument,\n options\n )\n}\nexport function useGetAdventureLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetAdventureQuery,\n GQL_GetAdventureQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetAdventureQuery,\n GQL_GetAdventureQueryVariables\n >(GetAdventureDocument, options)\n}\nexport type GetAdventureQueryHookResult = ReturnType<\n typeof useGetAdventureQuery\n>\nexport type GetAdventureLazyQueryHookResult = ReturnType<\n typeof useGetAdventureLazyQuery\n>\nexport type GetAdventureQueryResult = Apollo.QueryResult<\n GQL_GetAdventureQuery,\n GQL_GetAdventureQueryVariables\n>\nexport const GetBookingAdventuresDocument = gql`\n query getBookingAdventures($bookingId: ID!) {\n booking(id: $bookingId) {\n id\n adventures {\n id\n }\n }\n }\n`\n\n/**\n * __useGetBookingAdventuresQuery__\n *\n * To run a query within a React component, call `useGetBookingAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBookingAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBookingAdventuresQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useGetBookingAdventuresQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBookingAdventuresQuery,\n GQL_GetBookingAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBookingAdventuresQuery,\n GQL_GetBookingAdventuresQueryVariables\n >(GetBookingAdventuresDocument, options)\n}\nexport function useGetBookingAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBookingAdventuresQuery,\n GQL_GetBookingAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBookingAdventuresQuery,\n GQL_GetBookingAdventuresQueryVariables\n >(GetBookingAdventuresDocument, options)\n}\nexport type GetBookingAdventuresQueryHookResult = ReturnType<\n typeof useGetBookingAdventuresQuery\n>\nexport type GetBookingAdventuresLazyQueryHookResult = ReturnType<\n typeof useGetBookingAdventuresLazyQuery\n>\nexport type GetBookingAdventuresQueryResult = Apollo.QueryResult<\n GQL_GetBookingAdventuresQuery,\n GQL_GetBookingAdventuresQueryVariables\n>\nexport const GetBookingAdventuresIndexDocument = gql`\n query getBookingAdventuresIndex {\n currentUser {\n id\n bookingAdventuresIndex\n }\n }\n`\n\n/**\n * __useGetBookingAdventuresIndexQuery__\n *\n * To run a query within a React component, call `useGetBookingAdventuresIndexQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBookingAdventuresIndexQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBookingAdventuresIndexQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetBookingAdventuresIndexQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetBookingAdventuresIndexQuery,\n GQL_GetBookingAdventuresIndexQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBookingAdventuresIndexQuery,\n GQL_GetBookingAdventuresIndexQueryVariables\n >(GetBookingAdventuresIndexDocument, options)\n}\nexport function useGetBookingAdventuresIndexLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBookingAdventuresIndexQuery,\n GQL_GetBookingAdventuresIndexQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBookingAdventuresIndexQuery,\n GQL_GetBookingAdventuresIndexQueryVariables\n >(GetBookingAdventuresIndexDocument, options)\n}\nexport type GetBookingAdventuresIndexQueryHookResult = ReturnType<\n typeof useGetBookingAdventuresIndexQuery\n>\nexport type GetBookingAdventuresIndexLazyQueryHookResult = ReturnType<\n typeof useGetBookingAdventuresIndexLazyQuery\n>\nexport type GetBookingAdventuresIndexQueryResult = Apollo.QueryResult<\n GQL_GetBookingAdventuresIndexQuery,\n GQL_GetBookingAdventuresIndexQueryVariables\n>\nexport const GetBookingItineraryDocument = gql`\n query getBookingItinerary($bookingId: ID!) {\n booking(id: $bookingId) {\n id\n joinUrl\n role\n promptedToAddAdventures\n startDate\n travelCrew {\n id\n firstName\n avatar {\n original\n thumbLg\n thumbMd\n }\n }\n listing {\n id\n url\n coordinates\n subcategory {\n id\n slug\n }\n listingType {\n id\n slug\n }\n title\n city\n region {\n id\n name\n }\n location {\n name\n lat\n lng\n }\n state\n coordinates\n promoImage {\n medium\n large\n }\n }\n story {\n id\n promoImage {\n medium\n large\n }\n user {\n firstName\n avatar {\n original\n thumbLg\n }\n }\n }\n adventures {\n ... on StoryAdventure {\n ...AdventureCardFragment\n }\n ... on ListingAdventure {\n id\n adventureType {\n id\n slug\n }\n location {\n lat\n lng\n }\n }\n }\n }\n }\n ${AdventureCardFragmentFragmentDoc}\n`\n\n/**\n * __useGetBookingItineraryQuery__\n *\n * To run a query within a React component, call `useGetBookingItineraryQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBookingItineraryQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBookingItineraryQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useGetBookingItineraryQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBookingItineraryQuery,\n GQL_GetBookingItineraryQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBookingItineraryQuery,\n GQL_GetBookingItineraryQueryVariables\n >(GetBookingItineraryDocument, options)\n}\nexport function useGetBookingItineraryLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBookingItineraryQuery,\n GQL_GetBookingItineraryQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBookingItineraryQuery,\n GQL_GetBookingItineraryQueryVariables\n >(GetBookingItineraryDocument, options)\n}\nexport type GetBookingItineraryQueryHookResult = ReturnType<\n typeof useGetBookingItineraryQuery\n>\nexport type GetBookingItineraryLazyQueryHookResult = ReturnType<\n typeof useGetBookingItineraryLazyQuery\n>\nexport type GetBookingItineraryQueryResult = Apollo.QueryResult<\n GQL_GetBookingItineraryQuery,\n GQL_GetBookingItineraryQueryVariables\n>\nexport const GetBookingListingDocument = gql`\n query getBookingListing($bookingId: ID!) {\n booking(id: $bookingId) {\n id\n listing {\n id\n url\n coordinates\n subcategory {\n id\n slug\n }\n listingType {\n id\n slug\n }\n title\n city\n region {\n id\n name\n }\n state\n coordinates\n promoImage {\n medium\n large\n }\n }\n }\n }\n`\n\n/**\n * __useGetBookingListingQuery__\n *\n * To run a query within a React component, call `useGetBookingListingQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBookingListingQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBookingListingQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useGetBookingListingQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBookingListingQuery,\n GQL_GetBookingListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBookingListingQuery,\n GQL_GetBookingListingQueryVariables\n >(GetBookingListingDocument, options)\n}\nexport function useGetBookingListingLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBookingListingQuery,\n GQL_GetBookingListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBookingListingQuery,\n GQL_GetBookingListingQueryVariables\n >(GetBookingListingDocument, options)\n}\nexport type GetBookingListingQueryHookResult = ReturnType<\n typeof useGetBookingListingQuery\n>\nexport type GetBookingListingLazyQueryHookResult = ReturnType<\n typeof useGetBookingListingLazyQuery\n>\nexport type GetBookingListingQueryResult = Apollo.QueryResult<\n GQL_GetBookingListingQuery,\n GQL_GetBookingListingQueryVariables\n>\nexport const GetBookingNearbyAdventuresDocument = gql`\n query getBookingNearbyAdventures(\n $bookingId: ID!\n $pageSize: Int = 4\n $cursor: String\n ) {\n booking(id: $bookingId) {\n id\n listing {\n id\n country {\n id\n code\n }\n state\n nearbyAdventures(first: $pageSize, after: $cursor, sourceType: Story) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n ...AdventureCardFragment\n }\n }\n }\n }\n }\n }\n ${AdventureCardFragmentFragmentDoc}\n`\n\n/**\n * __useGetBookingNearbyAdventuresQuery__\n *\n * To run a query within a React component, call `useGetBookingNearbyAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBookingNearbyAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBookingNearbyAdventuresQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * pageSize: // value for 'pageSize'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetBookingNearbyAdventuresQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBookingNearbyAdventuresQuery,\n GQL_GetBookingNearbyAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBookingNearbyAdventuresQuery,\n GQL_GetBookingNearbyAdventuresQueryVariables\n >(GetBookingNearbyAdventuresDocument, options)\n}\nexport function useGetBookingNearbyAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBookingNearbyAdventuresQuery,\n GQL_GetBookingNearbyAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBookingNearbyAdventuresQuery,\n GQL_GetBookingNearbyAdventuresQueryVariables\n >(GetBookingNearbyAdventuresDocument, options)\n}\nexport type GetBookingNearbyAdventuresQueryHookResult = ReturnType<\n typeof useGetBookingNearbyAdventuresQuery\n>\nexport type GetBookingNearbyAdventuresLazyQueryHookResult = ReturnType<\n typeof useGetBookingNearbyAdventuresLazyQuery\n>\nexport type GetBookingNearbyAdventuresQueryResult = Apollo.QueryResult<\n GQL_GetBookingNearbyAdventuresQuery,\n GQL_GetBookingNearbyAdventuresQueryVariables\n>\nexport const GetBookingSuggestedAdventuresDocument = gql`\n query getBookingSuggestedAdventures(\n $bookingId: ID!\n $pageSize: Int = 4\n $cursor: String\n ) {\n booking(id: $bookingId) {\n id\n suggestedAdventures(first: $pageSize, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n ...AdventureCardFragment\n }\n }\n }\n }\n }\n ${AdventureCardFragmentFragmentDoc}\n`\n\n/**\n * __useGetBookingSuggestedAdventuresQuery__\n *\n * To run a query within a React component, call `useGetBookingSuggestedAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBookingSuggestedAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBookingSuggestedAdventuresQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * pageSize: // value for 'pageSize'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetBookingSuggestedAdventuresQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBookingSuggestedAdventuresQuery,\n GQL_GetBookingSuggestedAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBookingSuggestedAdventuresQuery,\n GQL_GetBookingSuggestedAdventuresQueryVariables\n >(GetBookingSuggestedAdventuresDocument, options)\n}\nexport function useGetBookingSuggestedAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBookingSuggestedAdventuresQuery,\n GQL_GetBookingSuggestedAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBookingSuggestedAdventuresQuery,\n GQL_GetBookingSuggestedAdventuresQueryVariables\n >(GetBookingSuggestedAdventuresDocument, options)\n}\nexport type GetBookingSuggestedAdventuresQueryHookResult = ReturnType<\n typeof useGetBookingSuggestedAdventuresQuery\n>\nexport type GetBookingSuggestedAdventuresLazyQueryHookResult = ReturnType<\n typeof useGetBookingSuggestedAdventuresLazyQuery\n>\nexport type GetBookingSuggestedAdventuresQueryResult = Apollo.QueryResult<\n GQL_GetBookingSuggestedAdventuresQuery,\n GQL_GetBookingSuggestedAdventuresQueryVariables\n>\nexport const GetMapNearbyAdventuresDocument = gql`\n query getMapNearbyAdventures($bookingId: ID!) {\n booking(id: $bookingId) {\n id\n listing {\n id\n coordinates\n subcategory {\n id\n slug\n }\n listingType {\n id\n slug\n }\n ...ListingCardFragment\n allNearbyAdventures(sourceType: Story) {\n id\n adventureType {\n id\n slug\n }\n location {\n lat\n lng\n }\n }\n }\n }\n }\n ${ListingCardFragmentFragmentDoc}\n`\n\n/**\n * __useGetMapNearbyAdventuresQuery__\n *\n * To run a query within a React component, call `useGetMapNearbyAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMapNearbyAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMapNearbyAdventuresQuery({\n * variables: {\n * bookingId: // value for 'bookingId'\n * },\n * });\n */\nexport function useGetMapNearbyAdventuresQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetMapNearbyAdventuresQuery,\n GQL_GetMapNearbyAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMapNearbyAdventuresQuery,\n GQL_GetMapNearbyAdventuresQueryVariables\n >(GetMapNearbyAdventuresDocument, options)\n}\nexport function useGetMapNearbyAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMapNearbyAdventuresQuery,\n GQL_GetMapNearbyAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMapNearbyAdventuresQuery,\n GQL_GetMapNearbyAdventuresQueryVariables\n >(GetMapNearbyAdventuresDocument, options)\n}\nexport type GetMapNearbyAdventuresQueryHookResult = ReturnType<\n typeof useGetMapNearbyAdventuresQuery\n>\nexport type GetMapNearbyAdventuresLazyQueryHookResult = ReturnType<\n typeof useGetMapNearbyAdventuresLazyQuery\n>\nexport type GetMapNearbyAdventuresQueryResult = Apollo.QueryResult<\n GQL_GetMapNearbyAdventuresQuery,\n GQL_GetMapNearbyAdventuresQueryVariables\n>\nexport const RemoveAdventureFromBookingDocument = gql`\n mutation removeAdventureFromBooking($bookingId: ID!, $adventureId: ID!) {\n destroyBookingAdventure(bookingId: $bookingId, adventureId: $adventureId) {\n adventures {\n id\n }\n }\n }\n`\nexport type GQL_RemoveAdventureFromBookingMutationFn = Apollo.MutationFunction<\n GQL_RemoveAdventureFromBookingMutation,\n GQL_RemoveAdventureFromBookingMutationVariables\n>\n\n/**\n * __useRemoveAdventureFromBookingMutation__\n *\n * To run a mutation, you first call `useRemoveAdventureFromBookingMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useRemoveAdventureFromBookingMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [removeAdventureFromBookingMutation, { data, loading, error }] = useRemoveAdventureFromBookingMutation({\n * variables: {\n * bookingId: // value for 'bookingId'\n * adventureId: // value for 'adventureId'\n * },\n * });\n */\nexport function useRemoveAdventureFromBookingMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_RemoveAdventureFromBookingMutation,\n GQL_RemoveAdventureFromBookingMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_RemoveAdventureFromBookingMutation,\n GQL_RemoveAdventureFromBookingMutationVariables\n >(RemoveAdventureFromBookingDocument, options)\n}\nexport type RemoveAdventureFromBookingMutationHookResult = ReturnType<\n typeof useRemoveAdventureFromBookingMutation\n>\nexport type RemoveAdventureFromBookingMutationResult = Apollo.MutationResult<\n GQL_RemoveAdventureFromBookingMutation\n>\nexport type RemoveAdventureFromBookingMutationOptions = Apollo.BaseMutationOptions<\n GQL_RemoveAdventureFromBookingMutation,\n GQL_RemoveAdventureFromBookingMutationVariables\n>\nexport const GetMyBucketListDocument = gql`\n query getMyBucketList($id: ID) {\n currentUser {\n id\n bucketList(id: $id) {\n ...BucketListFragment\n publicUrl\n }\n }\n }\n ${BucketListFragmentFragmentDoc}\n`\n\n/**\n * __useGetMyBucketListQuery__\n *\n * To run a query within a React component, call `useGetMyBucketListQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyBucketListQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyBucketListQuery({\n * variables: {\n * id: // value for 'id'\n * },\n * });\n */\nexport function useGetMyBucketListQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetMyBucketListQuery,\n GQL_GetMyBucketListQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyBucketListQuery,\n GQL_GetMyBucketListQueryVariables\n >(GetMyBucketListDocument, options)\n}\nexport function useGetMyBucketListLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyBucketListQuery,\n GQL_GetMyBucketListQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyBucketListQuery,\n GQL_GetMyBucketListQueryVariables\n >(GetMyBucketListDocument, options)\n}\nexport type GetMyBucketListQueryHookResult = ReturnType<\n typeof useGetMyBucketListQuery\n>\nexport type GetMyBucketListLazyQueryHookResult = ReturnType<\n typeof useGetMyBucketListLazyQuery\n>\nexport type GetMyBucketListQueryResult = Apollo.QueryResult<\n GQL_GetMyBucketListQuery,\n GQL_GetMyBucketListQueryVariables\n>\nexport const GetMyBucketListItemsDocument = gql`\n query getMyBucketListItems(\n $id: ID\n $params: SearchFilters\n $first: Int\n $cursor: String\n ) {\n currentUser {\n id\n bucketList(id: $id) {\n id\n items(params: $params, first: $first, after: $cursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n ...BucketListItemConnection\n }\n }\n }\n }\n ${BucketListItemConnectionFragmentDoc}\n`\n\n/**\n * __useGetMyBucketListItemsQuery__\n *\n * To run a query within a React component, call `useGetMyBucketListItemsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyBucketListItemsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyBucketListItemsQuery({\n * variables: {\n * id: // value for 'id'\n * params: // value for 'params'\n * first: // value for 'first'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetMyBucketListItemsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetMyBucketListItemsQuery,\n GQL_GetMyBucketListItemsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyBucketListItemsQuery,\n GQL_GetMyBucketListItemsQueryVariables\n >(GetMyBucketListItemsDocument, options)\n}\nexport function useGetMyBucketListItemsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyBucketListItemsQuery,\n GQL_GetMyBucketListItemsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyBucketListItemsQuery,\n GQL_GetMyBucketListItemsQueryVariables\n >(GetMyBucketListItemsDocument, options)\n}\nexport type GetMyBucketListItemsQueryHookResult = ReturnType<\n typeof useGetMyBucketListItemsQuery\n>\nexport type GetMyBucketListItemsLazyQueryHookResult = ReturnType<\n typeof useGetMyBucketListItemsLazyQuery\n>\nexport type GetMyBucketListItemsQueryResult = Apollo.QueryResult<\n GQL_GetMyBucketListItemsQuery,\n GQL_GetMyBucketListItemsQueryVariables\n>\nexport const GetMyBucketListMapResultsDocument = gql`\n query getMyBucketListMapResults($id: ID, $params: SearchFilters) {\n currentUser {\n id\n bucketList(id: $id) {\n id\n mapResults(params: $params) {\n ...MapResultFragment\n markerCount\n }\n }\n }\n }\n ${MapResultFragmentFragmentDoc}\n`\n\n/**\n * __useGetMyBucketListMapResultsQuery__\n *\n * To run a query within a React component, call `useGetMyBucketListMapResultsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyBucketListMapResultsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyBucketListMapResultsQuery({\n * variables: {\n * id: // value for 'id'\n * params: // value for 'params'\n * },\n * });\n */\nexport function useGetMyBucketListMapResultsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetMyBucketListMapResultsQuery,\n GQL_GetMyBucketListMapResultsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyBucketListMapResultsQuery,\n GQL_GetMyBucketListMapResultsQueryVariables\n >(GetMyBucketListMapResultsDocument, options)\n}\nexport function useGetMyBucketListMapResultsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyBucketListMapResultsQuery,\n GQL_GetMyBucketListMapResultsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyBucketListMapResultsQuery,\n GQL_GetMyBucketListMapResultsQueryVariables\n >(GetMyBucketListMapResultsDocument, options)\n}\nexport type GetMyBucketListMapResultsQueryHookResult = ReturnType<\n typeof useGetMyBucketListMapResultsQuery\n>\nexport type GetMyBucketListMapResultsLazyQueryHookResult = ReturnType<\n typeof useGetMyBucketListMapResultsLazyQuery\n>\nexport type GetMyBucketListMapResultsQueryResult = Apollo.QueryResult<\n GQL_GetMyBucketListMapResultsQuery,\n GQL_GetMyBucketListMapResultsQueryVariables\n>\nexport const CreateBucketListDocument = gql`\n mutation createBucketList($name: String!, $themeId: ID!) {\n createBucketList(name: $name, themeId: $themeId) {\n bucketList {\n ...BucketListFragment\n }\n }\n }\n ${BucketListFragmentFragmentDoc}\n`\nexport type GQL_CreateBucketListMutationFn = Apollo.MutationFunction<\n GQL_CreateBucketListMutation,\n GQL_CreateBucketListMutationVariables\n>\n\n/**\n * __useCreateBucketListMutation__\n *\n * To run a mutation, you first call `useCreateBucketListMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateBucketListMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createBucketListMutation, { data, loading, error }] = useCreateBucketListMutation({\n * variables: {\n * name: // value for 'name'\n * themeId: // value for 'themeId'\n * },\n * });\n */\nexport function useCreateBucketListMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateBucketListMutation,\n GQL_CreateBucketListMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateBucketListMutation,\n GQL_CreateBucketListMutationVariables\n >(CreateBucketListDocument, options)\n}\nexport type CreateBucketListMutationHookResult = ReturnType<\n typeof useCreateBucketListMutation\n>\nexport type CreateBucketListMutationResult = Apollo.MutationResult<\n GQL_CreateBucketListMutation\n>\nexport type CreateBucketListMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateBucketListMutation,\n GQL_CreateBucketListMutationVariables\n>\nexport const DestroyBucketListDocument = gql`\n mutation destroyBucketList($id: ID!) {\n destroyBucketList(bucketListId: $id) {\n bucketList {\n name\n }\n }\n }\n`\nexport type GQL_DestroyBucketListMutationFn = Apollo.MutationFunction<\n GQL_DestroyBucketListMutation,\n GQL_DestroyBucketListMutationVariables\n>\n\n/**\n * __useDestroyBucketListMutation__\n *\n * To run a mutation, you first call `useDestroyBucketListMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDestroyBucketListMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [destroyBucketListMutation, { data, loading, error }] = useDestroyBucketListMutation({\n * variables: {\n * id: // value for 'id'\n * },\n * });\n */\nexport function useDestroyBucketListMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DestroyBucketListMutation,\n GQL_DestroyBucketListMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DestroyBucketListMutation,\n GQL_DestroyBucketListMutationVariables\n >(DestroyBucketListDocument, options)\n}\nexport type DestroyBucketListMutationHookResult = ReturnType<\n typeof useDestroyBucketListMutation\n>\nexport type DestroyBucketListMutationResult = Apollo.MutationResult<\n GQL_DestroyBucketListMutation\n>\nexport type DestroyBucketListMutationOptions = Apollo.BaseMutationOptions<\n GQL_DestroyBucketListMutation,\n GQL_DestroyBucketListMutationVariables\n>\nexport const GetBucketListItemsIndexDocument = gql`\n query getBucketListItemsIndex {\n currentUser {\n id\n bucketListItemsIndex\n }\n }\n`\n\n/**\n * __useGetBucketListItemsIndexQuery__\n *\n * To run a query within a React component, call `useGetBucketListItemsIndexQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBucketListItemsIndexQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBucketListItemsIndexQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetBucketListItemsIndexQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetBucketListItemsIndexQuery,\n GQL_GetBucketListItemsIndexQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBucketListItemsIndexQuery,\n GQL_GetBucketListItemsIndexQueryVariables\n >(GetBucketListItemsIndexDocument, options)\n}\nexport function useGetBucketListItemsIndexLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBucketListItemsIndexQuery,\n GQL_GetBucketListItemsIndexQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBucketListItemsIndexQuery,\n GQL_GetBucketListItemsIndexQueryVariables\n >(GetBucketListItemsIndexDocument, options)\n}\nexport type GetBucketListItemsIndexQueryHookResult = ReturnType<\n typeof useGetBucketListItemsIndexQuery\n>\nexport type GetBucketListItemsIndexLazyQueryHookResult = ReturnType<\n typeof useGetBucketListItemsIndexLazyQuery\n>\nexport type GetBucketListItemsIndexQueryResult = Apollo.QueryResult<\n GQL_GetBucketListItemsIndexQuery,\n GQL_GetBucketListItemsIndexQueryVariables\n>\nexport const BucketListThemesDocument = gql`\n query bucketListThemes {\n defaults {\n bucketListThemes {\n ...BucketListTheme\n }\n }\n }\n ${BucketListThemeFragmentDoc}\n`\n\n/**\n * __useBucketListThemesQuery__\n *\n * To run a query within a React component, call `useBucketListThemesQuery` and pass it any options that fit your needs.\n * When your component renders, `useBucketListThemesQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useBucketListThemesQuery({\n * variables: {\n * },\n * });\n */\nexport function useBucketListThemesQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_BucketListThemesQuery,\n GQL_BucketListThemesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_BucketListThemesQuery,\n GQL_BucketListThemesQueryVariables\n >(BucketListThemesDocument, options)\n}\nexport function useBucketListThemesLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_BucketListThemesQuery,\n GQL_BucketListThemesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_BucketListThemesQuery,\n GQL_BucketListThemesQueryVariables\n >(BucketListThemesDocument, options)\n}\nexport type BucketListThemesQueryHookResult = ReturnType<\n typeof useBucketListThemesQuery\n>\nexport type BucketListThemesLazyQueryHookResult = ReturnType<\n typeof useBucketListThemesLazyQuery\n>\nexport type BucketListThemesQueryResult = Apollo.QueryResult<\n GQL_BucketListThemesQuery,\n GQL_BucketListThemesQueryVariables\n>\nexport const GetMyBucketListsDocument = gql`\n query getMyBucketLists {\n currentUser {\n id\n bucketLists {\n ...BucketListFragment\n }\n }\n }\n ${BucketListFragmentFragmentDoc}\n`\n\n/**\n * __useGetMyBucketListsQuery__\n *\n * To run a query within a React component, call `useGetMyBucketListsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyBucketListsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyBucketListsQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetMyBucketListsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetMyBucketListsQuery,\n GQL_GetMyBucketListsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyBucketListsQuery,\n GQL_GetMyBucketListsQueryVariables\n >(GetMyBucketListsDocument, options)\n}\nexport function useGetMyBucketListsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyBucketListsQuery,\n GQL_GetMyBucketListsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyBucketListsQuery,\n GQL_GetMyBucketListsQueryVariables\n >(GetMyBucketListsDocument, options)\n}\nexport type GetMyBucketListsQueryHookResult = ReturnType<\n typeof useGetMyBucketListsQuery\n>\nexport type GetMyBucketListsLazyQueryHookResult = ReturnType<\n typeof useGetMyBucketListsLazyQuery\n>\nexport type GetMyBucketListsQueryResult = Apollo.QueryResult<\n GQL_GetMyBucketListsQuery,\n GQL_GetMyBucketListsQueryVariables\n>\nexport const UpdateBucketListDocument = gql`\n mutation updateBucketList($id: ID!, $name: String!, $themeId: ID!) {\n updateBucketList(bucketListId: $id, name: $name, themeId: $themeId) {\n bucketList {\n ...BucketListFragment\n }\n }\n }\n ${BucketListFragmentFragmentDoc}\n`\nexport type GQL_UpdateBucketListMutationFn = Apollo.MutationFunction<\n GQL_UpdateBucketListMutation,\n GQL_UpdateBucketListMutationVariables\n>\n\n/**\n * __useUpdateBucketListMutation__\n *\n * To run a mutation, you first call `useUpdateBucketListMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateBucketListMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateBucketListMutation, { data, loading, error }] = useUpdateBucketListMutation({\n * variables: {\n * id: // value for 'id'\n * name: // value for 'name'\n * themeId: // value for 'themeId'\n * },\n * });\n */\nexport function useUpdateBucketListMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdateBucketListMutation,\n GQL_UpdateBucketListMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdateBucketListMutation,\n GQL_UpdateBucketListMutationVariables\n >(UpdateBucketListDocument, options)\n}\nexport type UpdateBucketListMutationHookResult = ReturnType<\n typeof useUpdateBucketListMutation\n>\nexport type UpdateBucketListMutationResult = Apollo.MutationResult<\n GQL_UpdateBucketListMutation\n>\nexport type UpdateBucketListMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdateBucketListMutation,\n GQL_UpdateBucketListMutationVariables\n>\nexport const GetMyCreatorCalendarDocument = gql`\n query getMyCreatorCalendar(\n $calendarStart: ISO8601Date!\n $calendarEnd: ISO8601Date!\n ) {\n currentUser {\n id\n calendar(startDate: $calendarStart, endDate: $calendarEnd) {\n days {\n available\n date\n }\n events {\n id\n type\n label\n start\n end\n }\n }\n }\n }\n`\n\n/**\n * __useGetMyCreatorCalendarQuery__\n *\n * To run a query within a React component, call `useGetMyCreatorCalendarQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyCreatorCalendarQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyCreatorCalendarQuery({\n * variables: {\n * calendarStart: // value for 'calendarStart'\n * calendarEnd: // value for 'calendarEnd'\n * },\n * });\n */\nexport function useGetMyCreatorCalendarQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetMyCreatorCalendarQuery,\n GQL_GetMyCreatorCalendarQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyCreatorCalendarQuery,\n GQL_GetMyCreatorCalendarQueryVariables\n >(GetMyCreatorCalendarDocument, options)\n}\nexport function useGetMyCreatorCalendarLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyCreatorCalendarQuery,\n GQL_GetMyCreatorCalendarQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyCreatorCalendarQuery,\n GQL_GetMyCreatorCalendarQueryVariables\n >(GetMyCreatorCalendarDocument, options)\n}\nexport type GetMyCreatorCalendarQueryHookResult = ReturnType<\n typeof useGetMyCreatorCalendarQuery\n>\nexport type GetMyCreatorCalendarLazyQueryHookResult = ReturnType<\n typeof useGetMyCreatorCalendarLazyQuery\n>\nexport type GetMyCreatorCalendarQueryResult = Apollo.QueryResult<\n GQL_GetMyCreatorCalendarQuery,\n GQL_GetMyCreatorCalendarQueryVariables\n>\nexport const UpdateMyCreatorCalendarDocument = gql`\n mutation updateMyCreatorCalendar(\n $startDate: ISO8601Date!\n $endDate: ISO8601Date!\n $available: Boolean!\n ) {\n updateStorytellerCalendar(\n startDate: $startDate\n endDate: $endDate\n available: $available\n ) {\n calendar {\n days {\n available\n date\n }\n events {\n id\n type\n label\n start\n end\n }\n }\n }\n }\n`\nexport type GQL_UpdateMyCreatorCalendarMutationFn = Apollo.MutationFunction<\n GQL_UpdateMyCreatorCalendarMutation,\n GQL_UpdateMyCreatorCalendarMutationVariables\n>\n\n/**\n * __useUpdateMyCreatorCalendarMutation__\n *\n * To run a mutation, you first call `useUpdateMyCreatorCalendarMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateMyCreatorCalendarMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateMyCreatorCalendarMutation, { data, loading, error }] = useUpdateMyCreatorCalendarMutation({\n * variables: {\n * startDate: // value for 'startDate'\n * endDate: // value for 'endDate'\n * available: // value for 'available'\n * },\n * });\n */\nexport function useUpdateMyCreatorCalendarMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdateMyCreatorCalendarMutation,\n GQL_UpdateMyCreatorCalendarMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdateMyCreatorCalendarMutation,\n GQL_UpdateMyCreatorCalendarMutationVariables\n >(UpdateMyCreatorCalendarDocument, options)\n}\nexport type UpdateMyCreatorCalendarMutationHookResult = ReturnType<\n typeof useUpdateMyCreatorCalendarMutation\n>\nexport type UpdateMyCreatorCalendarMutationResult = Apollo.MutationResult<\n GQL_UpdateMyCreatorCalendarMutation\n>\nexport type UpdateMyCreatorCalendarMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdateMyCreatorCalendarMutation,\n GQL_UpdateMyCreatorCalendarMutationVariables\n>\nexport const AcceptInvitationDocument = gql`\n mutation acceptInvitation(\n $password: String!\n $passwordConfirmation: String!\n $invitationToken: String\n ) {\n acceptInvitation(\n password: $password\n passwordConfirmation: $passwordConfirmation\n invitationToken: $invitationToken\n ) {\n user {\n id\n }\n }\n }\n`\nexport type GQL_AcceptInvitationMutationFn = Apollo.MutationFunction<\n GQL_AcceptInvitationMutation,\n GQL_AcceptInvitationMutationVariables\n>\n\n/**\n * __useAcceptInvitationMutation__\n *\n * To run a mutation, you first call `useAcceptInvitationMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useAcceptInvitationMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [acceptInvitationMutation, { data, loading, error }] = useAcceptInvitationMutation({\n * variables: {\n * password: // value for 'password'\n * passwordConfirmation: // value for 'passwordConfirmation'\n * invitationToken: // value for 'invitationToken'\n * },\n * });\n */\nexport function useAcceptInvitationMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_AcceptInvitationMutation,\n GQL_AcceptInvitationMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_AcceptInvitationMutation,\n GQL_AcceptInvitationMutationVariables\n >(AcceptInvitationDocument, options)\n}\nexport type AcceptInvitationMutationHookResult = ReturnType<\n typeof useAcceptInvitationMutation\n>\nexport type AcceptInvitationMutationResult = Apollo.MutationResult<\n GQL_AcceptInvitationMutation\n>\nexport type AcceptInvitationMutationOptions = Apollo.BaseMutationOptions<\n GQL_AcceptInvitationMutation,\n GQL_AcceptInvitationMutationVariables\n>\nexport const ListingCalendarDocument = gql`\n query listingCalendar(\n $listingId: ID!\n $calendarStart: ISO8601Date!\n $calendarEnd: ISO8601Date!\n ) {\n listing(id: $listingId) {\n id\n price\n weekendPrice\n pricingSuffix\n concurrentBookings\n channelManager\n channelManagerSyncEnabled\n listingType {\n slug\n }\n calendar(startDate: $calendarStart, endDate: $calendarEnd) {\n events {\n id\n type\n label\n start\n end\n summary\n ... on BookingCalendarEvent {\n booking {\n status\n }\n }\n }\n days {\n date\n available\n requested\n customPrice\n weekendPrice\n minimumNights\n customMinimumBookingDuration\n note\n }\n }\n }\n }\n`\n\n/**\n * __useListingCalendarQuery__\n *\n * To run a query within a React component, call `useListingCalendarQuery` and pass it any options that fit your needs.\n * When your component renders, `useListingCalendarQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useListingCalendarQuery({\n * variables: {\n * listingId: // value for 'listingId'\n * calendarStart: // value for 'calendarStart'\n * calendarEnd: // value for 'calendarEnd'\n * },\n * });\n */\nexport function useListingCalendarQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_ListingCalendarQuery,\n GQL_ListingCalendarQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_ListingCalendarQuery,\n GQL_ListingCalendarQueryVariables\n >(ListingCalendarDocument, options)\n}\nexport function useListingCalendarLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_ListingCalendarQuery,\n GQL_ListingCalendarQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_ListingCalendarQuery,\n GQL_ListingCalendarQueryVariables\n >(ListingCalendarDocument, options)\n}\nexport type ListingCalendarQueryHookResult = ReturnType<\n typeof useListingCalendarQuery\n>\nexport type ListingCalendarLazyQueryHookResult = ReturnType<\n typeof useListingCalendarLazyQuery\n>\nexport type ListingCalendarQueryResult = Apollo.QueryResult<\n GQL_ListingCalendarQuery,\n GQL_ListingCalendarQueryVariables\n>\nexport const UpdateListingCalendarDocument = gql`\n mutation updateListingCalendar(\n $listingId: ID!\n $startDate: ISO8601Date!\n $endDate: ISO8601Date!\n $calendarInput: CalendarInput!\n ) {\n updateCalendar(\n listingId: $listingId\n startDate: $startDate\n endDate: $endDate\n calendarInput: $calendarInput\n ) {\n calendar {\n days {\n date\n available\n minimumNights\n customPrice\n customMinimumBookingDuration\n note\n }\n }\n }\n }\n`\nexport type GQL_UpdateListingCalendarMutationFn = Apollo.MutationFunction<\n GQL_UpdateListingCalendarMutation,\n GQL_UpdateListingCalendarMutationVariables\n>\n\n/**\n * __useUpdateListingCalendarMutation__\n *\n * To run a mutation, you first call `useUpdateListingCalendarMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateListingCalendarMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateListingCalendarMutation, { data, loading, error }] = useUpdateListingCalendarMutation({\n * variables: {\n * listingId: // value for 'listingId'\n * startDate: // value for 'startDate'\n * endDate: // value for 'endDate'\n * calendarInput: // value for 'calendarInput'\n * },\n * });\n */\nexport function useUpdateListingCalendarMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdateListingCalendarMutation,\n GQL_UpdateListingCalendarMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdateListingCalendarMutation,\n GQL_UpdateListingCalendarMutationVariables\n >(UpdateListingCalendarDocument, options)\n}\nexport type UpdateListingCalendarMutationHookResult = ReturnType<\n typeof useUpdateListingCalendarMutation\n>\nexport type UpdateListingCalendarMutationResult = Apollo.MutationResult<\n GQL_UpdateListingCalendarMutation\n>\nexport type UpdateListingCalendarMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdateListingCalendarMutation,\n GQL_UpdateListingCalendarMutationVariables\n>\nexport const CreateAdventureLinkDocument = gql`\n mutation createAdventureLink($adventureId: ID!, $listingId: ID!) {\n createAdventureLink(adventureId: $adventureId, listingId: $listingId) {\n adventure {\n ...EditListingAdventureFragment\n }\n }\n }\n ${EditListingAdventureFragmentFragmentDoc}\n`\nexport type GQL_CreateAdventureLinkMutationFn = Apollo.MutationFunction<\n GQL_CreateAdventureLinkMutation,\n GQL_CreateAdventureLinkMutationVariables\n>\n\n/**\n * __useCreateAdventureLinkMutation__\n *\n * To run a mutation, you first call `useCreateAdventureLinkMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateAdventureLinkMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createAdventureLinkMutation, { data, loading, error }] = useCreateAdventureLinkMutation({\n * variables: {\n * adventureId: // value for 'adventureId'\n * listingId: // value for 'listingId'\n * },\n * });\n */\nexport function useCreateAdventureLinkMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateAdventureLinkMutation,\n GQL_CreateAdventureLinkMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateAdventureLinkMutation,\n GQL_CreateAdventureLinkMutationVariables\n >(CreateAdventureLinkDocument, options)\n}\nexport type CreateAdventureLinkMutationHookResult = ReturnType<\n typeof useCreateAdventureLinkMutation\n>\nexport type CreateAdventureLinkMutationResult = Apollo.MutationResult<\n GQL_CreateAdventureLinkMutation\n>\nexport type CreateAdventureLinkMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateAdventureLinkMutation,\n GQL_CreateAdventureLinkMutationVariables\n>\nexport const GetListingNearbyAdventuresDocument = gql`\n query getListingNearbyAdventures(\n $listingId: ID!\n $adventureType: String\n $pageSize: Int = 4\n $afterCursor: String\n $beforeCursor: String\n ) {\n listing(id: $listingId) {\n id\n nearbyAdventureTypes {\n id\n name\n slug\n category\n }\n nearbyAdventures(\n adventureType: $adventureType\n first: $pageSize\n after: $afterCursor\n before: $beforeCursor\n ) {\n pageInfo {\n startCursor\n endCursor\n hasNextPage\n hasPreviousPage\n }\n edges {\n cursor\n node {\n ...EditListingAdventureFragment\n }\n }\n }\n }\n }\n ${EditListingAdventureFragmentFragmentDoc}\n`\n\n/**\n * __useGetListingNearbyAdventuresQuery__\n *\n * To run a query within a React component, call `useGetListingNearbyAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetListingNearbyAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetListingNearbyAdventuresQuery({\n * variables: {\n * listingId: // value for 'listingId'\n * adventureType: // value for 'adventureType'\n * pageSize: // value for 'pageSize'\n * afterCursor: // value for 'afterCursor'\n * beforeCursor: // value for 'beforeCursor'\n * },\n * });\n */\nexport function useGetListingNearbyAdventuresQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetListingNearbyAdventuresQuery,\n GQL_GetListingNearbyAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetListingNearbyAdventuresQuery,\n GQL_GetListingNearbyAdventuresQueryVariables\n >(GetListingNearbyAdventuresDocument, options)\n}\nexport function useGetListingNearbyAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetListingNearbyAdventuresQuery,\n GQL_GetListingNearbyAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetListingNearbyAdventuresQuery,\n GQL_GetListingNearbyAdventuresQueryVariables\n >(GetListingNearbyAdventuresDocument, options)\n}\nexport type GetListingNearbyAdventuresQueryHookResult = ReturnType<\n typeof useGetListingNearbyAdventuresQuery\n>\nexport type GetListingNearbyAdventuresLazyQueryHookResult = ReturnType<\n typeof useGetListingNearbyAdventuresLazyQuery\n>\nexport type GetListingNearbyAdventuresQueryResult = Apollo.QueryResult<\n GQL_GetListingNearbyAdventuresQuery,\n GQL_GetListingNearbyAdventuresQueryVariables\n>\nexport const CreateListingAdventureDocument = gql`\n mutation createListingAdventure(\n $listingId: ID!\n $adventureInput: CreateAdventureInput!\n ) {\n createListingAdventure(\n listingId: $listingId\n adventureInput: $adventureInput\n ) {\n adventure {\n ...EditListingAdventureFragment\n }\n }\n }\n ${EditListingAdventureFragmentFragmentDoc}\n`\nexport type GQL_CreateListingAdventureMutationFn = Apollo.MutationFunction<\n GQL_CreateListingAdventureMutation,\n GQL_CreateListingAdventureMutationVariables\n>\n\n/**\n * __useCreateListingAdventureMutation__\n *\n * To run a mutation, you first call `useCreateListingAdventureMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateListingAdventureMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createListingAdventureMutation, { data, loading, error }] = useCreateListingAdventureMutation({\n * variables: {\n * listingId: // value for 'listingId'\n * adventureInput: // value for 'adventureInput'\n * },\n * });\n */\nexport function useCreateListingAdventureMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateListingAdventureMutation,\n GQL_CreateListingAdventureMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateListingAdventureMutation,\n GQL_CreateListingAdventureMutationVariables\n >(CreateListingAdventureDocument, options)\n}\nexport type CreateListingAdventureMutationHookResult = ReturnType<\n typeof useCreateListingAdventureMutation\n>\nexport type CreateListingAdventureMutationResult = Apollo.MutationResult<\n GQL_CreateListingAdventureMutation\n>\nexport type CreateListingAdventureMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateListingAdventureMutation,\n GQL_CreateListingAdventureMutationVariables\n>\nexport const DestroyAdventureLinkDocument = gql`\n mutation destroyAdventureLink($adventureId: ID!, $listingId: ID!) {\n destroyAdventureLink(adventureId: $adventureId, listingId: $listingId) {\n adventure {\n id\n }\n }\n }\n`\nexport type GQL_DestroyAdventureLinkMutationFn = Apollo.MutationFunction<\n GQL_DestroyAdventureLinkMutation,\n GQL_DestroyAdventureLinkMutationVariables\n>\n\n/**\n * __useDestroyAdventureLinkMutation__\n *\n * To run a mutation, you first call `useDestroyAdventureLinkMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDestroyAdventureLinkMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [destroyAdventureLinkMutation, { data, loading, error }] = useDestroyAdventureLinkMutation({\n * variables: {\n * adventureId: // value for 'adventureId'\n * listingId: // value for 'listingId'\n * },\n * });\n */\nexport function useDestroyAdventureLinkMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DestroyAdventureLinkMutation,\n GQL_DestroyAdventureLinkMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DestroyAdventureLinkMutation,\n GQL_DestroyAdventureLinkMutationVariables\n >(DestroyAdventureLinkDocument, options)\n}\nexport type DestroyAdventureLinkMutationHookResult = ReturnType<\n typeof useDestroyAdventureLinkMutation\n>\nexport type DestroyAdventureLinkMutationResult = Apollo.MutationResult<\n GQL_DestroyAdventureLinkMutation\n>\nexport type DestroyAdventureLinkMutationOptions = Apollo.BaseMutationOptions<\n GQL_DestroyAdventureLinkMutation,\n GQL_DestroyAdventureLinkMutationVariables\n>\nexport const DestroyAdventureDocument = gql`\n mutation destroyAdventure($id: ID!) {\n destroyAdventure(adventureId: $id) {\n adventure {\n id\n }\n }\n }\n`\nexport type GQL_DestroyAdventureMutationFn = Apollo.MutationFunction<\n GQL_DestroyAdventureMutation,\n GQL_DestroyAdventureMutationVariables\n>\n\n/**\n * __useDestroyAdventureMutation__\n *\n * To run a mutation, you first call `useDestroyAdventureMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDestroyAdventureMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [destroyAdventureMutation, { data, loading, error }] = useDestroyAdventureMutation({\n * variables: {\n * id: // value for 'id'\n * },\n * });\n */\nexport function useDestroyAdventureMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DestroyAdventureMutation,\n GQL_DestroyAdventureMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DestroyAdventureMutation,\n GQL_DestroyAdventureMutationVariables\n >(DestroyAdventureDocument, options)\n}\nexport type DestroyAdventureMutationHookResult = ReturnType<\n typeof useDestroyAdventureMutation\n>\nexport type DestroyAdventureMutationResult = Apollo.MutationResult<\n GQL_DestroyAdventureMutation\n>\nexport type DestroyAdventureMutationOptions = Apollo.BaseMutationOptions<\n GQL_DestroyAdventureMutation,\n GQL_DestroyAdventureMutationVariables\n>\nexport const GetListingAdventuresDocument = gql`\n query getListingAdventures($listingId: ID!) {\n listing(id: $listingId) {\n id\n linkedAdventureIds\n adventures {\n ...EditListingAdventureFragment\n }\n }\n }\n ${EditListingAdventureFragmentFragmentDoc}\n`\n\n/**\n * __useGetListingAdventuresQuery__\n *\n * To run a query within a React component, call `useGetListingAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetListingAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetListingAdventuresQuery({\n * variables: {\n * listingId: // value for 'listingId'\n * },\n * });\n */\nexport function useGetListingAdventuresQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetListingAdventuresQuery,\n GQL_GetListingAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetListingAdventuresQuery,\n GQL_GetListingAdventuresQueryVariables\n >(GetListingAdventuresDocument, options)\n}\nexport function useGetListingAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetListingAdventuresQuery,\n GQL_GetListingAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetListingAdventuresQuery,\n GQL_GetListingAdventuresQueryVariables\n >(GetListingAdventuresDocument, options)\n}\nexport type GetListingAdventuresQueryHookResult = ReturnType<\n typeof useGetListingAdventuresQuery\n>\nexport type GetListingAdventuresLazyQueryHookResult = ReturnType<\n typeof useGetListingAdventuresLazyQuery\n>\nexport type GetListingAdventuresQueryResult = Apollo.QueryResult<\n GQL_GetListingAdventuresQuery,\n GQL_GetListingAdventuresQueryVariables\n>\nexport const UpdateAdventureDocument = gql`\n mutation updateAdventure(\n $adventureId: ID!\n $adventureInput: UpdateAdventureInput!\n ) {\n updateAdventure(\n adventureId: $adventureId\n adventureInput: $adventureInput\n ) {\n adventure {\n ...EditListingAdventureFragment\n }\n }\n }\n ${EditListingAdventureFragmentFragmentDoc}\n`\nexport type GQL_UpdateAdventureMutationFn = Apollo.MutationFunction<\n GQL_UpdateAdventureMutation,\n GQL_UpdateAdventureMutationVariables\n>\n\n/**\n * __useUpdateAdventureMutation__\n *\n * To run a mutation, you first call `useUpdateAdventureMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateAdventureMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateAdventureMutation, { data, loading, error }] = useUpdateAdventureMutation({\n * variables: {\n * adventureId: // value for 'adventureId'\n * adventureInput: // value for 'adventureInput'\n * },\n * });\n */\nexport function useUpdateAdventureMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdateAdventureMutation,\n GQL_UpdateAdventureMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdateAdventureMutation,\n GQL_UpdateAdventureMutationVariables\n >(UpdateAdventureDocument, options)\n}\nexport type UpdateAdventureMutationHookResult = ReturnType<\n typeof useUpdateAdventureMutation\n>\nexport type UpdateAdventureMutationResult = Apollo.MutationResult<\n GQL_UpdateAdventureMutation\n>\nexport type UpdateAdventureMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdateAdventureMutation,\n GQL_UpdateAdventureMutationVariables\n>\nexport const GetStoryOfferCalendarDocument = gql`\n query getStoryOfferCalendar(\n $listingId: ID!\n $calendarStart: ISO8601Date!\n $calendarEnd: ISO8601Date!\n ) {\n listing(id: $listingId) {\n id\n storyOfferCalendar(endDate: $calendarEnd, startDate: $calendarStart) {\n days {\n available\n offer\n customOffer\n date\n discountedPrice\n customDiscountedPrice\n }\n startDate\n endDate\n }\n }\n }\n`\n\n/**\n * __useGetStoryOfferCalendarQuery__\n *\n * To run a query within a React component, call `useGetStoryOfferCalendarQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetStoryOfferCalendarQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetStoryOfferCalendarQuery({\n * variables: {\n * listingId: // value for 'listingId'\n * calendarStart: // value for 'calendarStart'\n * calendarEnd: // value for 'calendarEnd'\n * },\n * });\n */\nexport function useGetStoryOfferCalendarQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetStoryOfferCalendarQuery,\n GQL_GetStoryOfferCalendarQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetStoryOfferCalendarQuery,\n GQL_GetStoryOfferCalendarQueryVariables\n >(GetStoryOfferCalendarDocument, options)\n}\nexport function useGetStoryOfferCalendarLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetStoryOfferCalendarQuery,\n GQL_GetStoryOfferCalendarQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetStoryOfferCalendarQuery,\n GQL_GetStoryOfferCalendarQueryVariables\n >(GetStoryOfferCalendarDocument, options)\n}\nexport type GetStoryOfferCalendarQueryHookResult = ReturnType<\n typeof useGetStoryOfferCalendarQuery\n>\nexport type GetStoryOfferCalendarLazyQueryHookResult = ReturnType<\n typeof useGetStoryOfferCalendarLazyQuery\n>\nexport type GetStoryOfferCalendarQueryResult = Apollo.QueryResult<\n GQL_GetStoryOfferCalendarQuery,\n GQL_GetStoryOfferCalendarQueryVariables\n>\nexport const UpdateStoryOfferCalendarDocument = gql`\n mutation updateStoryOfferCalendar(\n $listingId: ID!\n $endDate: ISO8601Date!\n $startDate: ISO8601Date!\n $calendarInput: StoryOfferCalendarInput!\n ) {\n updateStoryOfferCalendar(\n listingId: $listingId\n endDate: $endDate\n startDate: $startDate\n calendarInput: $calendarInput\n ) {\n calendar {\n days {\n available\n date\n }\n endDate\n startDate\n }\n }\n }\n`\nexport type GQL_UpdateStoryOfferCalendarMutationFn = Apollo.MutationFunction<\n GQL_UpdateStoryOfferCalendarMutation,\n GQL_UpdateStoryOfferCalendarMutationVariables\n>\n\n/**\n * __useUpdateStoryOfferCalendarMutation__\n *\n * To run a mutation, you first call `useUpdateStoryOfferCalendarMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateStoryOfferCalendarMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateStoryOfferCalendarMutation, { data, loading, error }] = useUpdateStoryOfferCalendarMutation({\n * variables: {\n * listingId: // value for 'listingId'\n * endDate: // value for 'endDate'\n * startDate: // value for 'startDate'\n * calendarInput: // value for 'calendarInput'\n * },\n * });\n */\nexport function useUpdateStoryOfferCalendarMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdateStoryOfferCalendarMutation,\n GQL_UpdateStoryOfferCalendarMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdateStoryOfferCalendarMutation,\n GQL_UpdateStoryOfferCalendarMutationVariables\n >(UpdateStoryOfferCalendarDocument, options)\n}\nexport type UpdateStoryOfferCalendarMutationHookResult = ReturnType<\n typeof useUpdateStoryOfferCalendarMutation\n>\nexport type UpdateStoryOfferCalendarMutationResult = Apollo.MutationResult<\n GQL_UpdateStoryOfferCalendarMutation\n>\nexport type UpdateStoryOfferCalendarMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdateStoryOfferCalendarMutation,\n GQL_UpdateStoryOfferCalendarMutationVariables\n>\nexport const CreateStoryVideoDocument = gql`\n mutation createStoryVideo($storyId: ID!) {\n createStoryVideo(storyId: $storyId) {\n directUpload {\n url\n }\n }\n }\n`\nexport type GQL_CreateStoryVideoMutationFn = Apollo.MutationFunction<\n GQL_CreateStoryVideoMutation,\n GQL_CreateStoryVideoMutationVariables\n>\n\n/**\n * __useCreateStoryVideoMutation__\n *\n * To run a mutation, you first call `useCreateStoryVideoMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateStoryVideoMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createStoryVideoMutation, { data, loading, error }] = useCreateStoryVideoMutation({\n * variables: {\n * storyId: // value for 'storyId'\n * },\n * });\n */\nexport function useCreateStoryVideoMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateStoryVideoMutation,\n GQL_CreateStoryVideoMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateStoryVideoMutation,\n GQL_CreateStoryVideoMutationVariables\n >(CreateStoryVideoDocument, options)\n}\nexport type CreateStoryVideoMutationHookResult = ReturnType<\n typeof useCreateStoryVideoMutation\n>\nexport type CreateStoryVideoMutationResult = Apollo.MutationResult<\n GQL_CreateStoryVideoMutation\n>\nexport type CreateStoryVideoMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateStoryVideoMutation,\n GQL_CreateStoryVideoMutationVariables\n>\nexport const DestroyVideoDocument = gql`\n mutation destroyVideo($videoId: ID!) {\n destroyVideo(videoId: $videoId) {\n video {\n id\n }\n }\n }\n`\nexport type GQL_DestroyVideoMutationFn = Apollo.MutationFunction<\n GQL_DestroyVideoMutation,\n GQL_DestroyVideoMutationVariables\n>\n\n/**\n * __useDestroyVideoMutation__\n *\n * To run a mutation, you first call `useDestroyVideoMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDestroyVideoMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [destroyVideoMutation, { data, loading, error }] = useDestroyVideoMutation({\n * variables: {\n * videoId: // value for 'videoId'\n * },\n * });\n */\nexport function useDestroyVideoMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DestroyVideoMutation,\n GQL_DestroyVideoMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DestroyVideoMutation,\n GQL_DestroyVideoMutationVariables\n >(DestroyVideoDocument, options)\n}\nexport type DestroyVideoMutationHookResult = ReturnType<\n typeof useDestroyVideoMutation\n>\nexport type DestroyVideoMutationResult = Apollo.MutationResult<\n GQL_DestroyVideoMutation\n>\nexport type DestroyVideoMutationOptions = Apollo.BaseMutationOptions<\n GQL_DestroyVideoMutation,\n GQL_DestroyVideoMutationVariables\n>\nexport const GetStoryVideosDocument = gql`\n query getStoryVideos($storyId: ID!) {\n currentUser {\n id\n story(id: $storyId) {\n id\n videos {\n ...Video\n }\n }\n }\n }\n ${VideoFragmentDoc}\n`\n\n/**\n * __useGetStoryVideosQuery__\n *\n * To run a query within a React component, call `useGetStoryVideosQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetStoryVideosQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetStoryVideosQuery({\n * variables: {\n * storyId: // value for 'storyId'\n * },\n * });\n */\nexport function useGetStoryVideosQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetStoryVideosQuery,\n GQL_GetStoryVideosQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetStoryVideosQuery,\n GQL_GetStoryVideosQueryVariables\n >(GetStoryVideosDocument, options)\n}\nexport function useGetStoryVideosLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetStoryVideosQuery,\n GQL_GetStoryVideosQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetStoryVideosQuery,\n GQL_GetStoryVideosQueryVariables\n >(GetStoryVideosDocument, options)\n}\nexport type GetStoryVideosQueryHookResult = ReturnType<\n typeof useGetStoryVideosQuery\n>\nexport type GetStoryVideosLazyQueryHookResult = ReturnType<\n typeof useGetStoryVideosLazyQuery\n>\nexport type GetStoryVideosQueryResult = Apollo.QueryResult<\n GQL_GetStoryVideosQuery,\n GQL_GetStoryVideosQueryVariables\n>\nexport const CreateRipaVideoDocument = gql`\n mutation createRipaVideo($storyId: ID!, $category: RipaVideoCategory!) {\n createRipaVideo(storyId: $storyId, category: $category) {\n directUpload {\n url\n }\n }\n }\n`\nexport type GQL_CreateRipaVideoMutationFn = Apollo.MutationFunction<\n GQL_CreateRipaVideoMutation,\n GQL_CreateRipaVideoMutationVariables\n>\n\n/**\n * __useCreateRipaVideoMutation__\n *\n * To run a mutation, you first call `useCreateRipaVideoMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateRipaVideoMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createRipaVideoMutation, { data, loading, error }] = useCreateRipaVideoMutation({\n * variables: {\n * storyId: // value for 'storyId'\n * category: // value for 'category'\n * },\n * });\n */\nexport function useCreateRipaVideoMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateRipaVideoMutation,\n GQL_CreateRipaVideoMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateRipaVideoMutation,\n GQL_CreateRipaVideoMutationVariables\n >(CreateRipaVideoDocument, options)\n}\nexport type CreateRipaVideoMutationHookResult = ReturnType<\n typeof useCreateRipaVideoMutation\n>\nexport type CreateRipaVideoMutationResult = Apollo.MutationResult<\n GQL_CreateRipaVideoMutation\n>\nexport type CreateRipaVideoMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateRipaVideoMutation,\n GQL_CreateRipaVideoMutationVariables\n>\nexport const GetRipaVideosDocument = gql`\n query getRipaVideos($storyId: ID!) {\n currentUser {\n id\n story(id: $storyId) {\n id\n adventureRipaVideos {\n ...Video\n }\n accommodationRipaVideos {\n ...Video\n }\n }\n }\n }\n ${VideoFragmentDoc}\n`\n\n/**\n * __useGetRipaVideosQuery__\n *\n * To run a query within a React component, call `useGetRipaVideosQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetRipaVideosQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetRipaVideosQuery({\n * variables: {\n * storyId: // value for 'storyId'\n * },\n * });\n */\nexport function useGetRipaVideosQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetRipaVideosQuery,\n GQL_GetRipaVideosQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetRipaVideosQuery,\n GQL_GetRipaVideosQueryVariables\n >(GetRipaVideosDocument, options)\n}\nexport function useGetRipaVideosLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetRipaVideosQuery,\n GQL_GetRipaVideosQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetRipaVideosQuery,\n GQL_GetRipaVideosQueryVariables\n >(GetRipaVideosDocument, options)\n}\nexport type GetRipaVideosQueryHookResult = ReturnType<\n typeof useGetRipaVideosQuery\n>\nexport type GetRipaVideosLazyQueryHookResult = ReturnType<\n typeof useGetRipaVideosLazyQuery\n>\nexport type GetRipaVideosQueryResult = Apollo.QueryResult<\n GQL_GetRipaVideosQuery,\n GQL_GetRipaVideosQueryVariables\n>\nexport const CreateSavedMessageDocument = gql`\n mutation createSavedMessage($text: String!, $title: String!) {\n createSavedMessage(text: $text, title: $title) {\n savedMessage {\n id\n title\n text\n }\n }\n }\n`\nexport type GQL_CreateSavedMessageMutationFn = Apollo.MutationFunction<\n GQL_CreateSavedMessageMutation,\n GQL_CreateSavedMessageMutationVariables\n>\n\n/**\n * __useCreateSavedMessageMutation__\n *\n * To run a mutation, you first call `useCreateSavedMessageMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateSavedMessageMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createSavedMessageMutation, { data, loading, error }] = useCreateSavedMessageMutation({\n * variables: {\n * text: // value for 'text'\n * title: // value for 'title'\n * },\n * });\n */\nexport function useCreateSavedMessageMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateSavedMessageMutation,\n GQL_CreateSavedMessageMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateSavedMessageMutation,\n GQL_CreateSavedMessageMutationVariables\n >(CreateSavedMessageDocument, options)\n}\nexport type CreateSavedMessageMutationHookResult = ReturnType<\n typeof useCreateSavedMessageMutation\n>\nexport type CreateSavedMessageMutationResult = Apollo.MutationResult<\n GQL_CreateSavedMessageMutation\n>\nexport type CreateSavedMessageMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateSavedMessageMutation,\n GQL_CreateSavedMessageMutationVariables\n>\nexport const DestroySavedMessageDocument = gql`\n mutation destroySavedMessage($id: ID!) {\n destroySavedMessage(savedMessageId: $id) {\n savedMessages {\n id\n text\n title\n }\n }\n }\n`\nexport type GQL_DestroySavedMessageMutationFn = Apollo.MutationFunction<\n GQL_DestroySavedMessageMutation,\n GQL_DestroySavedMessageMutationVariables\n>\n\n/**\n * __useDestroySavedMessageMutation__\n *\n * To run a mutation, you first call `useDestroySavedMessageMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDestroySavedMessageMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [destroySavedMessageMutation, { data, loading, error }] = useDestroySavedMessageMutation({\n * variables: {\n * id: // value for 'id'\n * },\n * });\n */\nexport function useDestroySavedMessageMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_DestroySavedMessageMutation,\n GQL_DestroySavedMessageMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_DestroySavedMessageMutation,\n GQL_DestroySavedMessageMutationVariables\n >(DestroySavedMessageDocument, options)\n}\nexport type DestroySavedMessageMutationHookResult = ReturnType<\n typeof useDestroySavedMessageMutation\n>\nexport type DestroySavedMessageMutationResult = Apollo.MutationResult<\n GQL_DestroySavedMessageMutation\n>\nexport type DestroySavedMessageMutationOptions = Apollo.BaseMutationOptions<\n GQL_DestroySavedMessageMutation,\n GQL_DestroySavedMessageMutationVariables\n>\nexport const GetSavedMessagesDocument = gql`\n query getSavedMessages {\n currentUser {\n id\n savedMessages {\n id\n text\n title\n }\n }\n }\n`\n\n/**\n * __useGetSavedMessagesQuery__\n *\n * To run a query within a React component, call `useGetSavedMessagesQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetSavedMessagesQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetSavedMessagesQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetSavedMessagesQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetSavedMessagesQuery,\n GQL_GetSavedMessagesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetSavedMessagesQuery,\n GQL_GetSavedMessagesQueryVariables\n >(GetSavedMessagesDocument, options)\n}\nexport function useGetSavedMessagesLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetSavedMessagesQuery,\n GQL_GetSavedMessagesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetSavedMessagesQuery,\n GQL_GetSavedMessagesQueryVariables\n >(GetSavedMessagesDocument, options)\n}\nexport type GetSavedMessagesQueryHookResult = ReturnType<\n typeof useGetSavedMessagesQuery\n>\nexport type GetSavedMessagesLazyQueryHookResult = ReturnType<\n typeof useGetSavedMessagesLazyQuery\n>\nexport type GetSavedMessagesQueryResult = Apollo.QueryResult<\n GQL_GetSavedMessagesQuery,\n GQL_GetSavedMessagesQueryVariables\n>\nexport const UpdateSavedMessageDocument = gql`\n mutation updateSavedMessage($id: ID!, $text: String!, $title: String!) {\n updateSavedMessage(savedMessageId: $id, text: $text, title: $title) {\n savedMessage {\n id\n text\n title\n }\n }\n }\n`\nexport type GQL_UpdateSavedMessageMutationFn = Apollo.MutationFunction<\n GQL_UpdateSavedMessageMutation,\n GQL_UpdateSavedMessageMutationVariables\n>\n\n/**\n * __useUpdateSavedMessageMutation__\n *\n * To run a mutation, you first call `useUpdateSavedMessageMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateSavedMessageMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateSavedMessageMutation, { data, loading, error }] = useUpdateSavedMessageMutation({\n * variables: {\n * id: // value for 'id'\n * text: // value for 'text'\n * title: // value for 'title'\n * },\n * });\n */\nexport function useUpdateSavedMessageMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_UpdateSavedMessageMutation,\n GQL_UpdateSavedMessageMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_UpdateSavedMessageMutation,\n GQL_UpdateSavedMessageMutationVariables\n >(UpdateSavedMessageDocument, options)\n}\nexport type UpdateSavedMessageMutationHookResult = ReturnType<\n typeof useUpdateSavedMessageMutation\n>\nexport type UpdateSavedMessageMutationResult = Apollo.MutationResult<\n GQL_UpdateSavedMessageMutation\n>\nexport type UpdateSavedMessageMutationOptions = Apollo.BaseMutationOptions<\n GQL_UpdateSavedMessageMutation,\n GQL_UpdateSavedMessageMutationVariables\n>\nexport const ArchiveConversationDocument = gql`\n mutation archiveConversation($conversationId: ID!) {\n archiveConversation(conversationId: $conversationId) {\n conversation {\n id\n archivable\n archivedAt\n }\n }\n }\n`\nexport type GQL_ArchiveConversationMutationFn = Apollo.MutationFunction<\n GQL_ArchiveConversationMutation,\n GQL_ArchiveConversationMutationVariables\n>\n\n/**\n * __useArchiveConversationMutation__\n *\n * To run a mutation, you first call `useArchiveConversationMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useArchiveConversationMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [archiveConversationMutation, { data, loading, error }] = useArchiveConversationMutation({\n * variables: {\n * conversationId: // value for 'conversationId'\n * },\n * });\n */\nexport function useArchiveConversationMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_ArchiveConversationMutation,\n GQL_ArchiveConversationMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_ArchiveConversationMutation,\n GQL_ArchiveConversationMutationVariables\n >(ArchiveConversationDocument, options)\n}\nexport type ArchiveConversationMutationHookResult = ReturnType<\n typeof useArchiveConversationMutation\n>\nexport type ArchiveConversationMutationResult = Apollo.MutationResult<\n GQL_ArchiveConversationMutation\n>\nexport type ArchiveConversationMutationOptions = Apollo.BaseMutationOptions<\n GQL_ArchiveConversationMutation,\n GQL_ArchiveConversationMutationVariables\n>\nexport const InboxDocument = gql`\n query inbox(\n $bookingRequestsFirst: Int = 10\n $bookingRequestsCursor: String\n $unreadFirst: Int = 10\n $unreadCursor: String\n $readFirst: Int = 10\n $readCursor: String\n ) {\n currentUser {\n id\n host\n assignments {\n ...Assignment\n ...AssignmentBookingField\n }\n }\n inbox {\n bookingRequests(\n first: $bookingRequestsFirst\n after: $bookingRequestsCursor\n ) @connection(key: \"bookingRequests\") {\n ...ConversationConnectionFragment\n }\n unread(first: $unreadFirst, after: $unreadCursor)\n @connection(key: \"unread\") {\n ...ConversationConnectionFragment\n }\n read(first: $readFirst, after: $readCursor) @connection(key: \"read\") {\n ...ConversationConnectionFragment\n }\n }\n }\n ${AssignmentFragmentDoc}\n ${AssignmentBookingFieldFragmentDoc}\n ${ConversationConnectionFragmentFragmentDoc}\n`\n\n/**\n * __useInboxQuery__\n *\n * To run a query within a React component, call `useInboxQuery` and pass it any options that fit your needs.\n * When your component renders, `useInboxQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useInboxQuery({\n * variables: {\n * bookingRequestsFirst: // value for 'bookingRequestsFirst'\n * bookingRequestsCursor: // value for 'bookingRequestsCursor'\n * unreadFirst: // value for 'unreadFirst'\n * unreadCursor: // value for 'unreadCursor'\n * readFirst: // value for 'readFirst'\n * readCursor: // value for 'readCursor'\n * },\n * });\n */\nexport function useInboxQuery(\n baseOptions?: Apollo.QueryHookOptions\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n InboxDocument,\n options\n )\n}\nexport function useInboxLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_InboxQuery,\n GQL_InboxQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery(\n InboxDocument,\n options\n )\n}\nexport type InboxQueryHookResult = ReturnType\nexport type InboxLazyQueryHookResult = ReturnType\nexport type InboxQueryResult = Apollo.QueryResult<\n GQL_InboxQuery,\n GQL_InboxQueryVariables\n>\nexport const RestoreConversationDocument = gql`\n mutation restoreConversation($conversationId: ID!) {\n restoreConversation(conversationId: $conversationId) {\n conversation {\n id\n archivable\n archivedAt\n }\n }\n }\n`\nexport type GQL_RestoreConversationMutationFn = Apollo.MutationFunction<\n GQL_RestoreConversationMutation,\n GQL_RestoreConversationMutationVariables\n>\n\n/**\n * __useRestoreConversationMutation__\n *\n * To run a mutation, you first call `useRestoreConversationMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useRestoreConversationMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [restoreConversationMutation, { data, loading, error }] = useRestoreConversationMutation({\n * variables: {\n * conversationId: // value for 'conversationId'\n * },\n * });\n */\nexport function useRestoreConversationMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_RestoreConversationMutation,\n GQL_RestoreConversationMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_RestoreConversationMutation,\n GQL_RestoreConversationMutationVariables\n >(RestoreConversationDocument, options)\n}\nexport type RestoreConversationMutationHookResult = ReturnType<\n typeof useRestoreConversationMutation\n>\nexport type RestoreConversationMutationResult = Apollo.MutationResult<\n GQL_RestoreConversationMutation\n>\nexport type RestoreConversationMutationOptions = Apollo.BaseMutationOptions<\n GQL_RestoreConversationMutation,\n GQL_RestoreConversationMutationVariables\n>\nexport const SendMessageDocument = gql`\n mutation sendMessage(\n $conversationId: ID!\n $body: String!\n $attachments: [AttachmentInput!]\n ) {\n sendMessage(\n conversationId: $conversationId\n body: $body\n attachments: $attachments\n ) {\n message {\n body\n }\n }\n }\n`\nexport type GQL_SendMessageMutationFn = Apollo.MutationFunction<\n GQL_SendMessageMutation,\n GQL_SendMessageMutationVariables\n>\n\n/**\n * __useSendMessageMutation__\n *\n * To run a mutation, you first call `useSendMessageMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useSendMessageMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [sendMessageMutation, { data, loading, error }] = useSendMessageMutation({\n * variables: {\n * conversationId: // value for 'conversationId'\n * body: // value for 'body'\n * attachments: // value for 'attachments'\n * },\n * });\n */\nexport function useSendMessageMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_SendMessageMutation,\n GQL_SendMessageMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_SendMessageMutation,\n GQL_SendMessageMutationVariables\n >(SendMessageDocument, options)\n}\nexport type SendMessageMutationHookResult = ReturnType<\n typeof useSendMessageMutation\n>\nexport type SendMessageMutationResult = Apollo.MutationResult<\n GQL_SendMessageMutation\n>\nexport type SendMessageMutationOptions = Apollo.BaseMutationOptions<\n GQL_SendMessageMutation,\n GQL_SendMessageMutationVariables\n>\nexport const GetSearchBarResultsDocument = gql`\n query getSearchBarResults($query: String!, $sessionToken: String) {\n searchByTitle(query: $query, sessionToken: $sessionToken) {\n result {\n ... on Listing {\n id\n __typename\n title\n url\n promoImage {\n thumb\n }\n location {\n name\n lat\n lng\n }\n }\n ... on Story {\n id\n __typename\n title\n url\n user {\n id\n firstName\n avatar {\n original\n }\n }\n promoImage {\n thumb\n }\n featuredListing {\n location {\n name\n lat\n lng\n }\n }\n }\n ... on Region {\n id\n __typename\n name\n slug\n state {\n id\n countryId\n code\n }\n }\n ... on Prediction {\n __typename\n googlePlaceId\n description\n mainText\n }\n }\n }\n }\n`\n\n/**\n * __useGetSearchBarResultsQuery__\n *\n * To run a query within a React component, call `useGetSearchBarResultsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetSearchBarResultsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetSearchBarResultsQuery({\n * variables: {\n * query: // value for 'query'\n * sessionToken: // value for 'sessionToken'\n * },\n * });\n */\nexport function useGetSearchBarResultsQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetSearchBarResultsQuery,\n GQL_GetSearchBarResultsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetSearchBarResultsQuery,\n GQL_GetSearchBarResultsQueryVariables\n >(GetSearchBarResultsDocument, options)\n}\nexport function useGetSearchBarResultsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetSearchBarResultsQuery,\n GQL_GetSearchBarResultsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetSearchBarResultsQuery,\n GQL_GetSearchBarResultsQueryVariables\n >(GetSearchBarResultsDocument, options)\n}\nexport type GetSearchBarResultsQueryHookResult = ReturnType<\n typeof useGetSearchBarResultsQuery\n>\nexport type GetSearchBarResultsLazyQueryHookResult = ReturnType<\n typeof useGetSearchBarResultsLazyQuery\n>\nexport type GetSearchBarResultsQueryResult = Apollo.QueryResult<\n GQL_GetSearchBarResultsQuery,\n GQL_GetSearchBarResultsQueryVariables\n>\nexport const GetStatesForCountryDocument = gql`\n query getStatesForCountry($country: Countries!) {\n search(params: { country: $country }) {\n defaults {\n states {\n id\n code\n name\n countryId\n }\n }\n }\n }\n`\n\n/**\n * __useGetStatesForCountryQuery__\n *\n * To run a query within a React component, call `useGetStatesForCountryQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetStatesForCountryQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetStatesForCountryQuery({\n * variables: {\n * country: // value for 'country'\n * },\n * });\n */\nexport function useGetStatesForCountryQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetStatesForCountryQuery,\n GQL_GetStatesForCountryQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetStatesForCountryQuery,\n GQL_GetStatesForCountryQueryVariables\n >(GetStatesForCountryDocument, options)\n}\nexport function useGetStatesForCountryLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetStatesForCountryQuery,\n GQL_GetStatesForCountryQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetStatesForCountryQuery,\n GQL_GetStatesForCountryQueryVariables\n >(GetStatesForCountryDocument, options)\n}\nexport type GetStatesForCountryQueryHookResult = ReturnType<\n typeof useGetStatesForCountryQuery\n>\nexport type GetStatesForCountryLazyQueryHookResult = ReturnType<\n typeof useGetStatesForCountryLazyQuery\n>\nexport type GetStatesForCountryQueryResult = Apollo.QueryResult<\n GQL_GetStatesForCountryQuery,\n GQL_GetStatesForCountryQueryVariables\n>\nexport const PlaceLookupDocument = gql`\n query placeLookup($googlePlaceId: String!, $sessionToken: String) {\n placeLookup(googlePlaceId: $googlePlaceId, sessionToken: $sessionToken) {\n name\n googlePlaceId\n origin\n bounds {\n sw\n ne\n }\n country {\n code\n }\n }\n }\n`\n\n/**\n * __usePlaceLookupQuery__\n *\n * To run a query within a React component, call `usePlaceLookupQuery` and pass it any options that fit your needs.\n * When your component renders, `usePlaceLookupQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = usePlaceLookupQuery({\n * variables: {\n * googlePlaceId: // value for 'googlePlaceId'\n * sessionToken: // value for 'sessionToken'\n * },\n * });\n */\nexport function usePlaceLookupQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_PlaceLookupQuery,\n GQL_PlaceLookupQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n PlaceLookupDocument,\n options\n )\n}\nexport function usePlaceLookupLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_PlaceLookupQuery,\n GQL_PlaceLookupQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_PlaceLookupQuery,\n GQL_PlaceLookupQueryVariables\n >(PlaceLookupDocument, options)\n}\nexport type PlaceLookupQueryHookResult = ReturnType\nexport type PlaceLookupLazyQueryHookResult = ReturnType<\n typeof usePlaceLookupLazyQuery\n>\nexport type PlaceLookupQueryResult = Apollo.QueryResult<\n GQL_PlaceLookupQuery,\n GQL_PlaceLookupQueryVariables\n>\nexport const GetAdventureWithListingDocument = gql`\n query getAdventureWithListing($adventureId: ID!) {\n adventure(id: $adventureId) {\n id\n description\n locationType\n title\n adventureType {\n id\n name\n slug\n category\n }\n location {\n name\n lat\n lng\n }\n reviewScore\n ... on StoryAdventure {\n storyUrl\n storyteller {\n id\n firstName\n url\n avatar {\n original\n thumb\n thumbLg\n }\n }\n story {\n id\n title\n url\n active\n featuredListing {\n id\n state\n market {\n id\n code\n name\n }\n coordinates\n region {\n id\n name\n slug\n }\n subcategory {\n id\n slug\n }\n }\n }\n }\n }\n }\n`\n\n/**\n * __useGetAdventureWithListingQuery__\n *\n * To run a query within a React component, call `useGetAdventureWithListingQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetAdventureWithListingQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetAdventureWithListingQuery({\n * variables: {\n * adventureId: // value for 'adventureId'\n * },\n * });\n */\nexport function useGetAdventureWithListingQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetAdventureWithListingQuery,\n GQL_GetAdventureWithListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetAdventureWithListingQuery,\n GQL_GetAdventureWithListingQueryVariables\n >(GetAdventureWithListingDocument, options)\n}\nexport function useGetAdventureWithListingLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetAdventureWithListingQuery,\n GQL_GetAdventureWithListingQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetAdventureWithListingQuery,\n GQL_GetAdventureWithListingQueryVariables\n >(GetAdventureWithListingDocument, options)\n}\nexport type GetAdventureWithListingQueryHookResult = ReturnType<\n typeof useGetAdventureWithListingQuery\n>\nexport type GetAdventureWithListingLazyQueryHookResult = ReturnType<\n typeof useGetAdventureWithListingLazyQuery\n>\nexport type GetAdventureWithListingQueryResult = Apollo.QueryResult<\n GQL_GetAdventureWithListingQuery,\n GQL_GetAdventureWithListingQueryVariables\n>\nexport const GetAdventurePhotosDocument = gql`\n query getAdventurePhotos($id: ID!) {\n adventure(id: $id) {\n id\n photos(first: 10) {\n aspectRatio\n createdAt\n id\n image {\n original\n medium\n large\n hero\n thumb\n }\n position\n updatedAt\n }\n }\n }\n`\n\n/**\n * __useGetAdventurePhotosQuery__\n *\n * To run a query within a React component, call `useGetAdventurePhotosQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetAdventurePhotosQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetAdventurePhotosQuery({\n * variables: {\n * id: // value for 'id'\n * },\n * });\n */\nexport function useGetAdventurePhotosQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetAdventurePhotosQuery,\n GQL_GetAdventurePhotosQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetAdventurePhotosQuery,\n GQL_GetAdventurePhotosQueryVariables\n >(GetAdventurePhotosDocument, options)\n}\nexport function useGetAdventurePhotosLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetAdventurePhotosQuery,\n GQL_GetAdventurePhotosQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetAdventurePhotosQuery,\n GQL_GetAdventurePhotosQueryVariables\n >(GetAdventurePhotosDocument, options)\n}\nexport type GetAdventurePhotosQueryHookResult = ReturnType<\n typeof useGetAdventurePhotosQuery\n>\nexport type GetAdventurePhotosLazyQueryHookResult = ReturnType<\n typeof useGetAdventurePhotosLazyQuery\n>\nexport type GetAdventurePhotosQueryResult = Apollo.QueryResult<\n GQL_GetAdventurePhotosQuery,\n GQL_GetAdventurePhotosQueryVariables\n>\nexport const GetAdventureReviewsDocument = gql`\n query getAdventureReviews($id: ID!, $cursor: String) {\n adventure(id: $id) {\n id\n reviews(first: 3, after: $cursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n node {\n id\n createdAt\n content\n reviewer {\n firstName\n avatar {\n original\n thumbLg\n }\n }\n fulfillingMoments {\n slug\n name\n }\n }\n }\n }\n }\n }\n`\n\n/**\n * __useGetAdventureReviewsQuery__\n *\n * To run a query within a React component, call `useGetAdventureReviewsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetAdventureReviewsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetAdventureReviewsQuery({\n * variables: {\n * id: // value for 'id'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetAdventureReviewsQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetAdventureReviewsQuery,\n GQL_GetAdventureReviewsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetAdventureReviewsQuery,\n GQL_GetAdventureReviewsQueryVariables\n >(GetAdventureReviewsDocument, options)\n}\nexport function useGetAdventureReviewsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetAdventureReviewsQuery,\n GQL_GetAdventureReviewsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetAdventureReviewsQuery,\n GQL_GetAdventureReviewsQueryVariables\n >(GetAdventureReviewsDocument, options)\n}\nexport type GetAdventureReviewsQueryHookResult = ReturnType<\n typeof useGetAdventureReviewsQuery\n>\nexport type GetAdventureReviewsLazyQueryHookResult = ReturnType<\n typeof useGetAdventureReviewsLazyQuery\n>\nexport type GetAdventureReviewsQueryResult = Apollo.QueryResult<\n GQL_GetAdventureReviewsQuery,\n GQL_GetAdventureReviewsQueryVariables\n>\nexport const GetNearbyAdventuresDocument = gql`\n query getNearbyAdventures($id: ID!, $pageSize: Int = 3, $cursor: String) {\n adventure(id: $id) {\n id\n nearbyAdventures(first: $pageSize, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n ...AdventureCardFragment\n }\n }\n }\n }\n }\n ${AdventureCardFragmentFragmentDoc}\n`\n\n/**\n * __useGetNearbyAdventuresQuery__\n *\n * To run a query within a React component, call `useGetNearbyAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetNearbyAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetNearbyAdventuresQuery({\n * variables: {\n * id: // value for 'id'\n * pageSize: // value for 'pageSize'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetNearbyAdventuresQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetNearbyAdventuresQuery,\n GQL_GetNearbyAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetNearbyAdventuresQuery,\n GQL_GetNearbyAdventuresQueryVariables\n >(GetNearbyAdventuresDocument, options)\n}\nexport function useGetNearbyAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetNearbyAdventuresQuery,\n GQL_GetNearbyAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetNearbyAdventuresQuery,\n GQL_GetNearbyAdventuresQueryVariables\n >(GetNearbyAdventuresDocument, options)\n}\nexport type GetNearbyAdventuresQueryHookResult = ReturnType<\n typeof useGetNearbyAdventuresQuery\n>\nexport type GetNearbyAdventuresLazyQueryHookResult = ReturnType<\n typeof useGetNearbyAdventuresLazyQuery\n>\nexport type GetNearbyAdventuresQueryResult = Apollo.QueryResult<\n GQL_GetNearbyAdventuresQuery,\n GQL_GetNearbyAdventuresQueryVariables\n>\nexport const GetBucketListDocument = gql`\n query getBucketList($token: String!) {\n bucketList(token: $token) {\n ...BucketListFragment\n user {\n id\n firstName\n }\n }\n }\n ${BucketListFragmentFragmentDoc}\n`\n\n/**\n * __useGetBucketListQuery__\n *\n * To run a query within a React component, call `useGetBucketListQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBucketListQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBucketListQuery({\n * variables: {\n * token: // value for 'token'\n * },\n * });\n */\nexport function useGetBucketListQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBucketListQuery,\n GQL_GetBucketListQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBucketListQuery,\n GQL_GetBucketListQueryVariables\n >(GetBucketListDocument, options)\n}\nexport function useGetBucketListLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBucketListQuery,\n GQL_GetBucketListQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBucketListQuery,\n GQL_GetBucketListQueryVariables\n >(GetBucketListDocument, options)\n}\nexport type GetBucketListQueryHookResult = ReturnType<\n typeof useGetBucketListQuery\n>\nexport type GetBucketListLazyQueryHookResult = ReturnType<\n typeof useGetBucketListLazyQuery\n>\nexport type GetBucketListQueryResult = Apollo.QueryResult<\n GQL_GetBucketListQuery,\n GQL_GetBucketListQueryVariables\n>\nexport const GetBucketListItemsDocument = gql`\n query getBucketListItems(\n $token: String!\n $params: SearchFilters\n $first: Int\n $cursor: String\n ) {\n bucketList(token: $token) {\n id\n items(params: $params, first: $first, after: $cursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n ...BucketListItemConnection\n }\n }\n }\n ${BucketListItemConnectionFragmentDoc}\n`\n\n/**\n * __useGetBucketListItemsQuery__\n *\n * To run a query within a React component, call `useGetBucketListItemsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBucketListItemsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBucketListItemsQuery({\n * variables: {\n * token: // value for 'token'\n * params: // value for 'params'\n * first: // value for 'first'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetBucketListItemsQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBucketListItemsQuery,\n GQL_GetBucketListItemsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBucketListItemsQuery,\n GQL_GetBucketListItemsQueryVariables\n >(GetBucketListItemsDocument, options)\n}\nexport function useGetBucketListItemsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBucketListItemsQuery,\n GQL_GetBucketListItemsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBucketListItemsQuery,\n GQL_GetBucketListItemsQueryVariables\n >(GetBucketListItemsDocument, options)\n}\nexport type GetBucketListItemsQueryHookResult = ReturnType<\n typeof useGetBucketListItemsQuery\n>\nexport type GetBucketListItemsLazyQueryHookResult = ReturnType<\n typeof useGetBucketListItemsLazyQuery\n>\nexport type GetBucketListItemsQueryResult = Apollo.QueryResult<\n GQL_GetBucketListItemsQuery,\n GQL_GetBucketListItemsQueryVariables\n>\nexport const GetBucketListMapResultsDocument = gql`\n query getBucketListMapResults($token: String!, $params: SearchFilters) {\n bucketList(token: $token) {\n id\n mapResults(params: $params) {\n ...MapResultFragment\n }\n }\n }\n ${MapResultFragmentFragmentDoc}\n`\n\n/**\n * __useGetBucketListMapResultsQuery__\n *\n * To run a query within a React component, call `useGetBucketListMapResultsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetBucketListMapResultsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetBucketListMapResultsQuery({\n * variables: {\n * token: // value for 'token'\n * params: // value for 'params'\n * },\n * });\n */\nexport function useGetBucketListMapResultsQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetBucketListMapResultsQuery,\n GQL_GetBucketListMapResultsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetBucketListMapResultsQuery,\n GQL_GetBucketListMapResultsQueryVariables\n >(GetBucketListMapResultsDocument, options)\n}\nexport function useGetBucketListMapResultsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetBucketListMapResultsQuery,\n GQL_GetBucketListMapResultsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetBucketListMapResultsQuery,\n GQL_GetBucketListMapResultsQueryVariables\n >(GetBucketListMapResultsDocument, options)\n}\nexport type GetBucketListMapResultsQueryHookResult = ReturnType<\n typeof useGetBucketListMapResultsQuery\n>\nexport type GetBucketListMapResultsLazyQueryHookResult = ReturnType<\n typeof useGetBucketListMapResultsLazyQuery\n>\nexport type GetBucketListMapResultsQueryResult = Apollo.QueryResult<\n GQL_GetBucketListMapResultsQuery,\n GQL_GetBucketListMapResultsQueryVariables\n>\nexport const GetCollectionWithItemsOnlyDocument = gql`\n query getCollectionWithItemsOnly(\n $id: ID!\n $pageSize: Int = 12\n $cursor: String\n ) {\n collection(id: $id) {\n id\n ... on Collection {\n id\n items(first: $pageSize, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n photo {\n medium\n large\n }\n item {\n __typename\n ... on Listing {\n ...ListingCardFragment\n stories {\n ...StoryCardFragment\n }\n }\n ... on Story {\n ...StoryCardFragment\n featuredListing {\n ...StoryFeaturedListingFragment\n }\n }\n ... on StoryAdventure {\n ...AdventureCardFragment\n }\n ... on ListingAdventure {\n ...ListingAdventure\n }\n }\n }\n }\n }\n }\n }\n }\n ${ListingCardFragmentFragmentDoc}\n ${StoryCardFragmentFragmentDoc}\n ${StoryFeaturedListingFragmentFragmentDoc}\n ${AdventureCardFragmentFragmentDoc}\n ${ListingAdventureFragmentDoc}\n`\n\n/**\n * __useGetCollectionWithItemsOnlyQuery__\n *\n * To run a query within a React component, call `useGetCollectionWithItemsOnlyQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetCollectionWithItemsOnlyQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetCollectionWithItemsOnlyQuery({\n * variables: {\n * id: // value for 'id'\n * pageSize: // value for 'pageSize'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetCollectionWithItemsOnlyQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetCollectionWithItemsOnlyQuery,\n GQL_GetCollectionWithItemsOnlyQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetCollectionWithItemsOnlyQuery,\n GQL_GetCollectionWithItemsOnlyQueryVariables\n >(GetCollectionWithItemsOnlyDocument, options)\n}\nexport function useGetCollectionWithItemsOnlyLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetCollectionWithItemsOnlyQuery,\n GQL_GetCollectionWithItemsOnlyQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetCollectionWithItemsOnlyQuery,\n GQL_GetCollectionWithItemsOnlyQueryVariables\n >(GetCollectionWithItemsOnlyDocument, options)\n}\nexport type GetCollectionWithItemsOnlyQueryHookResult = ReturnType<\n typeof useGetCollectionWithItemsOnlyQuery\n>\nexport type GetCollectionWithItemsOnlyLazyQueryHookResult = ReturnType<\n typeof useGetCollectionWithItemsOnlyLazyQuery\n>\nexport type GetCollectionWithItemsOnlyQueryResult = Apollo.QueryResult<\n GQL_GetCollectionWithItemsOnlyQuery,\n GQL_GetCollectionWithItemsOnlyQueryVariables\n>\nexport const GetCollectionsDocument = gql`\n query getCollections($marketId: ID!, $first: Int = 4, $cursor: String) {\n collections(marketId: $marketId, first: $first, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n ...Collection\n }\n }\n }\n }\n ${CollectionFragmentDoc}\n`\n\n/**\n * __useGetCollectionsQuery__\n *\n * To run a query within a React component, call `useGetCollectionsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetCollectionsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetCollectionsQuery({\n * variables: {\n * marketId: // value for 'marketId'\n * first: // value for 'first'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetCollectionsQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetCollectionsQuery,\n GQL_GetCollectionsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetCollectionsQuery,\n GQL_GetCollectionsQueryVariables\n >(GetCollectionsDocument, options)\n}\nexport function useGetCollectionsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetCollectionsQuery,\n GQL_GetCollectionsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetCollectionsQuery,\n GQL_GetCollectionsQueryVariables\n >(GetCollectionsDocument, options)\n}\nexport type GetCollectionsQueryHookResult = ReturnType<\n typeof useGetCollectionsQuery\n>\nexport type GetCollectionsLazyQueryHookResult = ReturnType<\n typeof useGetCollectionsLazyQuery\n>\nexport type GetCollectionsQueryResult = Apollo.QueryResult<\n GQL_GetCollectionsQuery,\n GQL_GetCollectionsQueryVariables\n>\nexport const GetGlobalFeaturedAdventuresDocument = gql`\n query getGlobalFeaturedAdventures(\n $country: Countries\n $first: Int\n $cursor: String\n ) {\n featuredAdventures(country: $country, first: $first, after: $cursor) {\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n edges {\n node {\n id\n ...AdventureCardFragment\n }\n }\n }\n }\n ${AdventureCardFragmentFragmentDoc}\n`\n\n/**\n * __useGetGlobalFeaturedAdventuresQuery__\n *\n * To run a query within a React component, call `useGetGlobalFeaturedAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetGlobalFeaturedAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetGlobalFeaturedAdventuresQuery({\n * variables: {\n * country: // value for 'country'\n * first: // value for 'first'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetGlobalFeaturedAdventuresQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetGlobalFeaturedAdventuresQuery,\n GQL_GetGlobalFeaturedAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetGlobalFeaturedAdventuresQuery,\n GQL_GetGlobalFeaturedAdventuresQueryVariables\n >(GetGlobalFeaturedAdventuresDocument, options)\n}\nexport function useGetGlobalFeaturedAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetGlobalFeaturedAdventuresQuery,\n GQL_GetGlobalFeaturedAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetGlobalFeaturedAdventuresQuery,\n GQL_GetGlobalFeaturedAdventuresQueryVariables\n >(GetGlobalFeaturedAdventuresDocument, options)\n}\nexport type GetGlobalFeaturedAdventuresQueryHookResult = ReturnType<\n typeof useGetGlobalFeaturedAdventuresQuery\n>\nexport type GetGlobalFeaturedAdventuresLazyQueryHookResult = ReturnType<\n typeof useGetGlobalFeaturedAdventuresLazyQuery\n>\nexport type GetGlobalFeaturedAdventuresQueryResult = Apollo.QueryResult<\n GQL_GetGlobalFeaturedAdventuresQuery,\n GQL_GetGlobalFeaturedAdventuresQueryVariables\n>\nexport const GetMarketAdventuresDocument = gql`\n query getMarketAdventures($market: Markets!, $first: Int, $cursor: String) {\n market(code: $market) {\n id\n adventures(first: $first, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n ...AdventureCardFragment\n }\n }\n }\n }\n }\n ${AdventureCardFragmentFragmentDoc}\n`\n\n/**\n * __useGetMarketAdventuresQuery__\n *\n * To run a query within a React component, call `useGetMarketAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMarketAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMarketAdventuresQuery({\n * variables: {\n * market: // value for 'market'\n * first: // value for 'first'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetMarketAdventuresQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetMarketAdventuresQuery,\n GQL_GetMarketAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMarketAdventuresQuery,\n GQL_GetMarketAdventuresQueryVariables\n >(GetMarketAdventuresDocument, options)\n}\nexport function useGetMarketAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMarketAdventuresQuery,\n GQL_GetMarketAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMarketAdventuresQuery,\n GQL_GetMarketAdventuresQueryVariables\n >(GetMarketAdventuresDocument, options)\n}\nexport type GetMarketAdventuresQueryHookResult = ReturnType<\n typeof useGetMarketAdventuresQuery\n>\nexport type GetMarketAdventuresLazyQueryHookResult = ReturnType<\n typeof useGetMarketAdventuresLazyQuery\n>\nexport type GetMarketAdventuresQueryResult = Apollo.QueryResult<\n GQL_GetMarketAdventuresQuery,\n GQL_GetMarketAdventuresQueryVariables\n>\nexport const GetGlobalFeaturedCollectionsDocument = gql`\n query getGlobalFeaturedCollections(\n $country: Countries\n $first: Int\n $cursor: String\n ) {\n featuredCollections(country: $country, first: $first, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n ...Collection\n }\n }\n }\n }\n ${CollectionFragmentDoc}\n`\n\n/**\n * __useGetGlobalFeaturedCollectionsQuery__\n *\n * To run a query within a React component, call `useGetGlobalFeaturedCollectionsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetGlobalFeaturedCollectionsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetGlobalFeaturedCollectionsQuery({\n * variables: {\n * country: // value for 'country'\n * first: // value for 'first'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetGlobalFeaturedCollectionsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetGlobalFeaturedCollectionsQuery,\n GQL_GetGlobalFeaturedCollectionsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetGlobalFeaturedCollectionsQuery,\n GQL_GetGlobalFeaturedCollectionsQueryVariables\n >(GetGlobalFeaturedCollectionsDocument, options)\n}\nexport function useGetGlobalFeaturedCollectionsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetGlobalFeaturedCollectionsQuery,\n GQL_GetGlobalFeaturedCollectionsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetGlobalFeaturedCollectionsQuery,\n GQL_GetGlobalFeaturedCollectionsQueryVariables\n >(GetGlobalFeaturedCollectionsDocument, options)\n}\nexport type GetGlobalFeaturedCollectionsQueryHookResult = ReturnType<\n typeof useGetGlobalFeaturedCollectionsQuery\n>\nexport type GetGlobalFeaturedCollectionsLazyQueryHookResult = ReturnType<\n typeof useGetGlobalFeaturedCollectionsLazyQuery\n>\nexport type GetGlobalFeaturedCollectionsQueryResult = Apollo.QueryResult<\n GQL_GetGlobalFeaturedCollectionsQuery,\n GQL_GetGlobalFeaturedCollectionsQueryVariables\n>\nexport const GetMarketFeaturedCollectionsDocument = gql`\n query getMarketFeaturedCollections(\n $market: Markets!\n $first: Int\n $cursor: String\n ) {\n market(code: $market) {\n id\n featuredCollections(first: $first, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n ...Collection\n }\n }\n }\n }\n }\n ${CollectionFragmentDoc}\n`\n\n/**\n * __useGetMarketFeaturedCollectionsQuery__\n *\n * To run a query within a React component, call `useGetMarketFeaturedCollectionsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMarketFeaturedCollectionsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMarketFeaturedCollectionsQuery({\n * variables: {\n * market: // value for 'market'\n * first: // value for 'first'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetMarketFeaturedCollectionsQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetMarketFeaturedCollectionsQuery,\n GQL_GetMarketFeaturedCollectionsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMarketFeaturedCollectionsQuery,\n GQL_GetMarketFeaturedCollectionsQueryVariables\n >(GetMarketFeaturedCollectionsDocument, options)\n}\nexport function useGetMarketFeaturedCollectionsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMarketFeaturedCollectionsQuery,\n GQL_GetMarketFeaturedCollectionsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMarketFeaturedCollectionsQuery,\n GQL_GetMarketFeaturedCollectionsQueryVariables\n >(GetMarketFeaturedCollectionsDocument, options)\n}\nexport type GetMarketFeaturedCollectionsQueryHookResult = ReturnType<\n typeof useGetMarketFeaturedCollectionsQuery\n>\nexport type GetMarketFeaturedCollectionsLazyQueryHookResult = ReturnType<\n typeof useGetMarketFeaturedCollectionsLazyQuery\n>\nexport type GetMarketFeaturedCollectionsQueryResult = Apollo.QueryResult<\n GQL_GetMarketFeaturedCollectionsQuery,\n GQL_GetMarketFeaturedCollectionsQueryVariables\n>\nexport const GetListingAdventuresByProximityDocument = gql`\n query getListingAdventuresByProximity(\n $afterCursor: String\n $beforeCursor: String\n $first: Int\n $listingId: ID!\n ) {\n listing(id: $listingId) {\n id\n adventuresByProximity(\n after: $afterCursor\n before: $beforeCursor\n first: $first\n ) {\n pageInfo {\n hasNextPage\n hasPreviousPage\n endCursor\n startCursor\n }\n edges {\n node {\n ...ListingNearbyAdventure\n }\n }\n }\n }\n }\n ${ListingNearbyAdventureFragmentDoc}\n`\n\n/**\n * __useGetListingAdventuresByProximityQuery__\n *\n * To run a query within a React component, call `useGetListingAdventuresByProximityQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetListingAdventuresByProximityQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetListingAdventuresByProximityQuery({\n * variables: {\n * afterCursor: // value for 'afterCursor'\n * beforeCursor: // value for 'beforeCursor'\n * first: // value for 'first'\n * listingId: // value for 'listingId'\n * },\n * });\n */\nexport function useGetListingAdventuresByProximityQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetListingAdventuresByProximityQuery,\n GQL_GetListingAdventuresByProximityQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetListingAdventuresByProximityQuery,\n GQL_GetListingAdventuresByProximityQueryVariables\n >(GetListingAdventuresByProximityDocument, options)\n}\nexport function useGetListingAdventuresByProximityLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetListingAdventuresByProximityQuery,\n GQL_GetListingAdventuresByProximityQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetListingAdventuresByProximityQuery,\n GQL_GetListingAdventuresByProximityQueryVariables\n >(GetListingAdventuresByProximityDocument, options)\n}\nexport type GetListingAdventuresByProximityQueryHookResult = ReturnType<\n typeof useGetListingAdventuresByProximityQuery\n>\nexport type GetListingAdventuresByProximityLazyQueryHookResult = ReturnType<\n typeof useGetListingAdventuresByProximityLazyQuery\n>\nexport type GetListingAdventuresByProximityQueryResult = Apollo.QueryResult<\n GQL_GetListingAdventuresByProximityQuery,\n GQL_GetListingAdventuresByProximityQueryVariables\n>\nexport const GetListingPhotosDocument = gql`\n query getListingPhotos($listingId: ID!) {\n listing(id: $listingId) {\n id\n title\n price\n nicePricingSuffix\n photos {\n image {\n large\n }\n aspectRatio\n }\n }\n }\n`\n\n/**\n * __useGetListingPhotosQuery__\n *\n * To run a query within a React component, call `useGetListingPhotosQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetListingPhotosQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetListingPhotosQuery({\n * variables: {\n * listingId: // value for 'listingId'\n * },\n * });\n */\nexport function useGetListingPhotosQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetListingPhotosQuery,\n GQL_GetListingPhotosQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetListingPhotosQuery,\n GQL_GetListingPhotosQueryVariables\n >(GetListingPhotosDocument, options)\n}\nexport function useGetListingPhotosLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetListingPhotosQuery,\n GQL_GetListingPhotosQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetListingPhotosQuery,\n GQL_GetListingPhotosQueryVariables\n >(GetListingPhotosDocument, options)\n}\nexport type GetListingPhotosQueryHookResult = ReturnType<\n typeof useGetListingPhotosQuery\n>\nexport type GetListingPhotosLazyQueryHookResult = ReturnType<\n typeof useGetListingPhotosLazyQuery\n>\nexport type GetListingPhotosQueryResult = Apollo.QueryResult<\n GQL_GetListingPhotosQuery,\n GQL_GetListingPhotosQueryVariables\n>\nexport const GetMarketServiceRatesDocument = gql`\n query getMarketServiceRates($code: Markets!) {\n market(code: $code) {\n id\n customerServiceFeeBaseRate\n hostServiceFeeBaseRate\n }\n }\n`\n\n/**\n * __useGetMarketServiceRatesQuery__\n *\n * To run a query within a React component, call `useGetMarketServiceRatesQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMarketServiceRatesQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMarketServiceRatesQuery({\n * variables: {\n * code: // value for 'code'\n * },\n * });\n */\nexport function useGetMarketServiceRatesQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetMarketServiceRatesQuery,\n GQL_GetMarketServiceRatesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMarketServiceRatesQuery,\n GQL_GetMarketServiceRatesQueryVariables\n >(GetMarketServiceRatesDocument, options)\n}\nexport function useGetMarketServiceRatesLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMarketServiceRatesQuery,\n GQL_GetMarketServiceRatesQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMarketServiceRatesQuery,\n GQL_GetMarketServiceRatesQueryVariables\n >(GetMarketServiceRatesDocument, options)\n}\nexport type GetMarketServiceRatesQueryHookResult = ReturnType<\n typeof useGetMarketServiceRatesQuery\n>\nexport type GetMarketServiceRatesLazyQueryHookResult = ReturnType<\n typeof useGetMarketServiceRatesLazyQuery\n>\nexport type GetMarketServiceRatesQueryResult = Apollo.QueryResult<\n GQL_GetMarketServiceRatesQuery,\n GQL_GetMarketServiceRatesQueryVariables\n>\nexport const GetListingReviewsDocument = gql`\n query getListingReviews($listingId: ID!, $cursor: String) {\n listing(id: $listingId) {\n id\n reviews(first: 3, after: $cursor) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n node {\n ...ListingReview\n }\n }\n }\n }\n }\n ${ListingReviewFragmentDoc}\n`\n\n/**\n * __useGetListingReviewsQuery__\n *\n * To run a query within a React component, call `useGetListingReviewsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetListingReviewsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetListingReviewsQuery({\n * variables: {\n * listingId: // value for 'listingId'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useGetListingReviewsQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetListingReviewsQuery,\n GQL_GetListingReviewsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetListingReviewsQuery,\n GQL_GetListingReviewsQueryVariables\n >(GetListingReviewsDocument, options)\n}\nexport function useGetListingReviewsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetListingReviewsQuery,\n GQL_GetListingReviewsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetListingReviewsQuery,\n GQL_GetListingReviewsQueryVariables\n >(GetListingReviewsDocument, options)\n}\nexport type GetListingReviewsQueryHookResult = ReturnType<\n typeof useGetListingReviewsQuery\n>\nexport type GetListingReviewsLazyQueryHookResult = ReturnType<\n typeof useGetListingReviewsLazyQuery\n>\nexport type GetListingReviewsQueryResult = Apollo.QueryResult<\n GQL_GetListingReviewsQuery,\n GQL_GetListingReviewsQueryVariables\n>\nexport const GetCustomerReferralDocument = gql`\n query getCustomerReferral($token: String!) {\n customerReferral(token: $token) {\n recipientFirstName\n referrer {\n firstName\n avatar {\n original\n thumbLg\n }\n }\n referralVoucher {\n code\n amount\n expiresAt\n }\n message\n }\n }\n`\n\n/**\n * __useGetCustomerReferralQuery__\n *\n * To run a query within a React component, call `useGetCustomerReferralQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetCustomerReferralQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetCustomerReferralQuery({\n * variables: {\n * token: // value for 'token'\n * },\n * });\n */\nexport function useGetCustomerReferralQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_GetCustomerReferralQuery,\n GQL_GetCustomerReferralQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetCustomerReferralQuery,\n GQL_GetCustomerReferralQueryVariables\n >(GetCustomerReferralDocument, options)\n}\nexport function useGetCustomerReferralLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetCustomerReferralQuery,\n GQL_GetCustomerReferralQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetCustomerReferralQuery,\n GQL_GetCustomerReferralQueryVariables\n >(GetCustomerReferralDocument, options)\n}\nexport type GetCustomerReferralQueryHookResult = ReturnType<\n typeof useGetCustomerReferralQuery\n>\nexport type GetCustomerReferralLazyQueryHookResult = ReturnType<\n typeof useGetCustomerReferralLazyQuery\n>\nexport type GetCustomerReferralQueryResult = Apollo.QueryResult<\n GQL_GetCustomerReferralQuery,\n GQL_GetCustomerReferralQueryVariables\n>\nexport const ExploreDocument = gql`\n query Explore($market: Markets!, $cursor: String) {\n explore {\n regions(market: $market, first: 2, after: $cursor)\n @connection(key: \"regions\") {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n slug\n name\n stories {\n ...StoryCardFragment\n featuredListing {\n ...StoryFeaturedListingFragment\n }\n }\n }\n }\n }\n }\n }\n ${StoryCardFragmentFragmentDoc}\n ${StoryFeaturedListingFragmentFragmentDoc}\n`\n\n/**\n * __useExploreQuery__\n *\n * To run a query within a React component, call `useExploreQuery` and pass it any options that fit your needs.\n * When your component renders, `useExploreQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useExploreQuery({\n * variables: {\n * market: // value for 'market'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useExploreQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_ExploreQuery,\n GQL_ExploreQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n ExploreDocument,\n options\n )\n}\nexport function useExploreLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_ExploreQuery,\n GQL_ExploreQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery(\n ExploreDocument,\n options\n )\n}\nexport type ExploreQueryHookResult = ReturnType\nexport type ExploreLazyQueryHookResult = ReturnType\nexport type ExploreQueryResult = Apollo.QueryResult<\n GQL_ExploreQuery,\n GQL_ExploreQueryVariables\n>\nexport const RegionAdventuresDocument = gql`\n query RegionAdventures($regionId: ID!, $cursor: String) {\n region(id: $regionId) {\n adventures(first: 4, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n ...AdventureCardFragment\n }\n }\n }\n }\n }\n ${AdventureCardFragmentFragmentDoc}\n`\n\n/**\n * __useRegionAdventuresQuery__\n *\n * To run a query within a React component, call `useRegionAdventuresQuery` and pass it any options that fit your needs.\n * When your component renders, `useRegionAdventuresQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useRegionAdventuresQuery({\n * variables: {\n * regionId: // value for 'regionId'\n * cursor: // value for 'cursor'\n * },\n * });\n */\nexport function useRegionAdventuresQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_RegionAdventuresQuery,\n GQL_RegionAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_RegionAdventuresQuery,\n GQL_RegionAdventuresQueryVariables\n >(RegionAdventuresDocument, options)\n}\nexport function useRegionAdventuresLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_RegionAdventuresQuery,\n GQL_RegionAdventuresQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_RegionAdventuresQuery,\n GQL_RegionAdventuresQueryVariables\n >(RegionAdventuresDocument, options)\n}\nexport type RegionAdventuresQueryHookResult = ReturnType<\n typeof useRegionAdventuresQuery\n>\nexport type RegionAdventuresLazyQueryHookResult = ReturnType<\n typeof useRegionAdventuresLazyQuery\n>\nexport type RegionAdventuresQueryResult = Apollo.QueryResult<\n GQL_RegionAdventuresQuery,\n GQL_RegionAdventuresQueryVariables\n>\nexport const ExploreRegionDocument = gql`\n query exploreRegion($regionId: ID!) {\n explore {\n region(id: $regionId) {\n id\n slug\n name\n state {\n code\n }\n stories(max: 12) {\n ...StoryCardFragment\n featuredListing {\n ...StoryFeaturedListingFragment\n }\n }\n }\n }\n }\n ${StoryCardFragmentFragmentDoc}\n ${StoryFeaturedListingFragmentFragmentDoc}\n`\n\n/**\n * __useExploreRegionQuery__\n *\n * To run a query within a React component, call `useExploreRegionQuery` and pass it any options that fit your needs.\n * When your component renders, `useExploreRegionQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useExploreRegionQuery({\n * variables: {\n * regionId: // value for 'regionId'\n * },\n * });\n */\nexport function useExploreRegionQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_ExploreRegionQuery,\n GQL_ExploreRegionQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_ExploreRegionQuery,\n GQL_ExploreRegionQueryVariables\n >(ExploreRegionDocument, options)\n}\nexport function useExploreRegionLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_ExploreRegionQuery,\n GQL_ExploreRegionQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_ExploreRegionQuery,\n GQL_ExploreRegionQueryVariables\n >(ExploreRegionDocument, options)\n}\nexport type ExploreRegionQueryHookResult = ReturnType<\n typeof useExploreRegionQuery\n>\nexport type ExploreRegionLazyQueryHookResult = ReturnType<\n typeof useExploreRegionLazyQuery\n>\nexport type ExploreRegionQueryResult = Apollo.QueryResult<\n GQL_ExploreRegionQuery,\n GQL_ExploreRegionQueryVariables\n>\nexport const CreateCustomerReferralDocument = gql`\n mutation createCustomerReferral(\n $customerReferralInput: CustomerReferralInput!\n ) {\n createCustomerReferral(customerReferralInput: $customerReferralInput) {\n customerReferral {\n ...CustomerReferral\n }\n }\n }\n ${CustomerReferralFragmentDoc}\n`\nexport type GQL_CreateCustomerReferralMutationFn = Apollo.MutationFunction<\n GQL_CreateCustomerReferralMutation,\n GQL_CreateCustomerReferralMutationVariables\n>\n\n/**\n * __useCreateCustomerReferralMutation__\n *\n * To run a mutation, you first call `useCreateCustomerReferralMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateCustomerReferralMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createCustomerReferralMutation, { data, loading, error }] = useCreateCustomerReferralMutation({\n * variables: {\n * customerReferralInput: // value for 'customerReferralInput'\n * },\n * });\n */\nexport function useCreateCustomerReferralMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_CreateCustomerReferralMutation,\n GQL_CreateCustomerReferralMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_CreateCustomerReferralMutation,\n GQL_CreateCustomerReferralMutationVariables\n >(CreateCustomerReferralDocument, options)\n}\nexport type CreateCustomerReferralMutationHookResult = ReturnType<\n typeof useCreateCustomerReferralMutation\n>\nexport type CreateCustomerReferralMutationResult = Apollo.MutationResult<\n GQL_CreateCustomerReferralMutation\n>\nexport type CreateCustomerReferralMutationOptions = Apollo.BaseMutationOptions<\n GQL_CreateCustomerReferralMutation,\n GQL_CreateCustomerReferralMutationVariables\n>\nexport const GetMyCustomerReferralsDocument = gql`\n query getMyCustomerReferrals {\n currentUser {\n customerReferrals {\n ...CustomerReferral\n }\n }\n }\n ${CustomerReferralFragmentDoc}\n`\n\n/**\n * __useGetMyCustomerReferralsQuery__\n *\n * To run a query within a React component, call `useGetMyCustomerReferralsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyCustomerReferralsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyCustomerReferralsQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetMyCustomerReferralsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetMyCustomerReferralsQuery,\n GQL_GetMyCustomerReferralsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetMyCustomerReferralsQuery,\n GQL_GetMyCustomerReferralsQueryVariables\n >(GetMyCustomerReferralsDocument, options)\n}\nexport function useGetMyCustomerReferralsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetMyCustomerReferralsQuery,\n GQL_GetMyCustomerReferralsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetMyCustomerReferralsQuery,\n GQL_GetMyCustomerReferralsQueryVariables\n >(GetMyCustomerReferralsDocument, options)\n}\nexport type GetMyCustomerReferralsQueryHookResult = ReturnType<\n typeof useGetMyCustomerReferralsQuery\n>\nexport type GetMyCustomerReferralsLazyQueryHookResult = ReturnType<\n typeof useGetMyCustomerReferralsLazyQuery\n>\nexport type GetMyCustomerReferralsQueryResult = Apollo.QueryResult<\n GQL_GetMyCustomerReferralsQuery,\n GQL_GetMyCustomerReferralsQueryVariables\n>\nexport const GetUserMarketDocument = gql`\n query getUserMarket {\n currentUser {\n id\n market {\n id\n rewardVoucherAmount\n referralVoucherAmount\n }\n }\n }\n`\n\n/**\n * __useGetUserMarketQuery__\n *\n * To run a query within a React component, call `useGetUserMarketQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetUserMarketQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetUserMarketQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetUserMarketQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_GetUserMarketQuery,\n GQL_GetUserMarketQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_GetUserMarketQuery,\n GQL_GetUserMarketQueryVariables\n >(GetUserMarketDocument, options)\n}\nexport function useGetUserMarketLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_GetUserMarketQuery,\n GQL_GetUserMarketQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_GetUserMarketQuery,\n GQL_GetUserMarketQueryVariables\n >(GetUserMarketDocument, options)\n}\nexport type GetUserMarketQueryHookResult = ReturnType<\n typeof useGetUserMarketQuery\n>\nexport type GetUserMarketLazyQueryHookResult = ReturnType<\n typeof useGetUserMarketLazyQuery\n>\nexport type GetUserMarketQueryResult = Apollo.QueryResult<\n GQL_GetUserMarketQuery,\n GQL_GetUserMarketQueryVariables\n>\nexport const SendCustomerReferralDocument = gql`\n mutation sendCustomerReferral(\n $customerReferralId: ID!\n $recipientEmail: String!\n ) {\n sendCustomerReferral(\n customerReferralId: $customerReferralId\n recipientEmail: $recipientEmail\n ) {\n customerReferral {\n ...CustomerReferral\n recipientEmail\n }\n }\n }\n ${CustomerReferralFragmentDoc}\n`\nexport type GQL_SendCustomerReferralMutationFn = Apollo.MutationFunction<\n GQL_SendCustomerReferralMutation,\n GQL_SendCustomerReferralMutationVariables\n>\n\n/**\n * __useSendCustomerReferralMutation__\n *\n * To run a mutation, you first call `useSendCustomerReferralMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useSendCustomerReferralMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [sendCustomerReferralMutation, { data, loading, error }] = useSendCustomerReferralMutation({\n * variables: {\n * customerReferralId: // value for 'customerReferralId'\n * recipientEmail: // value for 'recipientEmail'\n * },\n * });\n */\nexport function useSendCustomerReferralMutation(\n baseOptions?: Apollo.MutationHookOptions<\n GQL_SendCustomerReferralMutation,\n GQL_SendCustomerReferralMutationVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useMutation<\n GQL_SendCustomerReferralMutation,\n GQL_SendCustomerReferralMutationVariables\n >(SendCustomerReferralDocument, options)\n}\nexport type SendCustomerReferralMutationHookResult = ReturnType<\n typeof useSendCustomerReferralMutation\n>\nexport type SendCustomerReferralMutationResult = Apollo.MutationResult<\n GQL_SendCustomerReferralMutation\n>\nexport type SendCustomerReferralMutationOptions = Apollo.BaseMutationOptions<\n GQL_SendCustomerReferralMutation,\n GQL_SendCustomerReferralMutationVariables\n>\nexport const MapMarkerCalloutDocument = gql`\n query mapMarkerCallout($params: SearchFilters, $type: Searchable!, $id: ID!) {\n search(params: $params) {\n result(type: $type, id: $id) {\n result {\n ... on Listing {\n listingType {\n slug\n }\n subcategory {\n slug\n }\n ...ListingCardFragment\n stories {\n ...StoryCardFragment\n }\n }\n ... on StoryAdventure {\n ...AdventureCardFragment\n }\n }\n pricing {\n total\n customerServiceFee\n lineItems {\n itemType\n quantity\n price\n amount\n }\n }\n discount {\n ... on PromotionalDiscount {\n id\n name\n percentage\n }\n }\n }\n }\n }\n ${ListingCardFragmentFragmentDoc}\n ${StoryCardFragmentFragmentDoc}\n ${AdventureCardFragmentFragmentDoc}\n`\n\n/**\n * __useMapMarkerCalloutQuery__\n *\n * To run a query within a React component, call `useMapMarkerCalloutQuery` and pass it any options that fit your needs.\n * When your component renders, `useMapMarkerCalloutQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useMapMarkerCalloutQuery({\n * variables: {\n * params: // value for 'params'\n * type: // value for 'type'\n * id: // value for 'id'\n * },\n * });\n */\nexport function useMapMarkerCalloutQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_MapMarkerCalloutQuery,\n GQL_MapMarkerCalloutQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery<\n GQL_MapMarkerCalloutQuery,\n GQL_MapMarkerCalloutQueryVariables\n >(MapMarkerCalloutDocument, options)\n}\nexport function useMapMarkerCalloutLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_MapMarkerCalloutQuery,\n GQL_MapMarkerCalloutQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_MapMarkerCalloutQuery,\n GQL_MapMarkerCalloutQueryVariables\n >(MapMarkerCalloutDocument, options)\n}\nexport type MapMarkerCalloutQueryHookResult = ReturnType<\n typeof useMapMarkerCalloutQuery\n>\nexport type MapMarkerCalloutLazyQueryHookResult = ReturnType<\n typeof useMapMarkerCalloutLazyQuery\n>\nexport type MapMarkerCalloutQueryResult = Apollo.QueryResult<\n GQL_MapMarkerCalloutQuery,\n GQL_MapMarkerCalloutQueryVariables\n>\nexport const MapResultsDocument = gql`\n query mapResults($params: SearchFilters) {\n search(params: $params) {\n mapResults {\n id\n type\n slug\n location: coordinates\n }\n }\n }\n`\n\n/**\n * __useMapResultsQuery__\n *\n * To run a query within a React component, call `useMapResultsQuery` and pass it any options that fit your needs.\n * When your component renders, `useMapResultsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useMapResultsQuery({\n * variables: {\n * params: // value for 'params'\n * },\n * });\n */\nexport function useMapResultsQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_MapResultsQuery,\n GQL_MapResultsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n MapResultsDocument,\n options\n )\n}\nexport function useMapResultsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_MapResultsQuery,\n GQL_MapResultsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery(\n MapResultsDocument,\n options\n )\n}\nexport type MapResultsQueryHookResult = ReturnType\nexport type MapResultsLazyQueryHookResult = ReturnType<\n typeof useMapResultsLazyQuery\n>\nexport type MapResultsQueryResult = Apollo.QueryResult<\n GQL_MapResultsQuery,\n GQL_MapResultsQueryVariables\n>\nexport const SearchDocument = gql`\n query search($pageSize: Int, $cursor: String, $params: SearchFilters) {\n search(params: $params) {\n defaults {\n percentageAvailable\n regions {\n id\n name\n slug\n }\n subcategories {\n id\n name\n slug\n }\n amenities {\n id\n name\n slug\n }\n adventureTypes {\n category\n createdAt\n id\n name\n updatedAt\n slug\n }\n }\n results: results(first: $pageSize, after: $cursor) {\n minPrice\n maxPrice\n totalCount\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n node {\n bucketListIds\n startDate\n endDate\n availableDates {\n startDate\n endDate\n total\n }\n pricing {\n total\n customerServiceFee\n taxAmount\n lineItems {\n itemType\n quantity\n price\n amount\n }\n }\n discount {\n ... on LongStayDiscount {\n id\n durationInNights\n percentage\n }\n ... on PromotionalDiscount {\n id\n name\n percentage\n }\n }\n result {\n ... on Listing {\n ...ListingCardFragment\n stories {\n ...StoryCardFragment\n }\n }\n ... on Story {\n ...StoryCardFragment\n featuredListing {\n ...StoryFeaturedListingFragment\n }\n }\n ... on StoryAdventure {\n ...AdventureCardFragment\n }\n ... on ListingAdventure {\n ...ListingAdventure\n }\n }\n }\n }\n }\n }\n }\n ${ListingCardFragmentFragmentDoc}\n ${StoryCardFragmentFragmentDoc}\n ${StoryFeaturedListingFragmentFragmentDoc}\n ${AdventureCardFragmentFragmentDoc}\n ${ListingAdventureFragmentDoc}\n`\n\n/**\n * __useSearchQuery__\n *\n * To run a query within a React component, call `useSearchQuery` and pass it any options that fit your needs.\n * When your component renders, `useSearchQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useSearchQuery({\n * variables: {\n * pageSize: // value for 'pageSize'\n * cursor: // value for 'cursor'\n * params: // value for 'params'\n * },\n * });\n */\nexport function useSearchQuery(\n baseOptions?: Apollo.QueryHookOptions<\n GQL_SearchQuery,\n GQL_SearchQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n SearchDocument,\n options\n )\n}\nexport function useSearchLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_SearchQuery,\n GQL_SearchQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery(\n SearchDocument,\n options\n )\n}\nexport type SearchQueryHookResult = ReturnType\nexport type SearchLazyQueryHookResult = ReturnType\nexport type SearchQueryResult = Apollo.QueryResult<\n GQL_SearchQuery,\n GQL_SearchQueryVariables\n>\nexport const SuggestionsDocument = gql`\n query Suggestions(\n $listingId: ID!\n $cursor: String\n $scope: MoreEscapesScope\n ) {\n moreEscapes(\n listingId: $listingId\n first: 3\n after: $cursor\n scope: $scope\n ) {\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n result {\n __typename\n ... on Listing {\n ...ListingCardFragment\n }\n ... on Story {\n ...StoryCardFragment\n featuredListing {\n ...StoryFeaturedListingFragment\n }\n }\n }\n }\n }\n }\n }\n ${ListingCardFragmentFragmentDoc}\n ${StoryCardFragmentFragmentDoc}\n ${StoryFeaturedListingFragmentFragmentDoc}\n`\n\n/**\n * __useSuggestionsQuery__\n *\n * To run a query within a React component, call `useSuggestionsQuery` and pass it any options that fit your needs.\n * When your component renders, `useSuggestionsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useSuggestionsQuery({\n * variables: {\n * listingId: // value for 'listingId'\n * cursor: // value for 'cursor'\n * scope: // value for 'scope'\n * },\n * });\n */\nexport function useSuggestionsQuery(\n baseOptions: Apollo.QueryHookOptions<\n GQL_SuggestionsQuery,\n GQL_SuggestionsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useQuery(\n SuggestionsDocument,\n options\n )\n}\nexport function useSuggestionsLazyQuery(\n baseOptions?: Apollo.LazyQueryHookOptions<\n GQL_SuggestionsQuery,\n GQL_SuggestionsQueryVariables\n >\n) {\n const options = { ...defaultOptions, ...baseOptions }\n return Apollo.useLazyQuery<\n GQL_SuggestionsQuery,\n GQL_SuggestionsQueryVariables\n >(SuggestionsDocument, options)\n}\nexport type SuggestionsQueryHookResult = ReturnType\nexport type SuggestionsLazyQueryHookResult = ReturnType<\n typeof useSuggestionsLazyQuery\n>\nexport type SuggestionsQueryResult = Apollo.QueryResult<\n GQL_SuggestionsQuery,\n GQL_SuggestionsQueryVariables\n>\n","import { useContext } from 'react'\n\nimport RailsEnvContext from '../contexts/RailsContext'\n\nconst useRailsEnv = () => useContext(RailsEnvContext)\n\nexport default useRailsEnv\n","import { useSelector, TypedUseSelectorHook } from 'react-redux'\n\nimport type { RootState } from '../typedRedux/configureStoreWithHistory'\n\nconst useReduxSelector: TypedUseSelectorHook = useSelector\n\nexport default useReduxSelector\n","import { useLocation } from 'react-router'\n\nimport useIsServerSide from './useIsServerSideContext'\n\nconst useSearchParams = () => {\n const isServerSide = useIsServerSide()\n const { search } = useLocation()\n\n if (isServerSide) {\n return undefined\n }\n\n return new URLSearchParams(search)\n}\n\nexport default useSearchParams\n","import { useEffect } from 'react'\n\nimport useIsServer from './useIsServer'\n\nconst hide = (selector: string) => {\n const el: HTMLElement = document.querySelector(selector)\n if (el) {\n el.style.display = 'none'\n }\n}\n\nconst show = (selector: string) => {\n const el: HTMLElement = document.querySelector(selector)\n if (el) {\n el.style.display = 'block'\n }\n}\n\ntype RestoreFooterOptions = {\n hideOnUnmount?: boolean\n}\n\nexport const useRestoreSiteFooter = (options?: RestoreFooterOptions) => {\n const isServer = useIsServer()\n\n useEffect(() => {\n if (!isServer) {\n show('#site-footer')\n }\n\n return () => {\n if (options?.hideOnUnmount) {\n hide('#site-footer')\n }\n }\n }, [isServer])\n}\n\ntype HideFooterOptions = {\n restoreOnUnmount?: boolean\n}\n\nexport const useHideSiteFooter = (options?: HideFooterOptions) => {\n const isServer = useIsServer()\n\n useEffect(() => {\n if (!isServer) {\n hide('#site-footer')\n }\n\n return () => {\n if (options?.restoreOnUnmount) {\n show('#site-footer')\n }\n }\n }, [isServer])\n}\n","import { useEffect, useState, useCallback } from 'react'\n\ntype SwiperCallback = () => any\n\ninterface Swiper {\n isBeginning: boolean\n isEnd: boolean\n on: (arg0: string, arg1: SwiperCallback) => any\n slidePrev: () => any\n slideNext: () => any\n}\n\ntype Output = [\n {\n handlePrev: () => any\n handleNext: () => any\n },\n {\n prevDisabled: boolean\n nextDisabled: boolean\n }\n]\n\nconst useSwiperPagination = (swiper: Swiper): Output => {\n const [paginationState, setPaginationState] = useState({\n prevDisabled: true,\n nextDisabled: false,\n })\n\n useEffect(() => {\n if (swiper) {\n // eslint-disable-next-line func-names\n ;['slideChange', 'observerUpdate'].forEach((event) =>\n swiper.on(event, () => {\n setPaginationState({\n prevDisabled: swiper.isBeginning,\n nextDisabled: swiper.isEnd,\n })\n })\n )\n }\n }, [swiper])\n\n const handlePrev = useCallback(() => {\n if (swiper) swiper.slidePrev()\n }, [swiper])\n\n const handleNext = useCallback(() => {\n if (swiper && !swiper.isEnd) swiper.slideNext()\n }, [swiper])\n\n return [{ handlePrev, handleNext }, paginationState]\n}\n\nexport default useSwiperPagination\n","export const heightSmall = 70\n\nexport const heightLarge = 100\n\n/* has to be higher than the elements rendered by rails views for the \"header\" layout */\nexport const zIndex = 10\n\nexport const searchResultsPanelZIndex = 3\n\nexport const searchInputZIndex = 3\n\nexport const mobileMenuZIndex = 4\n\nexport const navbarSizeBreakpoint = 'md' as const\n","import React from 'react'\n\nconst CreateAListing = () => (\n \n)\n\nexport default CreateAListing\n","import React from 'react'\n\nconst PublishAndPromote = () => (\n \n)\n\nexport default PublishAndPromote\n","import styled from 'styled-components'\n\nconst Title = styled.div`\n margin-bottom: 40px;\n h1 {\n font-size: 42px;\n }\n`\n\nexport default Title\n","import React, { useState } from 'react'\nimport styled from 'styled-components'\n\nimport TrackVisibility from '../../components/utils/TrackVisibility'\nimport MapWithListing, {\n ListingPopupData,\n} from '../../components/maps/ListingMap'\nimport { snakeCaseKeys } from '../../components/utils/propsUtils'\n\nconst MapWrapper = styled.div`\n width: 100%;\n height: 550px;\n`\n\nexport type AdventureMapProps = {\n adventureData: Omit\n photos?: Pick[]\n originalListing?: Pick & {\n subcategory?: Pick\n }\n}\n\nconst AdventureMap = ({\n adventureData,\n photos,\n originalListing,\n}: AdventureMapProps) => {\n const [showMap, setShowMap] = useState(false)\n\n const listingForMap = originalListing && {\n id: originalListing?.id,\n type: 'Listing' as GQL_Searchable,\n slug: originalListing?.subcategory?.slug,\n location: originalListing?.coordinates,\n listing: snakeCaseKeys(originalListing) as ListingPopupData,\n }\n\n const adventureForMap = {\n id: adventureData?.id,\n type: 'Adventure' as GQL_Searchable,\n slug: adventureData?.adventureType?.slug,\n location: [adventureData?.location?.lat, adventureData?.location?.lng],\n adventure: {\n ...adventureData,\n photos,\n },\n }\n\n return (\n {\n if (isVisible) setShowMap(true)\n }}\n >\n \n \n \n \n )\n}\n\nexport default AdventureMap\n","import React, { useState } from 'react'\nimport styled from 'styled-components'\nimport get from 'lodash/get'\n\nimport { useGetAdventureReviewsQuery } from 'hooks/useQueries'\nimport ReviewsModal from 'components/reviews/ReviewsModal'\nimport ReviewList from 'components/reviews/ReviewList'\nimport ReviewScore from 'components/reviews/ReviewScore'\nimport Button from 'components/display/Button'\nimport { SectionTitle } from '../../listing/Sections/shared'\nimport { Section } from '../shared'\n\nconst Spacer = styled.div`\n margin-bottom: 40px;\n`\n\ninterface ReviewsProps {\n adventureId: string\n score?: string\n}\n\nconst Reviews = ({ score, adventureId }: ReviewsProps) => {\n const [reviewsModalOpen, setReviewsModalOpen] = useState(false)\n const { data, loading } = useGetAdventureReviewsQuery({\n fetchPolicy: 'no-cache',\n variables: {\n id: adventureId,\n },\n })\n\n const reviewsConnection = get(data, 'adventure.reviews')\n const hasNextPage = get(data, 'adventure.reviews.pageInfo.hasNextPage')\n\n if (reviewsConnection && reviewsConnection.edges.length === 0) {\n return null\n }\n\n return (\n \n Reviews\n \n \n\n \n\n {hasNextPage && (\n \n )}\n\n {\n setReviewsModalOpen(false)\n }}\n />\n \n )\n}\n\nexport default Reviews\n","import React, { FunctionComponent, useState } from 'react'\nimport styled from 'styled-components'\n\nimport useIsServer from '../../hooks/useIsServer'\nimport { useGetAdventurePhotosQuery } from '../../hooks/useQueries'\n\nimport ActivityMatchedIcon from '../../components/display/ActivityMatchedIcon'\nimport Avatar from '../../components/display/Avatar'\nimport GalleryHeader from '../../components/display/GalleryHeader'\nimport LazyImage from '../../components/display/LazyImage'\nimport MobileGallery from '../../components/display/MobileGallery'\nimport Title from '../../components/display/Title'\nimport ReviewScore from '../../components/reviews/ReviewScore'\n\nimport DesktopListingHeader from '../listing/Header/DesktopListingHeader'\nimport {\n ListingTitle as AdventureTitle,\n ListingWrapper as AdventureWrapper,\n} from '../listing/Sections/shared'\n\nimport ShowMoreText from '../../components/ShowMoreText'\nimport { media } from '../../styles/media'\n\nimport AdventureMap, { AdventureMapProps } from './AdventureMap'\nimport Reviews from './Reviews'\nimport { NarrowerContainer, Section } from './shared'\n\nconst MobileHeaderWrapper = styled.div`\n ${media.md`\n display: none;\n `}\n`\n\nconst Spacer = styled.div`\n margin-bottom: 40px;\n`\n\nconst SummaryInfo = styled.div`\n color: ${({ theme }) => theme.brand.jungle};\n display: flex;\n justify-content: start;\n flex-wrap: wrap;\n align-items: center;\n font-size: 1.6rem;\n\n i {\n font-size: 30px;\n }\n\n & > * {\n margin-bottom: 10px;\n }\n`\n\nconst ActionsWrapper = styled.div`\n display: flex;\n\n & > * {\n margin-right: 12px;\n }\n`\n\nconst AuthorInfoWrapper = styled.div`\n margin-top: 50px;\n margin-bottom: 0;\n`\n\nconst AuthorInfo = styled.div`\n display: flex;\n justify-content: flex-start;\n align-items: center;\n\n ${Avatar} {\n display: block;\n min-width: 100px;\n min-height: 100px;\n margin-right: 24px;\n }\n`\n\nconst DiscoveredBy = styled.div`\n display: flex;\n flex-direction: column;\n justify-content: middle;\n color: #999;\n\n a {\n color: ${({ theme }) => theme.brand.jungle};\n }\n`\n\ninterface AdventureProps {\n adventure: AdventureMapProps['adventureData']\n originalListing?: AdventureMapProps['originalListing']\n actionNodes?: React.ReactNode\n children?: React.ReactNode\n}\n\nconst CommonAdventureDetails: FunctionComponent = ({\n adventure,\n originalListing,\n actionNodes,\n children,\n}) => {\n const serverSide = useIsServer()\n const [mobileGalleryOpen, setMobileGalleryOpen] = useState(false)\n\n const {\n id,\n adventureType,\n description,\n location,\n reviewScore,\n storyteller,\n storyUrl,\n story,\n title,\n } = adventure\n\n const { data: photoQueryData } = useGetAdventurePhotosQuery({\n variables: { id: id.toString() },\n })\n\n const photos = photoQueryData?.adventure?.photos\n const backgroundImage = photos && photos[0].image\n\n return (\n \n \n \n setMobileGalleryOpen(true)}\n />\n setMobileGalleryOpen(false)}\n />\n \n \n \n \n \n \n \n \n \n Discovered by {storyteller.firstName}\n {story.active && {story.title}}\n \n \n \n \n
\n {title}\n \n \n \n {adventureType.name} in {location.name}\n \n \n \n \n
\n {description}\n \n
\n
{actionNodes}\n
\n \n\n {!serverSide && (\n <>\n \n \n \n \n {children}\n >\n )}\n \n )\n}\n\nexport default CommonAdventureDetails\n","import React from 'react'\nimport styled from 'styled-components'\nimport { useLocation } from 'react-router'\n\nimport AdventureCard from '../../../components/cards/AdventureCard'\nimport AdventurePlaceholderCard from '../../../components/cards/AdventureCard/Placeholder'\nimport AddRemoveButton from '../../../dashboard/MyBookings/ItineraryBuilder/AddRemoveButton'\n\nconst AddRemoveButtonWrapper = styled.div`\n font-size: ${({ theme }) => theme['-ds-font-size-xs']['font-size'].value};\n`\n\ntype SuggestedAdventureCardProps = React.ComponentProps<\n typeof AdventureCard\n> & {\n id: string\n inItineraryContext?: boolean\n hideStoryteller?: boolean\n noLink?: boolean\n}\n\nexport const LoadingCard = () => \n\nconst SuggestedAdventureCard = ({\n id,\n title,\n photos,\n storyteller,\n location,\n inItineraryContext,\n reviewScore,\n showReviewScore,\n onSelectEscapeClick,\n isInEscape,\n url: directUrl,\n hideStoryteller,\n noLink,\n}: SuggestedAdventureCardProps) => {\n const { pathname } = useLocation()\n let url = inItineraryContext ? `${pathname}/${id}` : directUrl\n\n if (noLink) {\n url = undefined\n }\n\n return (\n <>\n \n \n \n )\n }\n />\n >\n )\n}\n\nexport default SuggestedAdventureCard\n","import React from 'react'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport styled from 'styled-components'\n\nimport useIsServerSideContext from '../../../hooks/useIsServerSideContext'\n\nimport TrackVisibility from '../../../components/utils/TrackVisibility'\nimport WithSelectEscape from '../../../components/SelectEscape/WithSelectEscape'\n\nimport SuggestedAdventureCard, { LoadingCard } from './SuggestedAdventureCard'\n\nconst Wrapper = styled.div`\n margin: 0 -14px;\n`\n\nconst Slide = styled.div`\n padding: 0 14px;\n max-width: 324px;\n box-sizing: border-box;\n`\n\nconst defaultParams = {\n slidesPerView: 2,\n slidesPerGroup: 2,\n shouldSwiperUpdate: true,\n speed: 600,\n breakpoints: {\n 768: {\n slidesPerView: 3,\n slidesPerGroup: 3,\n },\n 992: {\n slidesPerView: 4,\n slidesPerGroup: 4,\n },\n },\n}\n\ninterface AdventureCardSliderProps {\n getSwiper: React.ComponentProps['onSwiper']\n loading?: boolean\n canFetchMore?: boolean\n onFetchMore?: (...args: any) => any\n bookingAdventuresIndex: GQL_BookingAdventuresIndex\n bucketListItemsIndex: GQL_BucketListItemsIndex\n adventures: GQL_AdventureCardFragmentFragment[]\n inItineraryContext?: boolean\n maxSlides?: number\n showReviewScore?: boolean\n}\n\nconst AdventureCardSlider = ({\n getSwiper,\n loading,\n canFetchMore,\n onFetchMore,\n bookingAdventuresIndex,\n bucketListItemsIndex,\n adventures,\n inItineraryContext,\n showReviewScore,\n maxSlides,\n}: AdventureCardSliderProps) => {\n const isServer = useIsServerSideContext()\n const swiperParams = {\n ...defaultParams,\n }\n if (maxSlides) {\n swiperParams.breakpoints[992] = {\n slidesPerView: maxSlides,\n slidesPerGroup: maxSlides,\n }\n }\n\n const adventureSlides =\n adventures?.map((adventure) => (\n \n \n \n \n \n )) || []\n\n const loadingSlides = loading\n ? [...Array(4)].map((_, i) => (\n // eslint-disable-next-line react/jsx-indent,react/no-array-index-key\n \n \n \n ))\n : []\n\n const fetchMoreTriggerSlides =\n !loading && canFetchMore\n ? [\n {\n if (isVisible) {\n onFetchMore()\n }\n }}\n >\n \n ,\n ]\n : []\n\n const ssrSlide = (\n \n \n \n )\n\n const slides = isServer\n ? [ssrSlide]\n : [...adventureSlides, ...fetchMoreTriggerSlides, ...loadingSlides]\n\n return (\n \n \n {slides.map((slide) => (\n {slide}\n ))}\n \n \n )\n}\n\nexport default AdventureCardSlider\n","import React, { useEffect } from 'react'\nimport styled from 'styled-components'\nimport { useTrackVisibility } from 'react-intersection-observer-hook'\n\nimport AdventurePlaceholderCard from '../../../components/cards/AdventureCard/Placeholder'\nimport WithSelectEscape from '../../../components/SelectEscape/WithSelectEscape'\nimport { Content } from '../../../components/cards/shared/styled'\n\nimport SuggestedAdventureCard from './SuggestedAdventureCard'\n\nconst Wrapper = styled.div`\n margin: 0 -16px;\n`\n\nconst PlaceholderCardWrapper = styled.div`\n position: relative;\n top: 16px;\n`\n\nexport const HorizontalListWrapper = styled.div`\n transform: translate3d(0, 0, 0);\n margin: 0 -8px;\n overflow: hidden;\n`\n\nexport const HorizontalListTrack = styled.div`\n height: 100%;\n width: 100%;\n overflow-y: hidden;\n`\n\nexport const HorizontalListItem = styled.div`\n display: inline-block;\n width: 264px;\n margin: 0 8px;\n\n &:first-child {\n margin-left: 24px;\n }\n\n ${Content} {\n padding-left: 0 !important;\n padding-right: 0 !important;\n }\n`\n\nexport const HorizontalList = styled.div`\n height: 100%;\n overflow-y: auto;\n white-space: nowrap;\n overflow-x: scroll;\n -webkit-overflow-scrolling: touch;\n\n padding-bottom: 30px;\n padding-right: 15px;\n margin-bottom: -30px;\n\n &::-webkit-scrollbar {\n display: none;\n }\n`\n\ninterface AdventureCardListProps {\n adventures: GQL_AdventureCardFragmentFragment[]\n loading?: boolean\n canFetchMore?: boolean\n onFetchMore: (...args: any) => any\n bookingAdventuresIndex: GQL_BookingAdventuresIndex\n bucketListItemsIndex: GQL_BucketListItemsIndex\n inItineraryContext?: boolean\n showReviewScore?: boolean\n}\n\nconst AdventureCardList = ({\n adventures,\n loading,\n canFetchMore,\n onFetchMore,\n bookingAdventuresIndex,\n bucketListItemsIndex,\n inItineraryContext,\n showReviewScore,\n}: AdventureCardListProps) => {\n const [loaderRef, { isVisible }] = useTrackVisibility()\n\n useEffect(() => {\n if (isVisible && canFetchMore && !loading) {\n onFetchMore()\n }\n }, [isVisible, canFetchMore, loading])\n\n return (\n \n \n \n \n {adventures?.map((adventure) => (\n \n \n \n \n \n ))}\n\n \n {canFetchMore && (\n \n \n \n )}\n \n \n \n \n \n )\n}\n\nexport default AdventureCardList\n","import React, { useState, useContext } from 'react'\nimport styled from 'styled-components'\nimport Media from 'react-media'\n\nimport { breakpoints, media, mediaMax } from 'styles/media'\n\nimport TouchDeviceContext from 'contexts/TouchDeviceContext'\n\nimport useSwiperPagination from '../../../hooks/useSwiperPagination'\nimport { useGetSelectEscapeIndexesQuery } from '../../../hooks/useQueries'\n\nimport ChevronDownIcon from '../../../components/icons/ChevronDown'\n\nimport AdventureCardSlider from './AdventureCardSlider'\nimport AdventureCardList from './AdventureCardList'\n\nconst BREAKPOINT = 'lg' as const\n\nconst MobileOnly = styled.div`\n ${media[BREAKPOINT]`\n display: none;\n `}\n`\n\nconst DesktopOnly = styled.div`\n ${mediaMax[BREAKPOINT]`\n display: none;\n `}\n`\n\nconst Arrow = styled.button.attrs({ type: 'button' })<{\n left?: boolean\n right?: boolean\n disabled?: boolean\n}>`\n height: 40px;\n width: 40px;\n padding: 0;\n\n ${({ left }) =>\n left &&\n `\n left: 8px;\n\n svg {\n margin-left: -2px;\n }\n `}\n\n ${({ right }) =>\n right &&\n `\n right: 8px;\n svg {\n margin-right: -2px;\n }\n `}\n\n appearance: none;\n outline: 0;\n border: none;\n color: ${({ theme }) => theme.brand.forest};\n background-color: white;\n\n svg {\n display: inline-block;\n vertical-align: middle;\n height: 13px;\n margin-top: -2px;\n transform: rotate(${({ left }) => (left ? '90deg' : '-90deg')});\n }\n\n ${({ disabled }) =>\n disabled &&\n `\n color: #999;\n `}\n`\n\nconst Inner = styled.div``\n\nconst Intro = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n`\n\nconst Title = styled.h1`\n margin: 0;\n font-size: 20px;\n line-height: 1.1;\n\n color: ${({ theme }) => theme.brand.forest};\n`\n\nconst Empty = styled.div`\n color: ${({ theme }) => theme['-ds-core-300'].value};\n font-size: ${({ theme }) => theme['-ds-font-size-md']['font-size'].value};\n`\n\ntype AdventureEdge = {\n node?: GQL_AdventureCardFragmentFragment\n}\n\ntype SuggestedAdventuresProps = {\n adventures: { edges?: AdventureEdge[] }\n inItineraryContext?: boolean\n canFetchMore?: boolean\n customTitle?: React.ReactNode\n handleFetchMore: (...args: any) => any\n loading?: boolean\n isEmpty?: boolean\n maxSlidesDesktop?: number\n showReviewScore?: boolean\n}\n\nconst SuggestedAdventures = ({\n adventures,\n inItineraryContext,\n canFetchMore,\n customTitle,\n handleFetchMore,\n loading,\n isEmpty,\n maxSlidesDesktop,\n showReviewScore,\n}: SuggestedAdventuresProps) => {\n const [swiper, getSwiper] = useState(null)\n const [{ handlePrev, handleNext }] = useSwiperPagination(swiper)\n const isTouchDevice = useContext(TouchDeviceContext)\n\n const { data: selectEscapeIndexesData } = useGetSelectEscapeIndexesQuery()\n const bucketListItemsIndex = selectEscapeIndexesData?.currentUser\n ?.bucketListItemsIndex as GQL_BucketListItemsIndex\n const bookingAdventuresIndex = selectEscapeIndexesData?.currentUser\n ?.bookingAdventuresIndex as GQL_BookingAdventuresIndex\n\n const adventureNodes = adventures?.edges?.map(({ node }) => node)\n\n return (\n \n {(isDesktop) => (\n \n \n {customTitle || Suggested Things to Do}\n\n {(!isTouchDevice || isDesktop) && !isEmpty && (\n \n )}\n \n\n {isEmpty && Coming Soon!}\n\n {!isEmpty && (\n <>\n \n \n \n\n \n \n \n >\n )}\n \n )}\n \n )\n}\n\nexport default SuggestedAdventures\n","import styled from 'styled-components'\n\nimport Container from '../../components/layout/Container'\nimport { Section as BaseSection } from '../listing/Sections/shared'\n\nexport const Section = styled(BaseSection)`\n padding: 60px 0;\n`\n\nexport const NarrowerContainer = styled(Container)`\n max-width: 900px;\n overflow: hidden;\n`\n","import React, { FunctionComponent } from 'react'\nimport styled from 'styled-components'\nimport { connect } from 'react-redux'\nimport pick from 'lodash/pick'\nimport { RouterState } from 'connected-react-router'\n\nimport { updateFilters } from '../../actions/myBucketlistActions'\nimport { deserializeSearchQuery } from '../../actions/utils/search'\n\nimport DatesFilter from '../../search/filters/desktop/DatesFilter'\nimport CapacityFilter from '../../search/filters/desktop/CapacityFilter'\nimport { normalizeKeys } from '../../components/utils/propsUtils'\n\nconst Wrapper = styled.div`\n display: flex;\n margin: 0 -16px;\n`\n\nconst Filter = styled.div`\n padding-left: 16px;\n\n &:last-child {\n padding-right: 0;\n }\n`\n\ninterface BucketListFiltersProps {\n filters: Maybe\n dispatch: (...args: any) => any\n}\n\nconst DesktopBucketListFilters: FunctionComponent = ({\n filters,\n dispatch,\n}) => {\n const onFiltersChange = (newFilters: GQL_SearchFilters) => {\n dispatch(updateFilters(newFilters))\n }\n\n return (\n \n \n \n \n\n \n \n \n \n )\n}\n\ninterface ReduxState {\n router: RouterState\n}\n\nexport default connect(({ router }: ReduxState) => ({\n filters: normalizeKeys(deserializeSearchQuery(router.location.search)),\n}))(DesktopBucketListFilters)\n","import React from 'react'\n\nimport ComponentError from '../../components/display/ComponentError'\nimport {\n Outerwrapper,\n StickyBar,\n ResultsArea,\n MapContainer,\n} from '../../components/layout/ItemGridWithMap/Desktop'\n\ntype DesktopViewProps = {\n filterBarComponent: React.ReactNode\n resultsComponent: React.ReactNode\n mapComponent: React.ReactNode\n}\n\nconst DesktopView = ({\n filterBarComponent,\n resultsComponent,\n mapComponent,\n}: DesktopViewProps) => {\n return (\n \n \n {filterBarComponent}\n \n {mapComponent}\n \n \n \n {resultsComponent}\n \n \n )\n}\n\nexport default DesktopView\n","import React, {\n FunctionComponent,\n FormEvent,\n SyntheticEvent,\n useEffect,\n useState,\n} from 'react'\nimport styled, { css } from 'styled-components'\n\nimport { useMediaQueryContext } from 'contexts/MediaQueryContext'\n\nimport { useBucketListThemesLazyQuery } from '../../hooks/useQueries'\nimport { breakpoints, media } from '../../styles/media'\n\nimport Button from '../../components/display/Button'\nimport CloseButton from '../../components/display/CloseButton'\nimport InvisibleButton from '../../components/display/InvisibleButton'\nimport DialogModal from '../../components/display/DialogModal'\nimport LazyImage from '../../components/display/LazyImage'\nimport Modal from '../../components/display/Modal'\nimport Container from '../../components/layout/Container'\nimport CheckIcon from '../../components/icons/Check'\nimport CrossIcon from '../../components/icons/CrossOut'\nimport { PlaceholderCardWrapper } from '../../components/cards/PlaceholderCard'\nimport { Label, TextField } from '../../components/form'\n\nimport { StickyButtonWrapper } from './shared'\n\nconst Outer = styled(Container)`\n max-width: ${breakpoints.md}px;\n padding: 0;\n`\n\nconst Content = styled.div`\n position: relative;\n background-color: white;\n min-height: 100vh;\n padding-top: 60px;\n`\n\nconst Heading = styled.h1`\n margin: 0 0 20px 16px;\n font-size: 20px;\n color: #000000;\n text-transform: uppercase;\n`\n\nconst ThemesWrapper = styled.div`\n display: flex;\n flex-wrap: wrap;\n margin-bottom: 160px;\n`\n\nexport const selectMarkStyling = css`\n transition: color 150ms ease-out;\n border-radius: 50%;\n`\n\nexport const SelectedMark = styled.div<{ hollow?: boolean }>`\n display: flex;\n justify-content: center;\n align-items: center;\n position: absolute;\n top: 8px;\n right: 8px;\n\n width: 22px;\n height: 22px;\n\n ${selectMarkStyling}\n border: 1px solid ${({ theme }) => theme.brand.jungle};\n\n svg {\n width: 10px;\n height: 10px;\n color: ${({ theme }) => theme.brand.jungle};\n }\n background-color: ${({ theme, hollow }) =>\n hollow ? theme.brand.sand : theme.brand.afterglow};\n`\n\nconst ImagePlaceholder = styled(PlaceholderCardWrapper)`\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n`\n\nconst ThemeOption = styled(InvisibleButton)`\n position: relative;\n min-height: 100px;\n width: calc(50% - 8px);\n background-color: lightgrey;\n margin-bottom: 16px;\n\n border-radius: 6px;\n overflow: hidden;\n\n &:nth-child(odd) {\n margin-right: 16px;\n }\n\n ${media.md`\n min-height: 240px;\n `}\n`\n\nconst BucketlistForm = styled.form`\n display: flex;\n flex-direction: column;\n\n padding: 0 16px;\n border-top: solid 1px #d3d3d3;\n\n input,\n textarea {\n margin: 0;\n }\n\n ${Label} {\n margin: 30px 0 15px 0;\n }\n`\n\nconst ConfirmDeleteDialog = styled.div`\n width: 100%;\n height: 200px;\n display: flex;\n justify-content: center;\n align-items: center;\n\n ${Button} {\n width: 100px;\n margin: 0 16px;\n }\n`\n\ninterface EditBucketlistModalProps {\n bucketlist?: {\n id: string\n name?: string\n theme?: {\n id: string\n name: string\n }\n }\n isOpen: boolean\n onSaveBucketlist: (arg0: {\n id?: string\n name: string\n themeId: string\n }) => any\n onDeleteBucketlist?: (id: string) => any\n onRequestClose: (...args: any) => any\n noCloseOnSubmit?: boolean\n}\n\nconst EditBucketlistModal: FunctionComponent = ({\n bucketlist,\n isOpen,\n onSaveBucketlist,\n onDeleteBucketlist,\n onRequestClose,\n noCloseOnSubmit,\n}) => {\n const [name, setName] = useState(bucketlist?.name || '')\n const [themeId, setThemeId] = useState(bucketlist?.theme?.id || null)\n const [confirmDeleteModalOpen, setConfirmDeleteModalOpen] = useState(false)\n\n const { md: isMd } = useMediaQueryContext()\n\n const [\n loadBucketListThemes,\n { data, loading },\n ] = useBucketListThemesLazyQuery()\n useEffect(() => {\n if (isOpen) {\n loadBucketListThemes()\n }\n }, [isOpen])\n\n const bucketlistThemes = !loading && data?.defaults?.bucketListThemes\n\n const handleNameChange = (e: { target: { value: string } }) =>\n setName(e.target.value)\n const handleSubmit = (e: FormEvent) => {\n e.preventDefault()\n onSaveBucketlist({ id: bucketlist && bucketlist.id, name, themeId })\n if (!bucketlist || !bucketlist.id) {\n setName('')\n setThemeId(null)\n }\n\n if (!noCloseOnSubmit) {\n onRequestClose()\n }\n }\n const handleDelete = (e: SyntheticEvent) => {\n e.preventDefault()\n onDeleteBucketlist(bucketlist.id)\n setConfirmDeleteModalOpen(false)\n onRequestClose()\n }\n\n const headingText = bucketlist ? 'Edit Bucket List' : 'Create a Bucket List'\n const submitButtonText = bucketlist ? 'Save' : 'Create'\n const disableSubmit = name.length === 0 || !themeId\n\n return (\n \n \n \n \n \n \n {headingText}\n \n \n \n \n \n {!loading &&\n bucketlistThemes?.map(({ id, name: themeName, image }) => (\n setThemeId(id)}\n >\n <>\n {themeId === id && (\n \n \n \n )}\n \n \n >\n \n ))}\n \n \n \n \n \n {bucketlist && onDeleteBucketlist && (\n \n )}\n \n {bucketlist && (\n setConfirmDeleteModalOpen(false)}\n title={`Delete ${bucketlist.name}`}\n >\n \n \n \n \n \n )}\n \n \n )\n}\n\nexport default EditBucketlistModal\n","import React from 'react'\n\nimport Button from '../../components/display/Button'\n\ntype EmptyBodyProps = {\n publicBucketlist?: boolean\n}\n\nexport const EmptyBody = ({ publicBucketlist }: EmptyBodyProps) => {\n const heading = publicBucketlist\n ? 'This bucket list is empty'\n : 'Your bucket list is empty'\n\n return (\n \n
\n
{heading}
\n {!publicBucketlist && (\n <>\n
\n Let’s find some amazing places to fill your Bucket List.\n
\n
\n >\n )}\n
\n )\n}\n\ntype EmptyResultsProps = {\n onResetFilters?: (...args: any) => any\n type?: GQL_ListingTypes\n customHeading?: string | React.ReactNode\n customMessage?: string | React.ReactNode\n}\n\nexport const EmptyResults = ({\n onResetFilters,\n type,\n customMessage,\n customHeading,\n}: EmptyResultsProps) => {\n let targetDescriptionText\n switch (type) {\n case 'accommodation':\n targetDescriptionText = 'places to stay'\n break\n case 'adventures':\n targetDescriptionText = 'things to do'\n break\n default:\n targetDescriptionText = 'things'\n break\n }\n\n const heading =\n customHeading ??\n `None of the ${targetDescriptionText} in the bucket list match these filters`\n\n return (\n \n
\n
\n {heading}\n
\n {customMessage && (\n
\n {customMessage}\n
\n )}\n {onResetFilters && (\n <>\n
\n Try changing or clearing the filters\n
\n
\n \n
\n >\n )}\n
\n )\n}\n","import React, { FunctionComponent } from 'react'\n\nimport { useMediaQueryContext } from 'contexts/MediaQueryContext'\n\nimport { GetMyBucketListItemsQueryResult } from '../../hooks/useQueries'\n\nimport AdventureCard from '../../components/cards/AdventureCard'\nimport ListingCard from '../../components/cards/ListingCard'\nimport StoryCard from '../../components/cards/StoryCard'\nimport WithSelectEscape from '../../components/SelectEscape/WithSelectEscape'\nimport { normalizeKeys } from '../../components/utils/propsUtils'\nimport { mapGQLTypenameToGQLSearchable } from '../../dashboard/MyBucketlists/gql/getBucketListItemsIndexHelpers'\n\nexport type BucketListItemDatum = GetMyBucketListItemsQueryResult['data']['currentUser']['bucketList']['items']['edges'][0]['node']['item']\ntype BucketListItemPricing = GetMyBucketListItemsQueryResult['data']['currentUser']['bucketList']['items']['edges'][0]['node']['pricing']\n\nconst formatItemUrl = (url: string, searchQuery: string) => {\n if (searchQuery && searchQuery.length > 0) {\n return `${url}${searchQuery}`\n }\n\n return url\n}\n\ninterface BucketListItemProps {\n item: BucketListItemDatum\n pricing: BucketListItemPricing\n bookingAdventuresIndex: GQL_BookingAdventuresIndex\n bucketListItemsIndex: GQL_BucketListItemsIndex\n searchQuery?: string\n}\n\nconst BucketListItem: FunctionComponent = ({\n item,\n pricing,\n bookingAdventuresIndex,\n bucketListItemsIndex,\n searchQuery,\n}) => {\n const { md: largerThanMd } = useMediaQueryContext()\n const isMobile = !largerThanMd\n\n const itemType = mapGQLTypenameToGQLSearchable(item.__typename)\n\n switch (item.__typename) {\n case 'Listing':\n return (\n <>\n \n \n \n >\n )\n case 'Story':\n return (\n <>\n \n \n \n >\n )\n case 'StoryAdventure':\n return (\n <>\n \n \n \n >\n )\n default:\n return null\n }\n}\n\nexport default BucketListItem\n","import React from 'react'\n\nimport {\n useGetSelectEscapeIndexesQuery,\n GetBucketListItemsQueryResult,\n} from '../../hooks/useQueries'\n\nimport Button from '../../components/display/Button'\nimport { Grid, GridItem } from '../../components/layout/ItemGrid'\n\nimport BucketListItem from './BucketListItem'\nimport { EmptyResults, EmptyBody } from './Empty'\nimport { SeeMoreButtonWrapper, Subheading, Loader } from './shared'\n\ntype BucketListItemNode = GetBucketListItemsQueryResult['data']['bucketList']['items']['edges'][0]['node']\n\ntype BucketListItemsProps = {\n publicBucketlist?: boolean\n accommodationNodes: BucketListItemNode[]\n adventuresNodes: BucketListItemNode[]\n accommodationLoading: boolean\n adventuresLoading: boolean\n accommodationHasNextPage: boolean\n adventuresHasNextPage: boolean\n handleSeeMoreAccommodation: () => any\n handleSeeMoreAdventures: () => any\n bucketListLoading: boolean\n bucketListEmpty: boolean\n noMatchingAccommodationOnly?: boolean\n noMatchingItemsOfAnyKind?: boolean\n handleResetFilters: () => any\n}\n\nconst Items = ({\n publicBucketlist,\n accommodationLoading,\n accommodationNodes,\n accommodationHasNextPage,\n handleSeeMoreAccommodation,\n adventuresLoading,\n adventuresNodes,\n adventuresHasNextPage,\n handleSeeMoreAdventures,\n bucketListLoading,\n bucketListEmpty,\n noMatchingAccommodationOnly,\n noMatchingItemsOfAnyKind,\n handleResetFilters,\n}: BucketListItemsProps) => {\n const { data: selectEscapeIndexesData } = useGetSelectEscapeIndexesQuery()\n const bucketListItemsIndex = selectEscapeIndexesData?.currentUser\n ?.bucketListItemsIndex as GQL_BucketListItemsIndex\n const bookingAdventuresIndex = selectEscapeIndexesData?.currentUser\n ?.bookingAdventuresIndex as GQL_BookingAdventuresIndex\n\n return (\n \n \n {!accommodationLoading && accommodationNodes?.length > 0 && (\n <>\n Places to stay\n {accommodationNodes.map(({ item, pricing }) => {\n return (\n \n \n \n )\n })}\n\n {noMatchingAccommodationOnly && (\n \n )}\n\n {accommodationHasNextPage && (\n \n \n \n )}\n >\n )}\n\n {!accommodationLoading && // do not show while accom is loading, or this loads a split second earlier and jumps\n !adventuresLoading &&\n adventuresNodes?.length > 0 && (\n <>\n Things to do\n {adventuresNodes.map(({ item, pricing }) => {\n return (\n \n \n \n )\n })}\n\n {adventuresHasNextPage && (\n \n \n \n )}\n >\n )}\n\n {noMatchingItemsOfAnyKind && (\n \n )}\n\n {bucketListEmpty && }\n\n {(bucketListLoading || accommodationLoading || adventuresLoading) && (\n \n )}\n \n
\n )\n}\n\nexport default Items\n","import React from 'react'\n\nimport useIsServer from '../../hooks/useIsServer'\n\nimport Map from '../../components/maps/Map'\nimport MarkerCallout from '../../search/Map/MarkerCallout'\n\ntype BucketListMapResult = Omit<\n GQL_MapResult,\n 'markerCount' | 'coordinates'\n> & {\n location: number[]\n}\n\ntype BaseBucketListMapProps = {\n results: BucketListMapResult[]\n loading: boolean\n filters: GQL_SearchFilters\n searchQuery: string\n mobile?: boolean\n}\n\nconst BucketListMap = ({\n results,\n loading,\n filters,\n searchQuery,\n mobile,\n}: BaseBucketListMapProps) => {\n const isServer = useIsServer()\n\n if (isServer) {\n return null\n }\n\n return (\n \n )\n}\n\nexport default BucketListMap\n","import React from 'react'\n\nimport MapModal from '../../components/maps/MapModal'\nimport {\n MobileSearchViewWrapper,\n ResultsWrapper,\n} from '../../components/layout/ItemGridWithMap/Mobile'\nimport {\n Outerwrapper,\n StickyBar,\n} from '../../components/layout/ItemGridWithMap/Desktop'\n\ntype MobileViewProps = {\n filterBarComponent: React.ReactNode\n resultsComponent: React.ReactNode\n mapComponent: React.ReactNode\n}\n\nconst MobileView = ({\n filterBarComponent,\n resultsComponent,\n mapComponent,\n}: MobileViewProps) => {\n return (\n \n {filterBarComponent}\n \n {resultsComponent}\n \n\n \n \n )\n}\n\nexport default MobileView\n","const NAME_NARROW_CHAR_LIMIT = 40\n\nconst truncateToNearestWholeWord = (\n name: string,\n limit: number = NAME_NARROW_CHAR_LIMIT\n) => {\n const words = name.slice(0, limit).split(' ')\n\n return words.slice(0, words.length - 1).join(' ')\n}\n\nexport const formatNameNarrow = (\n name: string,\n limit: number = NAME_NARROW_CHAR_LIMIT\n) => {\n if (!name) return\n\n if (name.length < limit) {\n // eslint-disable-next-line consistent-return\n return name\n }\n\n const truncated = truncateToNearestWholeWord(name, limit)\n\n // eslint-disable-next-line consistent-return\n return `${truncated}...`\n}\n","import React, { memo } from 'react'\nimport styled from 'styled-components'\n\nimport { breakpoints, media, mediaMax } from '../../styles/media'\n\nimport BaseShareButton from '../../components/display/ShareButton'\nimport Button from '../../components/display/Button'\nimport InvisibleButton from '../../components/display/InvisibleButton'\nimport LazyImage from '../../components/display/LazyImage'\nimport Container from '../../components/layout/Container'\nimport PlaceholderCard from '../../components/cards/PlaceholderCard'\nimport { GridItem } from '../../components/layout/ItemGrid'\nimport {\n navbarSizeBreakpoint,\n heightSmall as navbarHeightSmall,\n} from '../../layout/Navbar/constants'\n\nexport const ACTIONS_BAR_HEIGHT_DESKTOP = 80\n\nexport const Loader = memo(() => (\n <>\n {[...Array(6)].map((e, i) => (\n // eslint-disable-next-line react/no-array-index-key\n \n \n \n ))}\n >\n))\n\nexport const StickyButtonWrapper = styled(Container)`\n z-index: 3;\n display: flex;\n flex-direction: column;\n position: fixed;\n bottom: 0;\n width: 100%;\n max-width: ${breakpoints.md}px;\n padding: 16px;\n background-color: white;\n\n ${Button} {\n flex-grow: 1;\n text-transform: uppercase;\n\n &:not(last-child) {\n margin-bottom: 6px;\n }\n }\n`\n\nexport const BucketListName = styled.span`\n font-size: 32px;\n font-weight: 500;\n letter-spacing: 2px;\n text-align: center;\n color: #ffffff;\n\n max-width: 1300px;\n`\n\nexport const Overlay = styled.div`\n position: absolute;\n z-index: 1;\n background-color: black;\n opacity: 0.2;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n`\nexport const ShareButton = styled(BaseShareButton)`\n border: none;\n font-size: 16px;\n color: #333333;\n margin-left: auto;\n`\n\nexport const Actions = styled.div<{ isSticky?: boolean; top?: number }>`\n display: flex;\n align-items: center;\n border-bottom: solid 1px #d3d3d3;\n border-top: solid 1px #d3d3d3;\n\n height: 65px;\n z-index: 2;\n background-color: #fff;\n\n & > div:first-child {\n flex-grow: 1;\n }\n`\n\nexport const DesktopActions = styled.div<{ isSticky?: boolean }>`\n position: relative;\n height: ${ACTIONS_BAR_HEIGHT_DESKTOP}px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n background-color: white;\n padding: 16px;\n z-index: 9;\n border-bottom: 1px solid #d1d1d1;\n`\n\nexport const EditButton = styled(InvisibleButton)`\n position: absolute;\n right: 0;\n top: 0;\n padding: 16px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n\n text-transform: uppercase;\n font-size: 16px;\n font-weight: 400;\n letter-spacing: 1px;\n color: #ffffff;\n\n svg {\n width: 14px;\n height: 14px;\n margin-right: 6px;\n }\n\n ${media.md`\n margin-top: 16px;\n margin-right: 16px;\n `}\n`\n\nexport const Header = styled.div`\n position: relative;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 100%;\n height: 240px;\n\n ${mediaMax[navbarSizeBreakpoint]`\n margin-top: ${navbarHeightSmall}px;\n `}\n\n ${media[navbarSizeBreakpoint]`\n margin-top: 0;\n `}\n\n background-color: lightgrey;\n font-size: 32px;\n letter-spacing: 2px;\n color: #ffffff;\n\n @media (min-width: 540px) {\n height: 400px;\n }\n @media (min-width: 768px) {\n height: 500px;\n }\n\n ${LazyImage} {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 0;\n }\n\n ${EditButton} {\n z-index: 3;\n }\n\n ${BucketListName} {\n z-index: 3;\n\n ${media.md`\n font-size: 42px;\n `}\n }\n`\n\nexport const Subheading = styled.h2`\n width: 100%;\n margin: 35px 16px 16px 16px;\n font-size: 20px;\n text-transform: capitalize;\n color: ${({ theme }) => theme.brand.forest};\n\n ${media.md`\n font-size: 30px;\n margin-bottom: 35px;\n\n &:first-child {\n margin-top: 0;\n }\n `}\n`\n\nexport const SeeMoreButtonWrapper = styled.div`\n width: 100%;\n display: flex;\n justify-content: center;\n padding: 0 32px;\n margin-top: 16px;\n margin-bottom: 48px;\n\n ${Button} {\n width: 100%;\n max-width: 400px;\n }\n`\n","import { useEffect } from 'react'\n\nimport { useMediaQueryContext } from 'contexts/MediaQueryContext'\n\nimport useIsServer from '../../hooks/useIsServer'\n\nconst useBucketListPageLayout = () => {\n const isServer = useIsServer()\n const { md: isMd } = useMediaQueryContext()\n\n // eslint-disable-next-line consistent-return\n useEffect(() => {\n if (!isServer) {\n const $footer: HTMLElement = document.querySelector('#site-footer')\n if ($footer) $footer.style.display = 'none'\n\n return () => {\n if ($footer) $footer.style.display = 'block'\n }\n }\n }, [])\n\n useEffect(() => {\n let $header: Element\n if (!isServer && !isMd) {\n $header = document.querySelector('.app-header')\n $header.classList.add('sticky')\n }\n\n return () => {\n if ($header?.classList?.remove) {\n $header.classList.remove('sticky')\n }\n }\n }, [isServer, isMd])\n}\n\nexport default useBucketListPageLayout\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport ShowMoreText from '../../../components/ShowMoreText'\nimport MediaWrapper from '../../../components/cards/shared/MediaWrapper'\nimport ImageOrSlider from '../../../components/cards/shared/ImageOrSlider'\nimport HeartOnIcon from '../../../components/icons/BucketlistHeartOn'\nimport HeartOffIcon from '../../../components/icons/BucketlistHeartOff'\n\nimport { BucketListButton } from '../../../components/cards/shared/styled'\nimport { titleCase } from '../../../components/utils/stringUtils'\n\nexport const AdventureCardWrapper = styled.div<{ embedded?: boolean }>`\n height: 100%;\n font-size: 16px;\n font-weight: 300;\n font-family: 'GT Walsheim Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif !important;\n\n line-height: 1.375;\n\n color: #999;\n background-color: white;\n\n border: 1px solid #d1d1d1;\n border-radius: 6px;\n\n overflow: hidden;\n white-space: pre-wrap;\n\n ${({ embedded }) =>\n embedded &&\n `\n border: none;\n `}\n`\n\nconst Content = styled.div`\n padding: 24px 16px;\n`\n\nexport const Title = styled.h3`\n color: #333;\n font-size: 16px;\n line-height: 24px;\n margin-bottom: 8px;\n\n font-weight: 500;\n\n .icon {\n font-size: 24px;\n line-height: 1;\n display: inline-block;\n vertical-align: middle;\n margin-right: 8px;\n }\n`\n\nconst IconWrapper = styled.div`\n position: relative;\n height: 0;\n padding-top: 72.222%;\n width: 100%;\n background-color: ${({ theme }) => theme.brand.sand};\n\n .icon {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n\n color: #333;\n font-size: 36px;\n }\n`\n\ntype AdventureCardProps = GQL_ListingNearbyAdventureFragment & {\n embedded?: boolean\n isInEscape?: boolean\n onSelectEscapeClick?: () => any\n storyteller?: GQL_ListingNearbyAdventure_StoryAdventure_Fragment['storyteller']\n}\n\nexport default ({\n adventureType,\n title,\n description,\n photos,\n storyteller,\n embedded,\n onSelectEscapeClick,\n isInEscape,\n url,\n __typename,\n}: AdventureCardProps) => {\n return (\n \n {photos?.length > 0 ? (\n \n \n \n ) : (\n \n \n \n )}\n \n \n {__typename === 'StoryAdventure' ? (\n {titleCase(title)}\n ) : (\n titleCase(title)\n )}\n \n \n {description}\n \n \n\n {onSelectEscapeClick && (\n {\n e.preventDefault()\n onSelectEscapeClick()\n }}\n // @ts-ignore -- not typed yet\n isActive={isInEscape}\n >\n \n \n \n )}\n \n )\n}\n\nexport const AdventureCardLoading = () => {\n return (\n \n \n \n \n )\n}\n","import React from 'react'\nimport { connect } from 'react-redux'\nimport { Field, change } from 'redux-form'\nimport { isTouchDevice } from '../utils/displayUtils'\nimport { shortTimeRangeString } from '../utils/dates'\n\nimport { renderSelectField, renderDropdownField, renderError } from '../form'\n\nimport { validRequired } from '../form/validate'\n\nconst BookingTimeSlot = ({ time_slots, dispatch, formName }) => {\n if (!(time_slots && time_slots.length > 0)) return null\n\n return (\n \n {\n /* eslint-disable eqeqeq */\n const { start, end } = time_slots.find((t) => t.id == value)\n /* eslint-enable eqeqeq */\n dispatch(change(formName, 'booking[start_time]', start))\n dispatch(change(formName, 'booking[end_time]', end))\n }}\n items={time_slots.map(({ start, end, ...timeSlot }) => ({\n ...timeSlot,\n label: shortTimeRangeString(start, end),\n }))}\n validate={[validRequired]}\n white\n >\n \n {time_slots.map(({ id, start, end }) => (\n \n ))}\n \n\n \n\n \n\n \n
\n )\n}\n\nexport default connect()(BookingTimeSlot)\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport ClockIcon from 'components/icons/Clock'\n\nconst Outer = styled.div`\n display: flex;\n align-items: flex-start;\n padding: 10px;\n\n color: ${({ theme }) => theme?.['-ds-success-300']?.value};\n background-color: ${({ theme }) => theme?.['-ds-success-100']?.value};\n\n border: 1px solid ${({ theme }) => theme?.['-ds-success-200']?.value};\n border-radius: 4px;\n\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n font-weight: 400;\n line-height: 1.4;\n\n svg {\n flex-shrink: 0;\n color: ${({ theme }) => theme?.['-ds-success-200']?.value};\n width: 15px;\n height: 15px;\n margin-top: 2px;\n margin-right: 10px;\n }\n`\n\ntype Props = {\n style?: React.CSSProperties\n}\n\nconst AvailabilityAlert = ({ style }: Props) => {\n return (\n \n \n \n Don’t snooze! This is usually booked.\n \n \n )\n}\n\nexport default AvailabilityAlert\n","import React from 'react'\n\nimport AvailabilityAlert from './AvailabilityAlert'\n\nconst DAYS_AFTER_START_DATE_THRESHOLD = 100\nexport const AVAILABILITY_SCORE_THRESHOLD = 20\n\ntype Props = {\n endDate: string\n fromDate?: string\n availabilityScore: number\n style?: React.CSSProperties\n}\n\nconst ContextualAvailabilityAlert = ({\n availabilityScore,\n fromDate,\n endDate,\n style,\n}: Props) => {\n const fromDateInstance = fromDate ? new Date(fromDate) : new Date()\n const endDateInstance = new Date(endDate)\n\n const diffTime = Math.abs(\n endDateInstance.getTime() - fromDateInstance.getTime()\n )\n\n const daysBetweenStartAndEndDate = Math.ceil(diffTime / (1000 * 60 * 60 * 24))\n\n const shouldDisplay =\n daysBetweenStartAndEndDate > 0 &&\n daysBetweenStartAndEndDate < DAYS_AFTER_START_DATE_THRESHOLD &&\n availabilityScore < AVAILABILITY_SCORE_THRESHOLD\n\n if (shouldDisplay !== true) {\n return null\n }\n\n return \n}\n\nexport default ContextualAvailabilityAlert\n","import React from 'react'\nimport styled from 'styled-components'\nimport { Field } from 'redux-form'\nimport get from 'lodash/get'\n\nimport { renderError } from '../../../components/form'\n\nimport GuestsInput from '../../../components/form/GuestsInput'\nimport BookingFormCalendar from '../../../components/enquiry/BookingFormCalendar'\nimport BookingTimeSlot from '../../../components/enquiry/BookingTimeSlot'\n\nimport ConditionalAvailabilityAlert from './AvailabilityAlert/ConditionalAvailabilityAlert'\n\nconst Wrapper = styled.div`\n .DateRangePicker,\n .SingleDatePicker {\n width: 100%;\n }\n`\n\nconst validDate = (value) =>\n !value ? 'Please add dates to request a booking' : undefined\nconst validEnquiryDate = (value) =>\n !value ? 'Please add your preferred dates to make an enquiry' : undefined\n\nconst BookingFormFields = ({\n formName,\n listingId,\n listing,\n enquiry,\n formValues,\n isEnquiryForm,\n}) => {\n const enquiryListing = get(enquiry, 'data.listing')\n\n let startDate\n let endDate\n\n if (enquiryListing && enquiry && enquiry.data) {\n const { start_date, end_date } = enquiryListing && enquiry && enquiry.data\n startDate = start_date\n endDate = end_date\n }\n\n return (\n \n \n
\n\n
\n \n
\n\n
\n\n
\n
\n\n {enquiry && (\n \n )}\n\n \n\n \n \n )\n}\n\nexport default BookingFormFields\n","import React, { useEffect } from 'react'\nimport styled from 'styled-components'\n\nimport useDispatch from 'hooks/useDispatch'\nimport useReduxSelector from 'hooks/useReduxSelector'\nimport useSearchParams from 'hooks/useSearchParams'\n\nimport Button from '../../../components/display/Button'\nimport InstantBookBadge from '../../../components/display/InstantBookBadge'\nimport { slugToNice } from '../../../components/utils/stringUtils'\nimport { formatPrice } from '../../../components/utils/pricing'\n\nimport { resetEnquiryPrices } from '../../../actions/enquiryActions'\n\nexport const MobileActionBarWrapper = styled.div`\n display: flex;\n align-items: center;\n padding: 16px;\n color: ${({ theme }) => theme.brand.forest};\n background-color: ${({ theme }) => theme.brand.sand};\n z-index: 8;\n`\n\nconst PriceWrapper = styled.div`\n flex: 1;\n`\n\ntype PriceProps = {\n $instantBookEnabled?: boolean\n}\n\nconst Price = styled.div`\n display: flex;\n flex-direction: row;\n align-items: baseline;\n\n strong {\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-lg']?.['font-size']?.value};\n font-weight: 500;\n line-height: 1.4;\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n }\n\n small {\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n color: ${({ theme }) => theme?.['-ds-neutral-500']?.value};\n margin: 0 4px;\n font-weight: 400;\n line-height: 1.4;\n }\n`\n\nconst IconButton = styled(Button)`\n padding: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n\n .icon {\n font-size: 18px;\n margin: 0;\n }\n`\n\nconst Actions = styled.div`\n display: flex;\n\n ${Button} {\n padding: 12px 16px;\n border: 1px solid ${({ theme }) => theme.brand.jungle};\n }\n\n ${Button}, ${IconButton} {\n min-width: 52px;\n margin-right: 8px;\n\n &:last-child {\n margin-right: 0;\n }\n\n svg {\n width: 18px;\n margin: 0;\n }\n }\n`\n\ntype MobileActionsBarProps = {\n listing: {\n id: number\n instant_book_enabled: boolean\n price: string\n pricing_suffix: string\n giftable: boolean\n }\n onShowBookingForm: () => any\n}\n\nconst MobileActionBar = ({\n listing,\n onShowBookingForm,\n}: MobileActionsBarProps) => {\n const dispatch = useDispatch()\n\n const searchParams = useSearchParams()\n\n const hasDatesInQueryString =\n searchParams?.has('startDate') && searchParams?.has('endDate')\n\n const enquiry = useReduxSelector((state) => state.enquiry)\n\n useEffect(() => {\n dispatch(resetEnquiryPrices())\n }, [dispatch])\n\n const hasTotal = parseFloat(enquiry?.data?.total) > 0\n\n const hasDatesInEnquiry =\n enquiry?.data?.start_date != null && enquiry?.data?.end_date\n\n const bookCtaLabel =\n hasDatesInQueryString || hasDatesInEnquiry\n ? 'Book now'\n : 'Check availability'\n\n return (\n \n \n \n \n {hasTotal\n ? formatPrice(enquiry.data.total, 0)\n : formatPrice(listing.price, 0)}\n \n \n {hasTotal ? 'total' : slugToNice(listing.pricing_suffix)}\n \n \n {listing.instant_book_enabled && (\n \n \n \n )}\n \n \n \n \n \n )\n}\n\nexport default MobileActionBar\n","import React from 'react'\n\nconst Video = () => (\n \n)\n\nexport default Video\n","/* global analytics */\nimport React from 'react'\nimport styled from 'styled-components'\nimport Slider from 'react-slick'\n\nimport { media } from '../../styles/media'\n\nimport Vimeo from '../Vimeo'\n\nimport ArrowLeft from '../icons/ArrowLeft'\nimport ArrowRight from '../icons/ArrowRight'\nimport CrossOutIcon from '../icons/CrossOut'\nimport VideoIcon from '../icons/Video'\n\nimport Modal from './Modal'\nimport StreamableVideo from './StreamableVideo'\n\nconst Container = styled.div`\n width: 90%;\n margin: 0 auto;\n max-width: 800px;\n`\n\nconst Header = styled.div`\n padding: 20px 0;\n\n color: white;\n text-align: right;\n\n svg {\n width: 40px;\n height: 40px;\n }\n\n @media (min-width: 768px) {\n padding: 40px 0;\n }\n`\n\nconst RatioWrapper = styled.div`\n position: relative;\n flex: 1;\n width: 100%;\n height: 0;\n padding-bottom: 75%;\n`\n\nconst Wrapper = styled.div`\n position: relative;\n height: 100%;\n\n margin: 0 -20px;\n\n ${media.md`\n width: 100%;\n margin: 0;\n `}\n\n @media (min-width: 992px) {\n left: -75px;\n }\n`\n\nconst MainSliderWrapper = styled.div`\n position: absolute;\n overflow: hidden;\n height: 100%;\n width: 100%;\n left: 0;\n top: -1px;\n\n .slick-slider,\n .slick-list,\n .slick-track {\n height: 100%;\n }\n\n .slick-slide {\n display: flex;\n background: black;\n }\n\n .slick-slide > div {\n width: 100%;\n }\n`\n\nconst MainSlide = styled.div`\n height: 100%;\n width: 100%;\n\n background-color: black;\n\n img {\n width: 100%;\n height: 100%;\n object-fit: contain;\n }\n`\n\nconst SideSliderWrapper = styled.div`\n position: absolute;\n left: 0;\n width: 100%;\n\n height: 150px;\n bottom: -150px;\n\n overflow: hidden;\n background-color: rgba(0, 0, 0, 0.6);\n\n @media (min-width: 992px) {\n height: auto;\n width: 150px;\n top: 0;\n left: auto;\n bottom: 1px;\n right: -150px;\n }\n`\n\nconst SideSlide = styled.div`\n position: relative;\n display: flex !important;\n align-items: center;\n justify-content: center;\n\n height: 120px !important;\n width: 100%;\n\n border: 0 !important;\n cursor: pointer;\n\n background-color: black;\n background-repeat: no-repeat;\n background-position: center;\n background-size: cover;\n\n svg {\n position: absolute;\n left: 50%;\n top: 50%;\n\n display: block;\n\n color: white;\n width: 32px;\n\n transform: translate(-50%, -50%);\n }\n\n ${({ backgroundImage }) =>\n backgroundImage &&\n `\n background-color: black;\n background-image: url(${backgroundImage});\n `}\n`\n\nconst NavButton = styled.button`\n position: absolute;\n top: 50%;\n ${({ left }) => (left ? 'left: 0;' : 'right: 0;')}\n transform: translateY(-50%);\n\n padding: 20px;\n border: 0;\n color: white;\n background-color: rgba(0, 0, 0, 0.6);\n\n svg {\n display: block;\n width: 16px;\n }\n`\n\nconst CloseButton = styled.button`\n position: relative;\n background: transparent;\n border: none;\n cursor: pointer;\n\n @media (min-width: 992px) {\n right: -75px;\n }\n`\n\nexport default class FullscreenSlider extends React.Component {\n constructor() {\n super()\n this.state = {\n videoPlayed: false,\n }\n }\n\n componentDidUpdate() {\n const { isOpen } = this.props\n\n setTimeout(() => {\n if (this.MainSlider && isOpen) {\n this.MainSlider.innerSlider.list.setAttribute('tabindex', 0)\n this.MainSlider.innerSlider.list.focus()\n }\n }, 0)\n }\n\n handleChangeSlide = (slideIndex) => {\n this.SideSlider.slickGoTo(slideIndex)\n }\n\n handleVideoPlayed = (url) => {\n const { videoPlayed } = this.state\n\n if (!videoPlayed) {\n this.setState({ videoPlayed: true })\n analytics.track('Played Video', { source: 'page', url })\n }\n }\n\n render() {\n const { slides, video_url, onRequestClose, isOpen } = this.props\n\n const MainSliderSettings = {\n arrows: false,\n beforeChange: () => this.Vimeo && this.Vimeo.pause(),\n afterChange: (next) => this.SideSlider && this.SideSlider.slickGoTo(next),\n }\n\n const SideSliderSettings = {\n slidesToShow: slides.length > 6 ? 6 : slides.length,\n vertical: true,\n verticalSwiping: true,\n arrows: false,\n focusOnSelect: true,\n responsive: [\n {\n breakpoint: 480,\n settings: {\n slidesToShow: slides.length > 3 ? 3 : slides.length,\n vertical: false,\n },\n },\n {\n breakpoint: 992,\n settings: {\n slidesToShow: slides.length > 4 ? 4 : slides.length,\n vertical: false,\n },\n },\n ],\n beforeChange: (current, next) => this.MainSlider.slickGoTo(next),\n }\n\n return (\n \n \n \n \n \n \n (this.MainSlider = slider)}\n {...MainSliderSettings}\n >\n {video_url && (\n \n (this.Vimeo = vimeo)}\n url={video_url}\n onPlay={this.handleVideoPlayed}\n />\n \n )}\n {slides.map((slide) =>\n slide.type === 'video' ? (\n \n \n \n ) : (\n \n
\n \n )\n )}\n \n\n \n
this.MainSlider.slickPrev()} left>\n \n \n
this.MainSlider.slickNext()} right>\n \n \n
\n \n \n\n \n (this.SideSlider = slider)}\n {...SideSliderSettings}\n >\n {video_url && (\n \n \n \n )}\n {slides.map((slide) =>\n slide.type === 'video' ? (\n \n \n \n ) : (\n \n )\n )}\n \n \n \n \n \n )\n }\n}\n","import React, { FunctionComponent, useState } from 'react'\nimport styled from 'styled-components'\n\nimport Button from '../../../components/display/Button'\nimport LazyImage from '../../../components/display/LazyImage'\nimport FullscreenSlider from '../../../components/display/FullscreenSlider'\n\nexport const DesktopListingHeaderWrapper = styled.div`\n position: relative;\n height: 0;\n padding-top: 37.777%;\n background-color: #333;\n\n ${LazyImage} {\n pointer-events: none;\n position: absolute;\n left: 0;\n top: 0;\n }\n`\n\nconst ActionButton = styled(Button)`\n color: #333 !important;\n background-color: rgba(255, 255, 255, 0.9);\n transition: background-color 300ms ease-out;\n &:hover {\n background-color: white;\n }\n`\n\nconst Wrapper = styled.div`\n display: flex;\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n\n ${ActionButton} {\n position: absolute;\n right: 40px;\n bottom: 40px;\n }\n`\n\nconst Main = styled.div<{ pointer?: boolean }>`\n ${({ pointer }) =>\n pointer &&\n `\n cursor: pointer;\n `}\n\n position: relative;\n flex: 1;\n`\n\nconst Thumbs = styled.div`\n display: flex;\n flex-direction: column;\n\n width: 33.333%;\n height: 100%;\n\n border-left: 2px solid white;\n`\n\nconst Thumb = styled.div`\n cursor: pointer;\n position: relative;\n flex: 1;\n\n &:first-child {\n border-bottom: 1px solid white;\n }\n\n &:last-child {\n border-top: 1px solid white;\n }\n`\n\ninterface DesktopListingHeaderProps {\n photos: Pick[]\n videos?: Array<{ id: string; streamUrl: string; thumbnailUrl: string }>\n video_url?: string\n}\n\nconst DesktopListingHeader: FunctionComponent = ({\n photos,\n videos = [],\n video_url,\n}) => {\n const [galleryOpen, setGalleryOpen] = useState(false)\n\n const handleGalleryOpen = () => setGalleryOpen(true)\n const handleGalleryClose = () => setGalleryOpen(false)\n\n const enableGallery = photos.length > 1\n\n const slides = [\n ...videos.map((video) => ({\n type: 'video',\n ...video,\n })),\n ...photos.map((photo) => ({\n type: 'photo',\n ...photo,\n })),\n ]\n\n return (\n \n \n {photos[0] && (\n \n \n \n \n )}\n\n {enableGallery && (\n \n {photos[1] && (\n \n \n \n \n )}\n {photos[2] && (\n \n \n \n \n )}\n \n )}\n\n {enableGallery && (\n \n View Photos\n \n )}\n \n\n \n \n )\n}\n\nexport default DesktopListingHeader\n","import React from 'react'\nimport styled from 'styled-components'\nimport Slider from 'react-slick'\nimport { transparentize } from 'polished'\n\nimport { isTouchDevice } from '../../../components/utils/displayUtils'\n\nimport ChevronDownIcon from '../../../components/icons/ChevronDown'\nimport LazyImage from '../../../components/display/LazyImage'\n\nexport const MobileListingSliderWrapper = styled.div`\n position: relative;\n overflow: hidden;\n width: 100%;\n height: 0;\n padding-top: 75%;\n background-color: #333;\n\n transform: translate3d(0, 0, 0);\n\n ${LazyImage} {\n pointer-events: none;\n position: absolute;\n left: 0;\n top: 0;\n }\n`\n\nexport const Image = styled.div`\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n width: 100%;\n`\n\nexport const SliderImage = styled.div`\n position: relative;\n width: 100%;\n height: 0;\n padding-top: 75%;\n background-color: #333;\n\n ${LazyImage} {\n pointer-events: none;\n position: absolute;\n left: 0;\n top: 0;\n }\n`\n\nconst Arrow = styled.button`\n position: absolute;\n\n height: 36px;\n width: 36px;\n padding: 0;\n\n top: 50%;\n transform: translateY(-50%);\n\n ${({ left }) =>\n left &&\n `\n left: 8px;\n svg {\n margin-left: -2px;\n }\n `}\n\n ${({ right }) =>\n right &&\n `\n right: 8px;\n svg {\n margin-right: -2px;\n }\n `}\n\n appearance: none;\n outline: 0;\n border: none;\n border-radius: 50%;\n background-color: ${({ theme }) => transparentize(0.3, theme.brand.forest)};\n\n svg {\n display: inline-block;\n vertical-align: middle;\n height: 13px;\n margin-top: -2px;\n color: white;\n transform: rotate(${({ left }) => (left ? '90deg' : '-90deg')});\n }\n`\n\nconst SliderWrapper = styled.div`\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n width: 100%;\n\n &:hover {\n ${Arrow} {\n opacity: 1;\n }\n }\n\n ${({ onTouchDevice }) =>\n onTouchDevice &&\n `\n ${Arrow} {\n opacity: 1 !important;\n }\n `}\n`\n\nconst SliderSettings = {\n arrows: false,\n dots: false,\n infinite: true,\n adaptiveHeight: false,\n}\n\nexport default class MobileListingSlider extends React.Component {\n render() {\n const { photos } = this.props\n return (\n \n \n {\n this.Slider = slider\n }}\n {...SliderSettings}\n >\n {photos.map((photo) => (\n \n \n \n \n
\n ))}\n \n this.Slider.slickPrev()}>\n \n \n this.Slider.slickNext()}>\n \n \n \n \n )\n }\n}\n","import styled from 'styled-components'\nimport { media, mediaMax } from '../../../styles/media'\n\nimport { MobileListingSliderWrapper } from '../Header/MobileListingSlider'\nimport { DesktopListingHeaderWrapper } from '../Header/DesktopListingHeader'\nimport { ListingStoryCardWrapper } from '../../../components/cards/ListingStoryCard'\nimport { MobileActionBarWrapper } from '../Booking/MobileActionBar'\n\nexport const ListingWrapper = styled.div`\n ${MobileListingSliderWrapper} {\n margin-bottom: 16px;\n }\n\n ${MobileActionBarWrapper} {\n position: fixed;\n bottom: 0;\n left: 0;\n width: 100%;\n\n box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.12);\n }\n\n ${mediaMax.md`\n ${DesktopListingHeaderWrapper} {\n display: none;\n }\n `}\n\n ${media.md`\n ${MobileListingSliderWrapper} {\n display: none;\n }\n `}\n\n ${media.lg`\n ${MobileActionBarWrapper} {\n display: none;\n }\n `}\n`\n\nexport const ContentWrapper = styled.div`\n ${ListingStoryCardWrapper} {\n margin-bottom: 40px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n`\n\nexport const Section = styled.section`\n padding: 40px 0;\n border-bottom: 1px solid #d1d1d1;\n\n ${media.md`\n padding: 56px 0;\n `}\n\n ${({ borderTop }) =>\n borderTop &&\n `\n border-top: 1px solid #d1d1d1;\n border-bottom: 0;\n `}\n\n ${({ noBorder }) =>\n noBorder &&\n `\n border: none;\n `}\n\n &:last-child {\n border: none;\n }\n`\n\nexport const SubSection = styled.div`\n margin-bottom: 40px;\n\n ${({ intro }) =>\n intro &&\n `\n font-size: 20px;\n `}\n\n ${({ lessMargin }) =>\n lessMargin &&\n `\n margin-bottom: 24px;\n `}\n\n ${({ moreMargin }) =>\n moreMargin &&\n `\n margin-bottom: 56px;\n `}\n`\n\nexport const ListingTitle = styled.h1`\n font-size: 32px;\n margin-bottom: 0.8em;\n\n color: ${({ theme }) => theme.brand.forest};\n\n ${media.md`\n font-size: 50px;\n `}\n`\n\nexport const SectionTitle = styled.h2`\n font-size: 32px;\n line-height: 1.2;\n\n margin: 0;\n margin-bottom: 0.8em;\n\n color: ${({ theme }) => theme.brand.forest};\n`\n\nexport const SectionSubtitle = styled.h3`\n font-size: 20px;\n line-height: 1.1;\n\n margin: 0;\n margin-bottom: 0.8em;\n\n color: ${({ theme }) => theme.brand.forest};\n`\n\nexport const InfoWithIcon = styled.div`\n display: flex;\n align-items: center;\n color: ${({ theme }) => theme.brand.jungle};\n margin-right: 20px;\n\n a {\n color: inherit;\n }\n\n .icon {\n color: inherit;\n margin-right: 14px;\n font-size: 24px;\n }\n`\n\nexport const MapWrapper = styled.div`\n height: 360px;\n`\n","import React, { useState, useEffect } from 'react'\nimport { Field, SubmissionError } from 'redux-form'\nimport styled from 'styled-components'\n\nimport Theme from 'styles/theme'\n\nimport { CardElement, useElements } from '@stripe/react-stripe-js'\n\nimport {\n InputGroup,\n InlineInput,\n InlineInputGroup,\n renderTextInput,\n renderError,\n ErrorLabel,\n} from '../../../components/form'\n\ntype CardNumberProps = {\n $invalid?: boolean\n $rounded?: boolean\n}\n\nconst CustomCardNumberElement = styled(CardElement)`\n height: 60px;\n padding: 18px;\n margin: 8px 0 8px;\n border: 1px solid #d5d5d5;\n\n ${({ $rounded = true }) =>\n $rounded &&\n `\n border-radius: 6px;\n `}\n\n &.StripeElement--invalid {\n border-color: ${({ theme }) => theme?.['-ds-error-300']?.value};\n }\n\n &.StripeElement--focus {\n border-color: ${({ theme }) => theme.brand.jungle};\n }\n\n ${({ $invalid, theme }) =>\n $invalid &&\n `\n border-color: ${theme?.['-ds-error-300']?.value};\n `}\n`\n\nconst CARD_OPTIONS = {\n hidePostalCode: true,\n style: {\n base: {\n color: '#333',\n fontSize: '16px',\n fontWeight: '300',\n fontFamily: Theme.fonts.default,\n letterSpacing: '0.5px',\n },\n invalid: {\n iconColor: Theme?.['-ds-error-300']?.value,\n color: Theme?.['-ds-error-300']?.value,\n },\n },\n}\n\nconst validCardName = (value: string) =>\n !value ? 'Please add the name on the credit card' : undefined\n\ntype NewCreditCardFieldsProps = {\n submitFailed: boolean\n error?: SubmissionError\n}\n\nconst NewCreditCardFields = ({\n submitFailed,\n error: submitError,\n}: NewCreditCardFieldsProps) => {\n const [stripeElementsError, setStripeElementsError] = useState(\n 'Please add card number, expiry date, and CVC'\n )\n const elements = useElements()\n\n useEffect(() => {\n // useElements() will return null until stripe has finished loading.\n // We load stripe asynchronously with loadStripe(), which returns a promise that\n // may not have yet resolved at the time this hook is first executed\n if (elements == null) return\n\n const cardElement = elements.getElement(CardElement)\n cardElement.on('change', ({ error }) => {\n setStripeElementsError(error ? error.message : '')\n })\n }, [elements])\n\n const generalFormError = submitError?.errors?._error\n\n const cardInputInvalid =\n generalFormError != null || (submitFailed && stripeElementsError != null)\n\n return (\n \n \n \n \n \n \n \n {submitFailed && stripeElementsError && generalFormError == null && (\n {stripeElementsError}\n )}\n \n\n \n \n \n \n {!generalFormError && (\n \n )}\n \n \n\n {generalFormError && {generalFormError}}\n \n
\n )\n}\n\nexport default NewCreditCardFields\n","import React from 'react'\nimport {\n WrappedFieldProps,\n Field,\n getFormValues,\n SubmissionError,\n} from 'redux-form'\nimport get from 'lodash/get'\nimport { ElementsConsumer, CardElement } from '@stripe/react-stripe-js'\nimport { connect } from 'react-redux'\nimport axios from 'axios'\n\nimport { useUserCreditCardsQuery } from 'hooks/useQueries'\nimport NewCreditCardFields from 'pages/user/PaymentMethods/NewCreditCardFields'\nimport Spinner from 'components/display/Spinner'\nimport { InputGroup, SelectField } from 'components/form'\nimport ChevronDown from 'components/icons/ChevronDown2'\nimport { HeadingMd, ParagraphSm } from 'components/display/Typography'\n\nimport { Stripe, StripeElements } from '@stripe/stripe-js'\n\ntype WithUserCreditCardQueryProps = {\n onCompleted: Parameters[0]['onCompleted']\n}\n\nconst UserCreditCardsQuery: React.FC = ({\n children,\n onCompleted,\n}) => {\n const { loading, data } = useUserCreditCardsQuery({ onCompleted })\n\n if (typeof children !== 'function') {\n throw new Error(\n 'children passed to UserCreditCardsQuery must be a function'\n )\n }\n\n return children({ loading, data })\n}\n\nexport type SelectPaymentMethodFormValues = {\n payment_method: {\n credit_card_id: string\n new_card_name: string\n }\n}\n\ninterface ReduxState {\n [formName: string]: SelectPaymentMethodFormValues\n}\n\ntype BaseProps = {\n error?: SubmissionError\n cardFieldsError?: string\n rounded?: boolean\n headingType?: 'h2' | 'h3' | 'h4'\n headingWeight?: '300' | '400' | '500'\n}\n\nexport type SelectPaymentMethodProps = WrappedFieldProps &\n BaseProps & {\n elements: StripeElements\n stripe: Stripe\n reduxState: ReduxState\n }\n\nclass SelectPaymentMethod extends React.Component {\n getCreditCardId = async (): Promise => {\n const { input, meta, elements, stripe, reduxState } = this.props\n const cardElement = elements.getElement(CardElement)\n /**\n * We need to return an existing credit card id if selected\n */\n if (input.value !== 'new') {\n return input.value\n }\n\n const {\n payment_method: { new_card_name: newCardName },\n } = getFormValues(meta.form)(reduxState) as SelectPaymentMethodFormValues\n\n let stripeToken: string\n\n try {\n const { token } = await stripe.createToken(cardElement, {\n name: newCardName,\n })\n stripeToken = token?.id\n } catch (error) {\n throw new SubmissionError({\n _error: 'Could not add the credit card. Please contact support.',\n })\n }\n\n if (stripeToken == null) {\n throw new SubmissionError({\n _error: 'Could not add the credit card. Please contact support.',\n })\n }\n\n // create new credit card and get its ID\n return axios\n .post('/user/credit_cards', {\n stripe_token: stripeToken,\n })\n .then(({ data }) => data.id)\n .catch((error) => {\n if (error.response) {\n const { data } = error.response\n const { error: errorMessage } = data\n throw new SubmissionError({\n // redux-form api -- `_error` applies to the whole form, rather than specific fields\n // we pass it down to NewCreditCardFields, which then knows to show inline feedback\n _error: errorMessage,\n })\n }\n })\n }\n\n handleCompleted = (data: GQL_UserCreditCardsQuery) => {\n const { input } = this.props\n const currentUser = get(data, 'currentUser')\n const preferred = currentUser.creditCards\n .filter((c) => !c.expired)\n .sort((a, b) => Number(b.default) - Number(a.default))\n if (preferred.length) return input.onChange(preferred[0].id)\n return input.onChange('new')\n }\n\n render() {\n const {\n input,\n meta,\n error: formError,\n rounded,\n headingType = 'h2',\n headingWeight = '500',\n } = this.props\n\n const error = meta.submitFailed ? formError : undefined\n\n return (\n \n {({\n loading,\n data,\n }: Pick<\n ReturnType,\n 'loading' | 'data'\n >) => {\n const currentUser = get(data, 'currentUser')\n if (loading) {\n return (\n \n \n \n )\n }\n\n return (\n \n
\n Select payment method\n \n\n
\n \n \n \n \n \n \n \n \n\n {input.value === 'new' && (\n
\n \n Add a new card\n \n \n \n )}\n
\n )\n }}\n \n )\n }\n}\n\nconst SelectPaymentMethodWithStripe = React.forwardRef(\n (props, ref) => (\n \n {({ elements, stripe }) => (\n \n )}\n \n )\n)\n\nexport default connect(\n ({ form }: ReduxState) => ({ reduxState: { form } }),\n null,\n null,\n {\n forwardRef: true,\n }\n)(SelectPaymentMethodWithStripe)\n","import { Field } from 'redux-form'\n\n/**\n * Handles getting credit_card_id from an instance of SelectPaymentMethod\n * @param paymentMethodRef - React Ref of the SelectPaymentMethodInstance\n * @returns Promise that resolves with credit_card_id\n */\nexport const handlePaymentMethod = (\n paymentMethodRef: React.RefObject\n): Promise | null => {\n if (!paymentMethodRef.current) return null\n return (\n paymentMethodRef.current\n .getRenderedComponent()\n // @ts-ignore\n .getCreditCardId()\n )\n}\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport voucherRiparideImage from 'assets/images/voucher-riparide.jpg' // eslint-disable-line\nimport voucherListingImage from 'assets/images/voucher-listing.jpg' // eslint-disable-line\nimport voucherStoryImage from 'assets/images/voucher-story.jpg' // eslint-disable-line\nimport RiparideSmallLogo from '../../components/icons/RiparideSmallLogo'\n\nimport { media } from '../../styles/media'\n\nconst Wrapper = styled.div`\n position: relative;\n width: 300px;\n height: 300px;\n\n font-size: 16px;\n\n border-radius: 6px;\n overflow: hidden;\n\n background-repeat: no-repeat;\n background-size: cover;\n background-position: center;\n background-color: black;\n background-image: url(${({ backgroundImage }) => backgroundImage});\n\n ${({ large }) =>\n large &&\n `\n font-size: 20px;\n `}\n`\n\nconst Overlay = styled.div`\n position: relative;\n width: 100%;\n height: 100%;\n\n padding: 40px;\n\n display: flex;\n align-items: center;\n justify-content: center;\n\n color: white;\n background-color: rgba(0, 0, 0, 0.3);\n\n svg {\n position: absolute;\n width: 60px;\n height: 45px;\n top: 30px;\n margin: 0 auto;\n }\n\n ${({ large }) =>\n large &&\n `\n ${media.md`\n padding: 40px;\n `}\n `}\n`\n\nconst ListingType = styled.div`\n width: 100%;\n margin-top: 10px;\n padding: 12px 0;\n\n font-size: 36px;\n text-align: center;\n text-transform: uppercase;\n\n ${({ large }) =>\n large &&\n `\n ${media.md`\n padding: 24px 0;\n `}\n `}\n`\n\nconst ListingTitle = styled.div`\n position: absolute;\n left: 20px;\n bottom: 20px;\n font-size: 1em;\n\n ${({ large }) =>\n large &&\n `\n left: 40px;\n bottom: 40px;\n `}\n`\n\nconst typeToImage = (type) => {\n switch (type) {\n case 'listing':\n return voucherListingImage\n case 'story':\n return voucherStoryImage\n default:\n return voucherRiparideImage\n }\n}\n\nconst Voucher = ({ title, type, large, backgroundImage }) => (\n \n \n \n \n {type ? `${type} Voucher` : 'THE GIFT OF ADVENTURE'}\n \n {title && {title}}\n \n \n)\n\nexport default Voucher\n","export default \"/assets/webpack-assets/voucher-listing.3c9241c5c6fe65df71d2a539fa93745c.jpg\";","export default \"/assets/webpack-assets/voucher-story.67b13c36ea76e989c1d6982f999d866b.jpg\";","export default \"/assets/webpack-assets/voucher-riparide.f5b370f276c07a9b6762dc6f79f5695a.jpg\";","import axios from 'axios'\nimport { push } from 'connected-react-router'\n\nexport function fetchVoucher(id) {\n return (dispatch) =>\n dispatch({\n type: 'VOUCHER_FETCH',\n payload: axios(`/vouchers/${id}`),\n })\n}\n\nexport function createVoucher(data) {\n return (dispatch) => {\n dispatch({\n type: 'VOUCHER_CREATE',\n payload: axios.post('/vouchers', data),\n }).then(({ value }) => {\n dispatch(push(`/vouchers/${value.data.id}/pay`))\n })\n }\n}\n\nexport function payVoucher(id, data) {\n return (dispatch) => {\n dispatch({\n type: 'VOUCHER_PAY',\n payload: axios.post(`/vouchers/${id}/pay`, data),\n }).then(() => {\n dispatch(push(`/vouchers/${id}/success`))\n })\n }\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport React, { ChangeEvent, FunctionComponent, useRef, useState } from 'react'\nimport styled from 'styled-components'\nimport { connect } from 'react-redux'\nimport { FormProvider, useForm, useWatch } from 'react-hook-form'\nimport { useTranslation } from 'react-i18next'\n\nimport useDispatch from 'hooks/useDispatch'\nimport { createVoucher } from 'actions/voucherActions'\nimport { mediaMax } from 'styles/media'\n\nimport TextareaField from 'components/hookForm/TextareaField'\nimport TextField from 'components/hookForm/TextField'\nimport Button from 'components/display/Button'\nimport Overlay from 'components/display/Overlay'\nimport Spinner from 'components/display/Spinner'\nimport SelectField from 'components/hookForm/SelectField'\nimport CurrencyField from 'components/hookForm/CurrencyField'\nimport ErrorMessage from 'components/hookForm/ErrorMessage'\nimport { HintWrapper, InputGroup, Label } from 'components/form'\nimport { formatPrice, formatPriceAsNumber } from 'components/utils/pricing'\nimport { Currency, countryForCurrency } from 'utils/currency'\n\nconst MESSAGE_MAX_LENGTH = 300\n\nexport const trimNewLines = (value: string) => {\n if (!value) {\n return value\n }\n return value.replace(/(\\r\\n\\t|\\n|\\r\\t)/gm, '')\n}\n\nconst Form = styled.form`\n max-width: 744px;\n margin-bottom: 64px;\n`\n\nconst CustomAmountInputAndCurrencySignWrapper = styled.div`\n display: flex;\n /* justify-content: center; */\n align-items: center;\n\n /* padding: 0 8px; */\n\n input {\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n font-weight: 400;\n margin: 0;\n padding: 0;\n border: 1px solid transparent;\n background-color: transparent;\n\n &:focus {\n border: 1px solid transparent;\n }\n\n &::-webkit-input-placeholder {\n /* Chrome/Opera/Safari */\n color: #999;\n }\n &::-moz-placeholder {\n /* Firefox 19+ */\n color: #999;\n }\n &:-ms-input-placeholder {\n /* IE 10+ */\n color: #999;\n }\n &:-moz-placeholder {\n /* Firefox 18- */\n color: #999;\n }\n }\n`\n\nconst HorizontalHiddenRadioLabel = styled.label<{ selected: boolean }>`\n input[type='radio'] {\n position: absolute;\n visibility: hidden;\n }\n\n width: 140px;\n ${mediaMax.md`\n width: 100%;\n `}\n height: 60px;\n display: flex;\n justify-content: center;\n align-items: center;\n\n cursor: pointer;\n border: 1px solid #d5d5d5;\n border-radius: 6px;\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n font-weight: 400;\n color: #1d1d1d;\n padding: 16px;\n\n transition: background-color 300ms ease-out;\n transition: border 300ms ease-out;\n\n ${({ selected, theme }) =>\n selected &&\n `\n border-color: ${theme.brand.jungle};\n color: ${theme.brand.jungle};\n background: rgba(12, 103, 118, 0.1);\n\n input {\n color: ${theme.brand.jungle};\n }\n `}\n`\n\nconst InputGroupHiddenRadios = styled.div`\n display: flex;\n margin-top: 8px;\n\n ${HorizontalHiddenRadioLabel} {\n position: relative;\n flex-grow: 1;\n margin-bottom: 16px;\n\n &:not(:last-child) {\n margin-right: 16px;\n }\n }\n`\n\nconst TotalLabel = styled.span`\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n`\n\nconst TotalAmount = styled.span`\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n margin-left: auto;\n`\n\nconst TotalRow = styled.div`\n display: flex;\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-lg']?.['font-size']?.value};\n font-weight: 500;\n margin-bottom: 30px;\n`\n\nconst Disclaimer = styled.p`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n color: ${({ theme }) => theme?.['-ds-neutral-600']?.value};\n`\n\nconst SubmitButton = styled(Button).attrs({\n uppercase: false,\n})`\n ${mediaMax.md`\n width: 100%;\n `}\n`\n\nconst amounts = {\n '100': 100,\n '200': 200,\n '300': 300,\n custom: 'custom',\n} as const\n\ntype VoucherFormFields = {\n recipient_name: string\n from_name: string\n currency: Currency\n custom_amount: number\n message: string\n}\n\ntype VoucherCreateProps = {\n updating: boolean\n listing_id?: number\n story_id?: number\n}\n\nconst VoucherCreate: FunctionComponent = ({\n updating,\n listing_id,\n story_id,\n}) => {\n const dispatch = useDispatch()\n const { t } = useTranslation('spelling')\n\n const [selectedAmountKey, setSelectedAmountKey] = useState<\n keyof typeof amounts\n >('100')\n\n const customInputRef = useRef()\n\n const form = useForm({\n mode: 'onTouched',\n })\n\n const selectedCurrency = useWatch({\n control: form.control,\n name: 'currency',\n })\n\n const customAmount = useWatch({\n control: form.control,\n name: 'custom_amount',\n })\n\n const handleSelectedAmountChange = (e: ChangeEvent) => {\n const { value } = e.target\n setSelectedAmountKey(value as keyof typeof amounts)\n if (value !== 'custom_amount') {\n form.setError('custom_amount', undefined)\n }\n }\n\n const { isSubmitting } = form.formState\n\n const onSubmit = (formValues: VoucherFormFields) => {\n const {\n currency,\n custom_amount,\n from_name,\n message,\n recipient_name,\n } = formValues\n\n const selectedAmount = amounts[selectedAmountKey]\n const amount = selectedAmount === 'custom' ? custom_amount : selectedAmount\n\n return dispatch(\n createVoucher({\n listing_id,\n story_id,\n from_name,\n recipient_name,\n amount,\n message,\n currency,\n })\n )\n }\n\n const currencySymbol = '$'\n const currencyCountry = countryForCurrency(selectedCurrency)\n\n const selectedAmount = amounts[selectedAmountKey]\n const amount = selectedAmount === 'custom' ? customAmount : selectedAmount\n\n const customAmountValidationMessage = `Please enter an amount between ${currencySymbol}50 and ${currencySymbol}1,200`\n\n return (\n \n \n\n {selectedCurrency && (\n \n This gift voucher is valid for escapes booked in {currencyCountry}{' '}\n only. The payment will be processed in {selectedCurrency} and your\n bank will determine the final amount charged, based on current\n exchange rates.\n \n )}\n \n )\n}\n\ntype ReduxState = {\n vouchers: {\n saving: boolean\n }\n}\n\nexport default connect(({ vouchers }: ReduxState) => ({\n updating: vouchers.saving,\n initialValues: {\n from_name: '',\n recipient_name: '',\n recipient_email: '',\n },\n}))(VoucherCreate)\n","export type Currency = 'AUD' | 'NZD' | 'USD'\n\nconst dollarCurrencies = ['AUD', 'NZD', 'USD'] as const\n\nexport const symbolForCurrency = (currency: Currency) => {\n if (dollarCurrencies.includes(currency)) {\n return '$'\n }\n\n return ''\n}\n\nexport const countryForCurrency = (currency: Currency) => {\n switch (currency) {\n case 'AUD':\n return 'Australia'\n case 'NZD':\n return 'New Zealand'\n case 'USD':\n return 'the United States'\n default:\n return currency\n }\n}\n","import React, { useEffect } from 'react'\nimport styled from 'styled-components'\nimport { connect } from 'react-redux'\nimport queryString from 'qs'\nimport { useTranslation } from 'react-i18next'\n\nimport { fetchListing } from '../../../actions/listingActions'\nimport { fetchStory } from '../../../actions/storyActions'\nimport { media, mediaMax } from '../../../styles/media'\n\nimport { BackLinkAnchor } from '../../../components/display/BackLink'\n\nimport Voucher from '../Voucher'\nimport VoucherCreateForm from './VoucherCreateForm'\n\nconst Wrapper = styled.div`\n .voucher {\n width: 100%;\n margin-bottom: 40px;\n ${media.md`\n height: 400px;\n `}\n }\n\n ${mediaMax.md`\n p {\n font-size: 16px;\n }\n `}\n`\n\nconst PageTitle = styled.h1`\n font-size: 32px;\n ${media.md`\n font-size: 40px;\n `}\n margin: 24px 0;\n color: ${({ theme }) => theme.brand.forest};\n`\n\nconst IntroSection = styled.div`\n width: 100%;\n padding: 16px 0;\n`\n\nconst VoucherCreate = ({ dispatch, location, listing, story }) => {\n const { listing_id, story_id } = queryString.parse(location.search, {\n ignoreQueryPrefix: true,\n })\n\n const { t } = useTranslation('spelling')\n\n useEffect(() => {\n window.scrollTo(0, 0)\n }, [])\n\n useEffect(() => {\n if (story_id) {\n dispatch(fetchStory(story_id))\n } else if (listing_id) {\n dispatch(fetchListing(listing_id))\n }\n }, [listing_id, story_id])\n\n const suggestable = listing.data || story.data\n\n return (\n \n \n \n
\n Riparide Gift Vouchers\n \n
\n \n {t('personalize')}\n {' '}\n your gift voucher\n \n
\n \n\n \n \n )\n}\n\nexport default connect(({ listing, story }) => ({\n listing,\n story,\n}))(VoucherCreate)\n","import React, { FunctionComponent, useRef, useEffect } from 'react'\nimport styled from 'styled-components'\nimport { useParams } from 'react-router'\nimport { reduxForm, InjectedFormProps, SubmissionError } from 'redux-form'\n\nimport useDispatch from 'hooks/useDispatch'\nimport useReduxSelector from 'hooks/useReduxSelector'\n\nimport { fetchVoucher, payVoucher } from '../../../actions/voucherActions'\nimport { mediaMax } from '../../../styles/media'\nimport { formatPrice } from '../../../components/utils/pricing'\n\nimport SelectPaymentMethod, {\n SelectPaymentMethodFormValues,\n} from '../../user/PaymentMethods/SelectPaymentMethod'\nimport { handlePaymentMethod } from '../../user/PaymentMethods/handlePaymentMethod'\nimport LazyStripeElements from '../../../components/stripe/LazyStripe'\n\nimport Button from '../../../components/display/Button'\nimport Container from '../../../components/layout/Container'\nimport InlineSpinner from '../../../components/display/InlineSpinner'\nimport Overlay from '../../../components/display/Overlay'\nimport Spinner from '../../../components/display/Spinner'\n\nimport Voucher from '../Voucher'\n\nconst SubmitButton = styled(Button)`\n min-width: 160px;\n ${mediaMax.md`\n width: 100%;\n `}\n`\n\nconst Wrapper = styled.form`\n position: relative;\n padding: 40px 0;\n`\n\nconst VoucherBox = styled.div`\n border: 1px solid ${({ theme }) => theme.colors.textGreyLight};\n border-radius: 6px;\n padding: 32px 24px;\n margin-bottom: 30px;\n\n .voucher {\n width: 100%;\n max-width: 340px;\n margin: 0 auto;\n margin-bottom: 40px;\n }\n\n h2 {\n margin: 0;\n margin-bottom: 32px;\n line-height: 1;\n\n text-align: center;\n font-size: 20px;\n font-weight: normal;\n }\n`\n\nconst VoucherDetails = styled.div`\n > div {\n margin-bottom: 1em;\n }\n`\n\nexport type VoucherPayProps = InjectedFormProps<\n SelectPaymentMethodFormValues\n> & {\n error?: SubmissionError\n}\n\nconst VoucherPay: FunctionComponent = ({\n handleSubmit,\n submitting,\n error,\n}) => {\n const dispatch = useDispatch()\n const paymentMethodRef = useRef(null)\n const { voucherId } = useParams<{ voucherId: string }>()\n\n const vouchers = useReduxSelector((state) => state?.vouchers)\n\n useEffect(() => {\n if (voucherId) {\n // @ts-ignore -- fetchVoucher not typed yet\n dispatch(fetchVoucher(voucherId))\n window.scrollTo(0, 0)\n }\n }, [])\n\n const suggestable = vouchers.data && vouchers.data[vouchers.data.suggestable]\n const { paying, fetching } = vouchers\n\n return (\n \n \n handlePaymentMethod(paymentMethodRef).then((credit_card_id) =>\n // @ts-ignore -- payVoucher not typed yet\n dispatch(payVoucher(voucherId, { ...formValues, credit_card_id }))\n )\n )}\n >\n \n \n
\n
\n Gift Voucher
\n {/* @ts-ignore -- Voucher not typed yet */}\n \n {vouchers.data && (\n \n \n Amount: {vouchers.data.currency}{' '}\n {formatPrice(vouchers.data.amount)}\n
\n To: {vouchers.data.recipient_name}
\n From: {vouchers.data.from_name}
\n Message:
\n {vouchers.data.message}
\n \n )}\n \n
\n\n
\n \n\n \n {paying || submitting ? : 'Buy Voucher'}\n \n
\n
\n\n {submitting && (\n \n \n \n )}\n \n \n \n )\n}\n\nconst VoucherPayForm = reduxForm({\n form: 'VoucherPay',\n})(VoucherPay)\n\nexport default VoucherPayForm\n","import React, { useEffect, useRef } from 'react'\nimport styled from 'styled-components'\nimport { connect } from 'react-redux'\n\nimport { useGetUserCountryAndStripeKeyQuery } from 'hooks/useQueries'\n\nimport { fetchVoucher } from '../../../actions/voucherActions'\nimport { media } from '../../../styles/media'\n\nimport ButtonLink from '../../../components/display/ButtonLink'\nimport InlineSpinner from '../../../components/display/InlineSpinner'\nimport Separator from '../../../components/display/Separator'\nimport BaseContainer from '../../../components/layout/Container'\n\nimport Voucher from '../Voucher'\n\nconst Container = styled(BaseContainer)`\n display: flex;\n flex-direction: column;\n align-items: center;\n`\n\nconst PrimaryCallsToAction = styled.div`\n margin: 16px 0;\n display: flex;\n flex-direction: column;\n\n ${media.md`\n margin-bottom: 0;\n flex-direction: row;\n `}\n\n ${ButtonLink} {\n margin-top: 16px;\n min-width: 230px;\n\n &:not(:last-child) {\n ${media.md`\n margin-right: 32px;\n `}\n }\n }\n`\n\nconst PrimarySection = styled.div`\n width: 100%;\n max-width: 618px;\n border: 1px solid ${({ theme }) => theme['-ds-neutral-500'].value};\n border-radius: 6px;\n padding: 16px;\n\n ${media.md`\n padding: 36px;\n `}\n\n display: flex;\n flex-direction: column;\n align-items: center;\n\n .voucher {\n width: 100%;\n height: 300px;\n\n ${media.md`\n height: 400px;\n `}\n }\n`\n\nconst Info = styled.div`\n width: 100%;\n max-width: 800px;\n text-align: center;\n\n padding-top: 36px;\n padding-bottom: 64px;\n ${media.md`\n padding-top: 56px;\n padding-bottom: 80px;\n `}\n\n & > * {\n margin: 16px 0;\n }\n\n h3 {\n color: ${({ theme }) => theme.brand.forest};\n font-size: 20px;\n ${media.md`\n font-size: 30px;\n `}\n }\n p {\n line-height: 1.75;\n text-align: center;\n font-size: 16px;\n margin-bottom: 0;\n ${media.md`\n font-size: 20px;\n `}\n }\n`\n\nconst Heading = styled.h1`\n color: ${({ theme }) => theme.brand.forest};\n text-align: center;\n font-size: 32px;\n font-weight: 500;\n line-height: 1.2;\n\n ${media.md`\n font-size: 40px;\n `}\n`\n\nconst SecondaryHeading = styled(Heading)`\n font-size: 20px;\n ${media.md`\n font-size: 30px;\n `}\n`\n\nconst HeadingWrapper = styled.div`\n padding: 36px 0;\n max-width: 600px;\n`\n\nconst SecondaryCallsToAction = styled.div`\n width: 100%;\n display: flex;\n flex-direction: column;\n\n ${media.md`\n flex-direction: row;\n justify-content: center;\n `}\n\n ${ButtonLink} {\n width: 100%;\n\n ${media.md`\n width: 240px;\n\n &:not(:last-child) {\n margin-right: 24px;\n }\n `}\n }\n`\n\nconst SecondarySection = styled.div`\n width: 100%;\n max-width: 800px;\n display: flex;\n flex-direction: column;\n align-items: center;\n\n padding: 64px 0;\n ${media.md`\n padding: 80px 0;\n `}\n\n ${SecondaryHeading} {\n margin-bottom: 44px;\n }\n\n ${SecondaryCallsToAction} {\n }\n`\n\nconst DownloadButtonLink = styled(ButtonLink)`\n background-color: ${({ theme }) => theme.brand.jungle};\n`\n\nconst VoucherCreateSuccess = ({ dispatch, match, vouchers, userSignedIn }) => {\n useEffect(() => {\n dispatch(fetchVoucher(match.params.voucherId))\n window.scrollTo(0, 0)\n }, [])\n\n const suggestable = vouchers.data && vouchers.data[vouchers.data.suggestable]\n const downloadUrl = vouchers?.data?.pdf_url\n\n const pollVoucherEndpoint = () =>\n dispatch(fetchVoucher(match.params.voucherId))\n\n const intervalId = useRef()\n\n // poll the endpoint while server is working on generating the voucher pdf and uploading it to storage\n useEffect(() => {\n if (!intervalId.current && userSignedIn) {\n intervalId.current = setInterval(pollVoucherEndpoint, 3000)\n }\n }, [intervalId, userSignedIn])\n\n // stop polling when server returns pdf url\n useEffect(() => {\n if (downloadUrl) {\n clearInterval(intervalId.current)\n }\n }, [downloadUrl, intervalId])\n\n // stop polling after 1 minute regardless\n useEffect(() => {\n setTimeout(() => {\n clearInterval(intervalId.current)\n }, 60000)\n }, [intervalId])\n\n const { data: countryData } = useGetUserCountryAndStripeKeyQuery()\n\n const countryCode = countryData?.currentUser?.defaultCountry?.code\n\n return (\n \n \n Your gift voucher purchase was successful\n \n\n \n \n \n \n {downloadUrl ? 'Download Voucher' : }\n \n \n Buy Another Voucher\n \n \n \n\n \n What's next?
\n \n Your gift voucher has also been emailed to{' '}\n {vouchers?.data?.user?.email} (check your junk folder if you\n can't find it). Print it out or send it to the lucky recipient,\n and then pat yourself on the back for giving such a great gift.\n
\n \n\n \n\n \n \n While you're here, why not check out some of our great stories\n and listings and book your own soul-fulfilling escape…\n \n \n \n {countryCode ? 'Book an Escape' : }\n \n \n \n \n )\n}\n\nexport default connect(({ vouchers, auth }) => ({\n vouchers,\n userSignedIn: auth?.isSignedIn,\n}))(VoucherCreateSuccess)\n","import React from 'react'\nimport Moment from 'moment'\nimport styled from 'styled-components'\n\nimport ShowMoreText from '../../ShowMoreText'\n\nconst ReviewContainer = styled.div`\n padding: 1em 0;\n justify-content: 'flex-start';\n display: flex;\n flex: 1;\n flex-direction: column;\n`\nconst ReviewMeta = styled.div`\n display: flex;\n flex-direction: row;\n justify-content: 'flex-start';\n padding: 1rem 0 1.6rem;\n`\nconst ReviewContent = styled.div`\n display: inline-block;\n position: relative;\n padding: 3rem;\n background-color: ${({ theme }) => theme.colors.grey};\n color: #555555;\n\n &:before {\n content: '';\n position: absolute;\n display: block;\n width: 25px;\n height: 25px;\n transform: rotate(45deg);\n top: -5px;\n left: 22px;\n right: auto;\n background-color: ${({ theme }) => theme.colors.grey};\n }\n`\nconst ReviewerWrap = styled.div`\n display: flex;\n flex-direction: column;\n order: 1;\n padding: 0 20px;\n text-align: left;\n`\nconst ProfileImgContainer = styled.div`\n vertical-align: top;\n margin: 0;\n`\nconst ProfileImg = styled.img`\n height: 70px;\n width: 70px;\n border-radius: 50%;\n`\nconst ReviewerName = styled.div`\n font-size: 1.8rem;\n margin-top: 1.2rem;\n color: #555555;\n`\nconst ReviewedDate = styled.div`\n font-size: 1.4rem;\n color: ${({ theme }) => theme.colors.textGreySemiLight};\n`\n\nclass Review extends React.Component {\n render() {\n const { review } = this.props\n const { reviewer, content } = review\n const reviewedDate = Moment(review.created_at).format('D MMM YYYY')\n\n return (\n \n \n \n \n \n \n {reviewer.first_name}\n {reviewedDate}\n \n \n \n {content}\n \n \n )\n }\n}\n\nexport default Review\n","import React from 'react'\n\nconst SvgInstagram = (props) => (\n \n)\n\nexport default SvgInstagram\n","import React from 'react'\nimport styled from 'styled-components'\nimport { connect } from 'react-redux'\nimport Media from 'react-media'\n\nimport fetchUser from '../../actions/userActions'\n\nimport Container from '../../components/layout/Container'\nimport Spinner from '../../components/display/Spinner'\nimport SimpleA from '../../components/display/SimpleAnchor'\n\nimport StoryCard from '../../components/cards/StoryCard'\nimport { Content } from '../../components/cards/shared/styled'\nimport ListingCard from '../../components/cards/ListingCard'\nimport Review from '../../components/cards/shared/Review'\n\nimport InstagramIcon from '../../components/icons/Instagram'\nimport LocationPinIcon from '../../components/icons/LocationPin'\nimport ValidIcon from '../../components/icons/Valid'\n\nimport ShowMoreText from '../../components/ShowMoreText'\n\nconst Wrapper = styled.div`\n .row {\n display: flex;\n flex-wrap: wrap;\n }\n`\n\nconst SpinnerWrapper = styled.div`\n min-height: 300px;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n`\n\nconst Section = styled.section`\n padding: 40px 0;\n margin: 0 !important;\n`\n\nconst SectionTitle = styled.h2`\n margin: 0;\n margin-bottom: 40px;\n font-size: 28px;\n line-height: 1;\n`\n\nconst Counter = styled.span`\n position: relative;\n top: -4px;\n display: inline-block;\n width: 24px;\n height: 24px;\n margin-left: 12px;\n\n font-size: 16px;\n font-weight: normal;\n line-height: 24px;\n text-align: center;\n\n border-radius: 4px;\n color: white;\n background-color: ${({ theme }) => theme.brand.jungle};\n`\n\nconst IntroSection = styled.div`\n display: flex;\n`\n\nconst IntroTitle = styled.h1`\n font-size: 32px;\n margin: 0;\n margin-bottom: 20px;\n\n @media (min-width: 768px) {\n font-size: 42px;\n }\n`\n\nconst AvatarWrapper = styled.div`\n padding-right: 20px;\n @media (min-width: 768px) {\n padding-right: 68px;\n }\n`\n\nconst Avatar = styled.img`\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background-color: black;\n margin-bottom: 20px;\n\n float: left;\n margin-right: 20px;\n\n @media (min-width: 768px) {\n float: none;\n margin-right: 0;\n width: 200px;\n height: 200px;\n }\n`\n\nconst AttributesWrapper = styled.div`\n display: flex;\n width: 100%;\n flex-direction: column;\n margin-bottom: 20px;\n @media (min-width: 768px) {\n flex-direction: row;\n }\n`\n\nconst UserAttribute = styled.div`\n display: flex;\n align-items: center;\n padding: 12px 0;\n margin-right: 20px;\n color: ${({ theme, colorful }) =>\n colorful ? theme['-ds-core-400'].value : theme.colors.labelGrey};\n\n svg {\n color: ${({ theme }) => theme['-ds-core-400'].value};\n height: 18px;\n margin-right: 8px;\n }\n`\n\nconst CardWrapper = styled.div`\n position: relative;\n\n ${Content} {\n padding-left: 0 !important;\n padding-right: 0 !important;\n }\n`\n\nclass UserProfile extends React.Component {\n UNSAFE_componentWillMount() {\n const { dispatch, match } = this.props\n dispatch(fetchUser(match.params.userId)).then(({ value }) => {\n const { data } = value\n\n if (data && document) {\n document.title = `${data.first_name} | ${document.title}`\n }\n })\n }\n\n renderStory = (story) => {\n const { listing } = story.featured_listing\n\n return (\n \n \n \n )\n }\n\n render() {\n const { user } = this.props\n\n if (user.fetching || !user.data) {\n return (\n \n \n \n )\n }\n\n return (\n \n \n \n \n \n \n \n \n \n \n
\n \n \n
Hi, I'm {user.data.first_name}\n
\n {user.data.location && (\n \n {user.data.location}\n \n )}\n {user.data.email_verified && (\n \n Email Verified\n \n )}\n {user.data.phone_number_verified && (\n \n Phone Verified\n \n )}\n {user.data.facebook_verified && (\n \n Facebook Verified\n \n )}\n {user.data?.instagram && (\n \n \n @{user.data.instagram}\n \n \n )}\n \n
{user.data.description}\n
\n \n \n\n {user.data.stories.length > 0 && (\n \n \n Stories {user.data.stories.length}\n \n \n {user.data.stories.map(this.renderStory)}\n
\n \n )}\n\n {user.data.listings.length > 0 && (\n \n \n Listings {user.data.listings.length}\n \n \n {user.data.listings.map((listing) => (\n \n \n \n ))}\n
\n \n )}\n\n {user.data.reviews.length > 0 && (\n \n \n Reviews {user.data.reviews.length}\n \n \n {user.data.reviews.map((review) => (\n \n ))}\n
\n \n )}\n \n \n )\n }\n}\n\nexport default connect(({ user }) => ({ user }))(UserProfile)\n","import axios from 'axios'\n\nexport default function fetchUser(id) {\n return (dispatch) =>\n dispatch({\n type: 'USER_FETCH',\n payload: axios(`/users/${id}`),\n })\n}\n","/* global analytics */\nimport React, { useEffect, useState } from 'react'\nimport { connect } from 'react-redux'\nimport { useParams } from 'react-router'\nimport cloneDeep from 'lodash/cloneDeep'\nimport { RouterState } from 'connected-react-router'\n\nimport { useMediaQueryContext } from 'contexts/MediaQueryContext'\n\nimport {\n useGetBucketListQuery,\n useGetBucketListItemsQuery,\n useGetBucketListMapResultsQuery,\n} from '../../hooks/useQueries'\nimport { resetFilters } from '../../actions/myBucketlistActions'\nimport { deserializeSearchQuery } from '../../actions/utils/search'\n\nimport LazyImage from '../../components/display/LazyImage'\nimport DisableScrollAnchoring from '../../components/utils/DisableScrollAnchoring'\nimport useWhichMapMode from '../../components/layout/ItemGridWithMap/useWhichMapMode'\nimport DatesFilter from '../../search/filters/mobile/DatesFilter'\nimport PeopleFilterPanel from '../../search/filters/mobile/PeopleFilter'\nimport { MobileFiltersInner } from '../../components/layout/ItemGridWithMap/Mobile'\nimport { MobileFilterButton } from '../../search/MobileSearchView'\nimport { normalizeKeys } from '../../components/utils/propsUtils'\n\nimport Map from './Map'\nimport DesktopBucketListFilters from './DesktopBucketListFilters'\nimport DesktopView from './DesktopView'\nimport MobileView from './MobileView'\nimport Items from './Items'\nimport useBucketListPageLayout from './useBucketListPageLayout'\nimport {\n Actions,\n BucketListName,\n DesktopActions,\n Header,\n Overlay,\n} from './shared'\nimport { formatNameNarrow } from './helpers'\n\ninterface Filters {\n adults?: number\n children?: number\n startDate?: string\n endDate?: string\n}\n\ninterface BucketListProps {\n filters: Filters\n dispatch: (...args: any) => any\n searchQuery?: string\n}\n\ntype FilterPanelName = 'dates' | 'people' | 'adventure_type' | null\n\nconst Bucketlist = ({ dispatch, filters, searchQuery }: BucketListProps) => {\n useBucketListPageLayout()\n\n const { md: isMd } = useMediaQueryContext()\n\n const mapMode = useWhichMapMode()\n const inlineMapMode = mapMode === 'inline'\n\n const { token } = useParams() as { token: string }\n\n const [openPanel, setOpenPanel] = useState(null) as [\n FilterPanelName,\n (arg0: FilterPanelName) => any\n ]\n const handleClosePanel = () => setOpenPanel(null)\n const handleResetFilters = () => dispatch(resetFilters())\n\n const {\n loading: bucketListLoading,\n data: bucketListData,\n } = useGetBucketListQuery({\n variables: {\n token,\n },\n })\n const user = bucketListData?.bucketList?.user\n\n const itemsPerFetch = 12\n const {\n loading: accommodationLoading,\n data: accommodationData,\n fetchMore: fetchMoreAccomodation,\n } = useGetBucketListItemsQuery({\n variables: {\n token,\n first: itemsPerFetch,\n params: {\n ...filters,\n type: 'accommodation',\n },\n },\n })\n\n const {\n loading: adventuresLoading,\n data: adventuresData,\n fetchMore: fetchMoreAdventures,\n } = useGetBucketListItemsQuery({\n variables: {\n token,\n first: itemsPerFetch,\n params: {\n ...filters,\n type: 'adventures',\n },\n },\n })\n\n const {\n loading: mapLoading,\n data: mapData,\n } = useGetBucketListMapResultsQuery({\n variables: {\n token,\n params: filters,\n },\n })\n const mapResults = mapData?.bucketList?.mapResults || []\n\n useEffect(() => {\n if (user) {\n analytics.track('Public Bucket List Viewed', {\n owner_id: user.id,\n })\n }\n }, [user])\n\n const handleSeeMoreAccommodation = () => {\n fetchMoreAccomodation({\n variables: {\n cursor: accommodationData.bucketList.items.pageInfo.endCursor,\n },\n updateQuery: (prevResult, { fetchMoreResult }) => {\n if (!fetchMoreResult) return prevResult\n\n const { edges: previousEdges } = prevResult.bucketList.items\n const {\n edges: nextEdges,\n pageInfo: nextPageInfo,\n } = fetchMoreResult.bucketList.items\n\n const nextResult = cloneDeep(prevResult)\n nextResult.bucketList.items.pageInfo = nextPageInfo\n nextResult.bucketList.items.edges = [...previousEdges, ...nextEdges]\n return nextResult\n },\n })\n }\n\n const handleSeeMoreAdventures = () => {\n fetchMoreAdventures({\n variables: {\n cursor: adventuresData.bucketList.items.pageInfo.endCursor,\n },\n updateQuery: (prevResult, { fetchMoreResult }) => {\n const nextResult = cloneDeep(prevResult)\n if (!fetchMoreResult) return nextResult\n\n const { edges: previousEdges } = prevResult.bucketList.items\n const {\n edges: nextEdges,\n pageInfo: nextPageInfo,\n } = fetchMoreResult.bucketList.items\n\n nextResult.bucketList.items.pageInfo = nextPageInfo\n nextResult.bucketList.items.edges = [...previousEdges, ...nextEdges]\n return nextResult\n },\n })\n }\n\n const accommodationHasNextPage =\n accommodationData?.bucketList?.items?.pageInfo?.hasNextPage\n const adventuresHasNextPage =\n adventuresData?.bucketList?.items?.pageInfo?.hasNextPage\n\n const accommodationNodes = accommodationData?.bucketList?.items?.edges?.map(\n ({ node }) => node\n )\n const adventuresNodes = adventuresData?.bucketList?.items?.edges?.map(\n ({ node }) => node\n )\n\n const hasFilters = Object.keys(filters).length > 0\n const noAccommodation = accommodationNodes?.length === 0\n const noAdventures = adventuresNodes?.length === 0\n const noNodes = noAccommodation && noAdventures\n const bucketListEmpty = !hasFilters && noNodes\n\n const themeImage = bucketListData?.bucketList?.theme?.image\n const headerImageSrc = isMd ? themeImage?.hero : themeImage?.large\n const headerBucketListName = isMd\n ? bucketListData?.bucketList?.name\n : formatNameNarrow(bucketListData?.bucketList?.name)\n\n const hideFilters =\n bucketListData?.bucketList?.includesAccommodation === false\n\n const mapComponent = (\n \n )\n\n const itemsComponent = (\n \n )\n\n const filterBarComponent =\n bucketListEmpty !== true &&\n (isMd ? (\n \n {!hideFilters && }\n \n ) : (\n \n \n {!hideFilters && (\n <>\n setOpenPanel('dates')}\n active={!!filters.startDate || !!filters.endDate}\n >\n Dates\n \n setOpenPanel('people')}\n active={!!filters.adults || !!filters.children}\n >\n People\n \n >\n )}\n \n \n ))\n\n return (\n <>\n \n \n \n {headerBucketListName}\n \n \n\n {inlineMapMode ? (\n \n ) : (\n \n )}\n\n \n\n \n >\n )\n}\n\ninterface ReduxState {\n router: RouterState\n}\n\nexport default connect(({ router }: ReduxState) => ({\n filters: normalizeKeys(deserializeSearchQuery(router.location.search)),\n searchQuery: router.location.search,\n}))(Bucketlist)\n","import React from 'react'\n\nimport BaseHeader from 'components/landing/SmallHeader'\nimport { formatPrice } from 'components/utils/pricing'\n\ntype HeaderProps = {\n referral: GQL_GetCustomerReferralQuery['customerReferral']\n}\n\nconst Header = ({ referral }: HeaderProps) => (\n \n)\n\nexport default Header\n","import React from 'react'\nimport styled from 'styled-components'\nimport Avatar from 'components/display/Avatar'\nimport LazyImage from 'components/display/LazyImage'\nimport { ParagraphSm } from 'components/display/Typography'\nimport TextWithLineBreaks from 'components/TextWithLineBreaks'\n\nconst Wrapper = styled.div`\n display: flex;\n align-items: flex-start;\n margin: 24px 0;\n\n ${Avatar} {\n height: 100px;\n width: 100px;\n }\n`\n\nconst Card = styled.div`\n border: 1px solid #dddddd;\n border-radius: 8px;\n padding: 16px;\n width: 100%;\n`\n\ntype MessageProps = {\n referral: GQL_GetCustomerReferralQuery['customerReferral']\n}\n\nconst Message = ({ referral }: MessageProps) => {\n const { referrer } = referral\n\n return (\n \n \n \n \n \n \n \n \n \n \n )\n}\n\nexport default Message\n","import React from 'react'\nimport styled from 'styled-components'\nimport moment from 'moment'\n\nconst Wrapper = styled.div`\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-bottom 24px;\n`\n\nconst Code = styled.div`\n border: 2px solid;\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n border-color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n background-color: ${({ theme }) => theme?.['-ds-neutral-200']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-lg']?.['font-size']?.value};\n font-weight: 400;\n text-align: center;\n border-radius: 8px;\n padding: 16px;\n width: 100%;\n margin-top: 6px;\n`\n\nconst Expiry = styled.div`\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n margin-top: 8px;\n`\n\ntype VoucherProps = {\n voucher: GQL_GetCustomerReferralQuery['customerReferral']['referralVoucher']\n}\n\nconst Voucher = ({ voucher }: VoucherProps) => {\n return (\n \n {voucher.code}
\n \n Expiry Date: {moment(voucher.expiresAt).format('DD MMM YYYY')}\n \n \n )\n}\n\nexport default Voucher\n","import React from 'react'\n\nimport MetaTags from 'components/meta/MetaTags'\nimport ScrollTop from 'components/utils/ScrollTop'\nimport {\n Container,\n PageCTALink,\n ResponsiveTwoColumnLayout,\n SpacedColumn,\n} from 'components/landing/display'\nimport { useGetCustomerReferralQuery } from 'hooks/useQueries'\nimport { useParams } from 'react-router'\nimport Loading from 'components/display/Loading'\nimport { HeadingLg, ParagraphSm } from 'components/display/Typography'\nimport styled from 'styled-components'\nimport SimpleA from 'components/display/SimpleAnchor'\nimport HelpCard from 'components/cards/HelpCard'\nimport isEmpty from 'lodash/isEmpty'\nimport Header from './Header'\nimport Message from './Message'\nimport Voucher from './Voucher'\n\nconst MessageWrapper = styled.div`\n width: 100%;\n`\n\nconst VoucherWrapper = styled.div`\n width: 100%;\n\n ${HeadingLg} {\n margin-top: 24px;\n text-align: center;\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n }\n`\n\nconst Referral = () => {\n const { token } = useParams() as { token: string }\n const { data, loading } = useGetCustomerReferralQuery({\n variables: { token },\n })\n\n if (loading) {\n return \n }\n\n const referral = data?.customerReferral\n\n return (\n <>\n \n \n \n\n \n \n {!isEmpty(referral.message) && (\n \n \n Here's what they had to say:\n \n \n \n )}\n \n \n \n Use your voucher code below when booking your first escape, and\n we'll send {referral.referrer.firstName} a voucher too once\n your booking is complete.\n \n Your unique voucher code\n \n \n Simply add your voucher when you're booking your first\n escape.\n \n \n \n Learn more about redeeming vouchers.\n \n \n \n \n \n \n \n \n \n Ready to get started? Check out our stories to find your first\n adventure.\n \n }\n href=\"/stories\"\n >\n Explore Stories\n \n \n \n \n Learn more about how referrals work on Riparide.\n \n \n \n >\n )\n}\n\nexport default Referral\n","import React from 'react'\nimport { Switch, Route } from 'react-router-dom'\nimport loadable from '@loadable/component'\n\nimport VoucherCreate from '../pages/vouchers/Create'\nimport VoucherPay from '../pages/vouchers/Pay/index'\nimport VoucherCreateSuccess from '../pages/vouchers/Success'\n\nimport UserProfile from '../pages/user/UserProfile'\nimport Bucketlist from '../pages/bucketlist'\nimport Loading from '../components/display/Loading'\nimport Referral from '../pages/referral'\n\nconst UserRoutes = loadable(\n () => import('./UserRoutes' /* webpackChunkName: \"user\" */),\n {\n fallback: ,\n }\n)\nconst BookingRoutes = loadable(\n () => import('./BookingRoutes' /* webpackChunkName: \"bookings\" */),\n {\n fallback: ,\n }\n)\n\nexport default (\n \n \n \n \n \n\n \n \n\n \n \n \n \n \n)\n","import React, { useEffect, useRef } from 'react'\nimport styled from 'styled-components'\nimport { Tab, Tabs, TabList, TabPanel } from 'react-tabs'\n\nimport { Source, trackAccommodationViewed } from 'analytics/map'\nimport ListingCard from 'components/cards/ListingCard'\nimport StoryCard from 'components/cards/StoryCard'\nimport WithSelectEscape from 'components/SelectEscape/WithSelectEscape'\n\nconst Wrapper = styled.div<{ hideTabs?: boolean }>`\n .react-tabs {\n display: flex;\n flex-direction: column;\n justify-content: center;\n\n &__tab-list {\n display: ${({ hideTabs }) => (hideTabs ? 'none' : 'flex')};\n align-items: center;\n list-style: none;\n background-color: ${({ theme }) => theme?.['-ds-neutral-200']?.value};\n border-radius: 100px;\n margin: 0 auto 8px auto;\n padding: 2.5px 4px;\n }\n\n &__tab {\n font-family: ${({ theme }) =>\n theme?.['-ds-font-size-xxxs']?.['font-family']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxxs']?.['font-size']?.value};\n font-weight: 500;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n padding: 10px 20px;\n border-radius: 100px;\n }\n\n &__tab--selected {\n background-color: ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n border: 1px solid rgba(72, 80, 93, 0.1);\n box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.05);\n }\n }\n`\n\ninterface MarkerCalloutTabbedViewProps {\n tabIndex: number\n onTabChange: (prop: any) => any\n listing: GQL_Listing\n latestStory: GQL_StoryCardFragmentFragment\n bucketListItemsIndex: GQL_BucketListItemsIndex\n showListing: boolean\n source: Source\n}\n\nconst MarkerCalloutTabbedView = ({\n tabIndex,\n onTabChange,\n listing,\n latestStory,\n bucketListItemsIndex,\n showListing,\n source,\n}: MarkerCalloutTabbedViewProps) => {\n const analyticsTrackedMatrix = useRef([])\n\n useEffect(() => {\n trackAccommodationViewed({\n listingId: listing.id,\n storyId: latestStory.id,\n source,\n })\n\n if (showListing) {\n // otherwise, the listing itself\n trackAccommodationViewed({\n listingId: listing.id,\n source,\n })\n }\n }, [])\n\n return (\n \n {\n onTabChange(index)\n\n if (analyticsTrackedMatrix.current[index] === true) return\n\n trackAccommodationViewed({\n listingId: listing.id,\n storyId: latestStory.id,\n source,\n })\n\n analyticsTrackedMatrix.current[index] = true\n }}\n >\n \n Story\n {showListing && Listing}\n \n\n \n \n \n \n \n\n {showListing && (\n \n \n \n \n \n )}\n \n \n )\n}\n\nexport default MarkerCalloutTabbedView\n","import React from 'react'\nimport { connect } from 'react-redux'\nimport styled, { ThemeProvider } from 'styled-components'\nimport { withRouter } from 'react-router'\n\nimport { useMapMarkerCalloutQuery } from 'hooks/useQueries'\nimport {\n trackAccommodationViewed,\n trackAdventureViewed,\n} from '../../analytics/map'\n\nimport { MarkerPopupWrapper } from '../../components/maps/styled'\nimport AdventureCard from '../../components/cards/AdventureCard'\n\nimport { deserializeSearchQuery } from '../../actions/utils/search'\nimport styledTheme from '../../styles/theme'\n\nimport PlaceholderCard from '../../components/cards/PlaceholderCard'\nimport ListingCard from '../../components/cards/ListingCard'\nimport WithSelectEscape from '../../components/SelectEscape/WithSelectEscape'\nimport { makeItemKey } from '../../dashboard/MyBucketlists/gql/getBucketListItemsIndexHelpers'\n\nimport { formatUrlWithFilters } from '../utils'\nimport MarkerCalloutTabbedView from './MarkerCalloutTabbedView'\n\nconst MarkerCalloutWrapper = styled.div`\n position: relative;\n height: 0;\n width: 0;\n\n transition: transform 300ms ease-out;\n\n ${({ x, y }) => `\n transform: translate(${x}px, ${y}px);\n `}\n\n ${({ open }) =>\n open &&\n `\n z-index: 1;\n `}\n`\n\nconst isListingInBucketList = ({\n listing,\n bucketListItemsIndex,\n bucketListId,\n}) => {\n const indexKey = makeItemKey({ itemId: listing.id, itemType: 'Listing' })\n const bucketListIds = bucketListItemsIndex[indexKey] ?? []\n return bucketListIds.includes(bucketListId)\n}\n\nconst filterStoriesThatAreInCurrentBucketList = ({\n stories,\n bucketListItemsIndex,\n bucketListId,\n}) => {\n return stories.filter((story) => {\n const indexKey = makeItemKey({ itemId: story.id, itemType: 'Story' })\n const bucketListIds = bucketListItemsIndex[indexKey] ?? []\n\n return bucketListIds.includes(bucketListId)\n })\n}\n\nclass MarkerCallout extends React.Component {\n constructor() {\n super()\n this.state = {\n tabIndex: 0,\n transform: {\n x: 0,\n y: 0,\n },\n }\n this.isDragging = false\n this.calloutRef = React.createRef()\n this.analyticsTracked = false\n }\n\n componentDidMount() {\n const { transform } = this.props\n setTimeout(() => this.setState({ transform }), 0)\n }\n\n componentDidUpdate() {\n const { open, mapContainerRef } = this.props\n\n if (open && mapContainerRef.current) {\n mapContainerRef.current.addEventListener(\n 'mousedown',\n this.handleMouseDown\n )\n mapContainerRef.current.addEventListener(\n 'mousemove',\n this.handleMouseMove\n )\n mapContainerRef.current.addEventListener('mouseup', this.handleMouseUp)\n mapContainerRef.current.addEventListener('click', this.handleMouseUp)\n } else {\n this.removeListeners()\n }\n }\n\n componentWillUnmount() {\n this.removeListeners()\n }\n\n removeListeners = () => {\n const { mapContainerRef } = this.props\n if (mapContainerRef.current) {\n mapContainerRef.current.removeEventListener(\n 'mousedown',\n this.handleMouseDown\n )\n mapContainerRef.current.removeEventListener(\n 'mousemove',\n this.handleMouseMove\n )\n mapContainerRef.current.removeEventListener('mouseup', this.handleMouseUp)\n mapContainerRef.current.removeEventListener('click', this.handleMouseUp)\n }\n }\n\n handleMouseDown = () => {\n this.isDragging = false\n }\n\n handleMouseUp = (e) => {\n if (!this.isDragging) {\n const { onClose } = this.props\n if (!this.calloutRef.current.contains(e.target)) {\n onClose()\n }\n }\n }\n\n handleMouseMove = () => {\n this.isDragging = true\n }\n\n renderInner = (result, pricing) => {\n const {\n bookingAdventuresIndex,\n bucketListItemsIndex,\n onAddedToBucketList,\n onRemovedFromBucketList,\n open,\n source,\n filters,\n } = this.props\n\n const shouldDispatchAnalytics = open && this.analyticsTracked !== true\n\n switch (result.__typename) {\n case 'Listing':\n if (shouldDispatchAnalytics) {\n trackAccommodationViewed({\n listingId: result.id,\n source,\n })\n this.analyticsTracked = true\n }\n return (\n <>\n \n \n \n >\n )\n\n case 'StoryAdventure':\n if (shouldDispatchAnalytics) {\n trackAdventureViewed({\n adventureId: result.id,\n source,\n })\n this.analyticsTracked = true\n }\n return (\n \n \n \n )\n\n default:\n return result.__typename\n }\n }\n\n render() {\n const {\n data,\n loading,\n children,\n open,\n bucketListItemsIndex,\n onPopupInteractionStart,\n onPopupInteractionEnd,\n isOnBucketListRoute,\n bucketListId,\n source,\n filters,\n } = this.props\n const { transform, tabIndex } = this.state\n\n const { result: originalResult, pricing } = data?.search?.result ?? {\n result: {},\n }\n\n const filteredStories =\n isOnBucketListRoute && bucketListId && originalResult?.stories\n ? filterStoriesThatAreInCurrentBucketList({\n stories: originalResult.stories,\n bucketListId,\n bucketListItemsIndex,\n })\n : originalResult.stories\n\n const result = {\n ...originalResult,\n stories: filteredStories,\n }\n\n const showListing =\n isOnBucketListRoute && result.__typename === 'Listing'\n ? isListingInBucketList({\n listing: result,\n bucketListItemsIndex,\n bucketListId,\n })\n : true\n\n const hasManyResults = result && result.stories && result.stories.length > 0\n\n return (\n \n \n \n {children}\n
\n {(loading || !result) && }\n {!loading && result && (\n \n {hasManyResults ? (\n \n this.setState({ tabIndex: index })\n }\n listing={{\n ...result,\n pricing,\n url: formatUrlWithFilters(filters, result.url),\n }}\n latestStory={{\n ...result.stories[0],\n url: formatUrlWithFilters(\n filters,\n result.stories[0].url\n ),\n }}\n bucketListItemsIndex={bucketListItemsIndex}\n showListing={showListing}\n source={source}\n />\n ) : (\n this.renderInner(result, pricing)\n )}\n
\n )}\n \n
\n \n \n )\n }\n}\n\nconst MarkerCalloutWithData = (props) => {\n const { id, open, filters, type } = props\n\n const params = {\n ...filters,\n }\n /*\n The mapMarkerCallout query is scoped to `search`, which expects a value for\n the top-level `type` property of either 'accommodation' or 'adventures' -- on the search page this is\n always present because it's toggled between accom and adventures. On the bucket\n list page, both need to be displayed at the same time. Therefore, we derive the high-level\n `type` value from the `type` of the MapResult itself.\n */\n if (!filters.type) {\n params.type = type === 'Adventure' ? 'adventures' : 'accommodation'\n }\n\n const { data, loading } = useMapMarkerCalloutQuery({\n variables: { params, type, id },\n skip: !open,\n })\n\n const propsWithData = {\n ...props,\n data,\n loading,\n params,\n }\n\n return \n}\n\nexport default withRouter(\n connect(({ router }, { match }) => ({\n filters: deserializeSearchQuery(router.location.search),\n isOnBucketListRoute: router.location.pathname.includes('bucketlist'),\n bucketListId: match.params.id,\n }))(MarkerCalloutWithData)\n)\n","export type SetNavbarStickyAction = {\n type: 'SET_NAVBAR_STICKY'\n sticky: boolean\n}\n\nexport const setNavbarSticky = (sticky: boolean): SetNavbarStickyAction => {\n return {\n type: 'SET_NAVBAR_STICKY',\n sticky,\n }\n}\n","import { useEffect, useRef } from 'react'\n\nimport useDispatch from 'hooks/useDispatch'\nimport useReduxSelector from 'hooks/useReduxSelector'\nimport { setNavbarSticky } from 'actions/navbarActions'\n\nconst useStickyNavbar = (sticky: boolean) => {\n const dispatch = useDispatch()\n const currentStateValue = useReduxSelector((state) => state?.navbar?.sticky)\n const initialValue = useRef(currentStateValue)\n\n const setNew = () => {\n dispatch(setNavbarSticky(sticky))\n }\n\n const restoreInitial = () => {\n dispatch(setNavbarSticky(initialValue.current))\n }\n\n useEffect(() => {\n setNew()\n\n return restoreInitial\n }, [])\n}\n\nexport default useStickyNavbar\n","import React, { useMemo, useState } from 'react'\nimport { connect } from 'react-redux'\nimport debounce from 'lodash/debounce'\n\nimport { updateFilters } from '../../../actions/searchActions'\nimport CrossOutIcon from '../../../components/icons/CrossOut'\n\nimport CommonMultiSelectFilter from '../common/MultiSelectFilter'\n\nimport { FilterPanel, CloseButton, PanelHeader } from './shared'\n\nimport FilterPanelActions from './FilterPanelActions'\n\ntype FilterKey = keyof GQL_SearchFilters\n\ninterface MultiSelectFilterPanelProps {\n filterKey: FilterKey\n possibleFilters:\n | GQL_Region[]\n | GQL_AdventureType[]\n | Array<{\n slug: string\n name: string\n }>\n selectedFiltersSlugs: Array\n onClose: (...args: any) => any\n update: (...args: any) => any\n heading: string\n open?: boolean\n noTruncate?: boolean\n resultsCount?: number\n updateDebounceMs?: number\n}\n\nconst MultiSelectFilter = ({\n filterKey,\n possibleFilters = [],\n selectedFiltersSlugs: initialSelectedFiltersSlugs = [],\n onClose,\n update,\n heading,\n open,\n noTruncate,\n resultsCount,\n updateDebounceMs = 500,\n}: MultiSelectFilterPanelProps) => {\n const [showResultCount, setShowResultCount] = useState(true)\n const debouncedUpdate = useMemo(\n () =>\n debounce((nextFilters: GQL_SearchFilters) => {\n update(nextFilters)\n setShowResultCount(true)\n }, updateDebounceMs),\n [update]\n )\n\n const [selectedFiltersSlugs, setSelectedFiltersSlugs] = useState(\n initialSelectedFiltersSlugs\n )\n\n const handleClosePanel = () => {\n onClose()\n }\n\n const handleApply = () => {\n window.scrollTo(0, 0)\n handleClosePanel()\n }\n\n const handleResetFilters = () => {\n update({ [filterKey]: null })\n setSelectedFiltersSlugs([])\n window.scrollTo(0, 0)\n onClose()\n }\n\n const handleSelectionChange = (nextFilters: GQL_SearchFilters) => {\n setSelectedFiltersSlugs(nextFilters[filterKey])\n setShowResultCount(false)\n debouncedUpdate(nextFilters)\n }\n\n return (\n \n \n {heading}\n \n \n \n \n\n \n\n \n \n )\n}\n\nexport { MultiSelectFilter as MultiSelectFilterPanel }\n\nexport default connect(undefined, (dispatch) => ({\n // @ts-ignore -- updateFilters not typed yet\n update: (filters) => dispatch(updateFilters(filters)),\n}))(MultiSelectFilter)\n","import React, { useEffect, useMemo, useRef, useState } from 'react'\nimport { connect } from 'react-redux'\nimport pick from 'lodash/pick'\nimport debounce from 'lodash/debounce'\n\nimport { SearchQueryResult } from '../../../../hooks/useQueries'\nimport { updateFilters } from '../../../../actions/searchActions'\n\nimport CloseIcon from '../../../../components/icons/AirbnbClose'\n\nimport { FilterPanel, CloseButton, PanelHeader } from '../shared'\nimport { BOOKING_OPTIONS_FILTERS } from '../../common/BookingOptionsFilter'\n\nimport CommonMoreFilters from '../../common/MoreFilters'\n\nimport FilterPanelActions from '../FilterPanelActions'\n\nconst clearedFilters: GQL_SearchFilters = {\n regions: null,\n priceStart: null,\n priceEnd: null,\n subcategories: null,\n amenities: null,\n petFriendly: null,\n bedrooms: null,\n beds: null,\n}\nBOOKING_OPTIONS_FILTERS.forEach((key) => {\n clearedFilters[key] = null\n})\nObject.freeze(clearedFilters)\n\nconst selectFilters = (filters: Filters) => {\n return {\n ...clearedFilters,\n ...pick(filters, [\n 'regions',\n 'priceStart',\n 'priceEnd',\n 'subcategories',\n 'amenities',\n 'petFriendly',\n 'bedrooms',\n 'beds',\n ...BOOKING_OPTIONS_FILTERS,\n ]),\n }\n}\n\nconst usePriceBounds = (\n panelOpen: boolean,\n minPrice: number,\n maxPrice: number\n) => {\n const [priceBounds, setPriceBounds] = useState<[number, number]>()\n\n // update when panel is opened or closed\n useEffect(() => {\n setPriceBounds([minPrice, maxPrice])\n }, [panelOpen])\n\n // If has remained open then ignore the change in min/max price unless this is the first set of results\n // with a min/max value. This prevents the price slider range shifting with every drag of the price slider.\n useEffect(() => {\n if (priceBounds?.[0] == null || priceBounds?.[1] == null) {\n setPriceBounds([minPrice, maxPrice])\n }\n }, [minPrice, maxPrice])\n\n return priceBounds\n}\n\ntype Filters = Omit & {\n state?: string\n}\n\nconst useFiltersState = (filters: Filters) => {\n const filtersHaveUpdatedOnce = useRef(false)\n const [state, setState] = useState(selectFilters(filters))\n\n useEffect(() => {\n if (filtersHaveUpdatedOnce.current === false) {\n setState(selectFilters(filters))\n filtersHaveUpdatedOnce.current = true\n }\n }, [filters])\n\n return [state, setState] as const\n}\n\ntype MoreFiltersProps = {\n open: boolean\n filters: Filters\n defaults: SearchQueryResult['data']['search']['defaults']\n minPrice: number\n maxPrice: number\n update: (_filters: Filters) => void\n onClose: () => any\n includeRegionsFilter?: boolean\n resultsCount?: number\n updateDebounceMs?: number\n}\n\nconst MoreFilters = ({\n filters,\n open,\n defaults,\n includeRegionsFilter,\n minPrice,\n maxPrice,\n onClose,\n update,\n resultsCount,\n updateDebounceMs = 500,\n}: MoreFiltersProps) => {\n const [showResultCount, setShowResultCount] = useState(true)\n const debouncedUpdate = useMemo(\n () =>\n debounce((nextFilters: Filters) => {\n update(nextFilters)\n setShowResultCount(true)\n }, updateDebounceMs),\n [update]\n )\n\n const scrollContainer = useRef()\n\n const [state, setState] = useFiltersState(filters)\n\n const priceBounds = usePriceBounds(open, minPrice, maxPrice)\n\n const handleFiltersChange = (changes: Partial) => {\n const nextFilters = {\n ...state,\n ...changes,\n }\n setState(nextFilters)\n setShowResultCount(false)\n debouncedUpdate(nextFilters)\n }\n\n const handlePriceRangeChange = ([priceStart, priceEnd]: [number, number]) => {\n const nextFilters = {\n ...state,\n priceStart: priceStart >= minPrice ? priceStart : null,\n priceEnd: priceEnd <= maxPrice ? priceEnd : null,\n }\n handleFiltersChange(nextFilters)\n }\n\n const resetScroll = () => {\n scrollContainer.current.scrollTo(0, 0)\n }\n\n const handleClosePanel = () => {\n resetScroll()\n onClose()\n }\n\n const handleApply = () => {\n handleClosePanel()\n }\n\n const handleResetFilters = () => {\n const nextFilters = {\n ...filters,\n ...clearedFilters,\n }\n debouncedUpdate(nextFilters)\n setState({ ...clearedFilters })\n onClose()\n }\n\n const {\n petFriendly,\n regions,\n priceStart,\n priceEnd,\n subcategories,\n amenities,\n bedrooms,\n beds,\n fullRefund,\n instantBook,\n oneNightStayWeekday,\n oneNightStayWeekend,\n } = selectFilters(state)\n\n return (\n \n \n \n \n \n Filters\n \n\n \n\n \n \n )\n}\n\nexport { MoreFilters }\n\nexport default connect(undefined, (dispatch) => ({\n update: (filters: Filters) =>\n dispatch(\n // @ts-ignore -- not typed yet\n updateFilters(filters)\n ),\n}))(MoreFilters)\n","/* eslint-disable import/no-named-as-default */\nimport React, { useEffect, useState } from 'react'\nimport moment from 'moment'\nimport styled from 'styled-components'\n\nimport useDispatch from 'hooks/useDispatch'\nimport useIsServerSide from '../hooks/useIsServerSideContext'\nimport { SearchQueryResult } from '../hooks/useQueries'\nimport { disallowedFiltersForType } from '../actions/searchActions'\nimport { setListingsMobileFilterViewState } from '../actions/viewstateActions'\n\nimport useStickyNavbar from '../layout/Navbar/useStickyNavbar'\nimport LockBodyScroll from '../components/display/LockBodyScroll'\nimport FadeIn from '../components/display/FadeIn'\nimport FiltersIcon from '../components/icons/Filters'\nimport {\n Outerwrapper,\n MobileSearchViewWrapper,\n StickyMobileFilters,\n MobileFiltersOuter,\n MobileFiltersInner,\n ResultsWrapper,\n MapWrapper,\n} from '../components/layout/ItemGridWithMap/Mobile'\n\nimport DatesFilter from './filters/mobile/DatesFilter'\nimport MultiSelectFilter from './filters/mobile/MultiSelectFilter'\nimport PeopleFilterPanel from './filters/mobile/PeopleFilter'\nimport MoreFilters from './filters/mobile/MoreFilters'\nimport MobileViewToggle from './filters/mobile/MobileViewToggle'\n\nconst FilterSpacer = styled.div`\n width: 8px;\n height: 16px;\n`\n\ntype FilterButtonProps = {\n active?: boolean\n}\n\nexport const MobileFilterButton = styled.button`\n display: flex;\n align-items: center;\n padding: 0.666em 0.8333em;\n\n font-size: 12px;\n\n border-radius: 6px;\n background-color: white;\n border: 1px solid #d5d5d5;\n\n svg {\n width: 13px;\n height: 11px;\n margin-right: 4px;\n }\n\n ${({ active, theme }) =>\n active &&\n `\n color: white;\n background-color: ${theme.brand.jungle};\n border: none;\n `}\n`\n\nconst getDatesLabel = (filters: GQL_SearchFilters) => {\n const { startDate, endDate, weekendMonths } = filters\n if (weekendMonths?.length > 0 && startDate == null && endDate == null) {\n return 'Available weekends'\n }\n const formatDate = (d: string) => moment(d).format('DD MMM')\n const fomattedStart = startDate ? formatDate(startDate) : 'Start'\n const fomattedEnd = endDate ? formatDate(endDate) : 'End'\n return startDate || endDate ? `${fomattedStart} - ${fomattedEnd}` : 'Dates'\n}\n\nconst getPeopleLabel = (filters: GQL_SearchFilters) => {\n const people = {\n adults: filters.adults || 0,\n children: filters.children || 0,\n }\n const numberOfPeople = Object.values(people).reduce((a, b) => a + b, 0)\n if (numberOfPeople > 0) {\n return `${numberOfPeople} ${numberOfPeople > 1 ? 'People' : 'Person'}`\n }\n return 'People'\n}\n\ntype DisallowedFilters = {\n [key in keyof GQL_SearchFilters]: true\n}\n\ninterface SearchViewProps {\n filters: GQL_SearchFilters\n defaults: SearchQueryResult['data']['search']['defaults']\n minPrice: number\n maxPrice: number\n resultsComponent: React.ReactNode\n mapComponent: React.ReactNode\n searchTypeToggleComponent: React.ReactNode\n resultsCount?: number\n}\n\nconst MobileSearchView = ({\n filters,\n defaults,\n minPrice,\n maxPrice,\n resultsComponent,\n mapComponent,\n searchTypeToggleComponent,\n resultsCount,\n}: SearchViewProps) => {\n const dispatch = useDispatch()\n const isServerSide = useIsServerSide()\n const [hasToggledView, setHasToggledView] = useState(false)\n const [showMap, setShowMap] = useState(false)\n const [openPanel, setOpenPanel] = useState(null)\n\n useStickyNavbar(true)\n\n useEffect(() => {\n let $header: Element\n if (!isServerSide) {\n $header = document.querySelector('.app-header')\n $header?.classList?.add('sticky')\n }\n\n return () => {\n if ($header?.classList?.remove) {\n $header?.classList?.remove('sticky')\n }\n }\n }, [])\n\n const handleOpenRegionsFilter = () => setOpenPanel('regions')\n const handleOpenDatesFilter = () => setOpenPanel('dates')\n const handleOpenPeopleFilter = () => setOpenPanel('people')\n const handleOpenAdventureTypesFilter = () => setOpenPanel('adventureTypes')\n const handleOpenMoreFilters = () => setOpenPanel('more')\n\n const handleClosePanel = () => setOpenPanel(null)\n\n const handleToggleView = () => {\n setHasToggledView(true)\n setShowMap(!showMap)\n dispatch(setListingsMobileFilterViewState(false))\n }\n\n const currentSearchType = filters.type\n const disallowedFiltersKeys: string[] =\n disallowedFiltersForType[currentSearchType] ?? []\n const disallowedFiltersDict = disallowedFiltersKeys.reduce(\n (acc, filterKey) => {\n return {\n ...acc,\n [filterKey]: true,\n }\n },\n {} as DisallowedFilters\n )\n\n const regionsFilterAsPrimary =\n currentSearchType === 'adventures' &&\n filters?.country != null &&\n filters?.state != null\n\n /**\n * We need to count filters that are active but group them by how they are\n * represented visually\n */\n const activeSecondaryFilters = [\n regionsFilterAsPrimary !== true && filters.regions,\n filters.priceStart || filters.priceEnd,\n filters.subcategories,\n filters.amenities,\n filters.petFriendly,\n filters.bedrooms,\n filters.beds,\n filters.instantBook,\n filters.fullRefund,\n filters.oneNightStayWeekday,\n filters.oneNightStayWeekend,\n ].filter((v) => !!v)\n\n const dateFilterAllowed =\n !disallowedFiltersDict.startDate && !disallowedFiltersDict.endDate\n const peopleFilterAllowed = !disallowedFiltersDict.adults\n\n const filtersBar = (\n \n \n {searchTypeToggleComponent}\n {regionsFilterAsPrimary && (\n \n Regions\n \n )}\n {dateFilterAllowed && (\n \n {getDatesLabel(filters)}\n \n )}\n {peopleFilterAllowed && (\n \n {getPeopleLabel(filters)}\n \n )}\n {currentSearchType === 'adventures' && (\n \n Adventure Type\n \n )}\n {currentSearchType !== 'adventures' && (\n 0}\n data-testid=\"more-filters\"\n >\n \n Filters\n {activeSecondaryFilters.length > 0 &&\n ` (${activeSecondaryFilters.length})`}\n \n )}\n \n \n \n )\n\n return (\n \n \n {(showMap || openPanel) && }\n\n {showMap ? (\n // placeholder to avoid layout shift; hardcoded to the effective height of filters bar for now\n \n ) : (\n {filtersBar}\n )}\n\n \n {resultsComponent}\n \n\n {hasToggledView && (\n \n {showMap && filtersBar}\n \n {mapComponent}\n \n \n )}\n\n \n \n\n \n\n \n\n \n\n \n\n \n \n )\n}\n\nexport default MobileSearchView\n","export function setListingsMobileFilterViewState(payload) {\n return (dispatch) => {\n dispatch({\n type: 'SET_LISTINGS_MOBILE_FILTER_VIEW_STATE',\n payload,\n })\n }\n}\n\nexport function setListingMobileBookingEnquiryFormViewState(payload) {\n return (dispatch) => {\n dispatch({\n type: 'SET_LISTING_MOBILE_BOOKING_ENQUIRY_FORM_VIEW_STATE',\n payload,\n })\n }\n}\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport { media } from 'styles/media'\n\nimport SvgIconCalendar from 'components/icons/CalendarBookingsDetailed'\nimport SvgIconCheckCircle from 'components/icons/CheckCircle'\nimport { ParagraphSm } from 'components/display/Typography'\nimport { Hint } from 'components/form'\n\ntype Option = {\n label: string\n value: string\n}\n\nconst CheckIconWrapper = styled.div<{ $checked: boolean }>`\n width: 22px;\n height: 22px;\n position: absolute;\n top: 8px;\n right: 8px;\n\n svg {\n width: 22px;\n height: 22px;\n color: ${({ theme, $checked }) =>\n $checked\n ? theme?.['-ds-core-400']?.value\n : theme?.['-ds-neutral-300']?.value};\n }\n\n ${media.md`\n position: relative;\n margin-left: auto;\n margin-left: 0;\n margin-top: 16px;\n top: unset;\n right: unset;\n `}\n`\n\nconst CalendarIconWrapper = styled.div`\n display: none;\n\n ${media.md`\n display: block;\n width: 30px;\n height: 28px;\n margin: 0 0 10px 0;\n\n svg {\n width: 30px;\n height: 28px;\n margin: 0;\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n }\n `}\n`\n\nconst Options = styled.div`\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-gap: 16px;\n\n margin-top: 24px;\n\n input[type='checkbox'] {\n position: absolute;\n visibility: hidden;\n }\n\n input[type='checkbox'] + label {\n border: 1px solid ${({ theme }) => theme?.['-ds-neutral-300']?.value};\n }\n\n input[type='checkbox']:checked + label {\n border: 1px solid ${({ theme }) => theme?.['-ds-core-400']?.value};\n background-color: ${({ theme }) => theme?.['-ds-success-100']?.value};\n }\n\n ${media.md`\n grid-template-columns: 1fr 1fr 1fr 1fr 1fr;\n `}\n`\n\nconst MonthWrapper = styled.div``\n\nconst MonthLabel = styled.label`\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n position: relative;\n cursor: pointer;\n user-select: none;\n\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n font-weight: 400;\n padding: 16px;\n border-radius: 8px;\n\n ${media.md`\n flex-direction: column;\n text-align: center;\n align-items: center;\n `}\n`\n\ntype ChangeInput = { value: string; checked: boolean }\n\ntype Props = {\n selectedValues: string[]\n onChange: (_: ChangeInput) => any\n}\n\nconst AvailableWeekendsInput = ({ selectedValues, onChange }: Props) => {\n const options: Option[] = [...Array(5)].map((_, index) => {\n const now = new Date()\n const optionDate = new Date(now.setMonth(now.getMonth() + index))\n const month = optionDate.getMonth() + 1 // month starts at 0\n const twoDigitMonth = month.toString().padStart(2, '0')\n const year = optionDate.getFullYear()\n\n const label = new Intl.DateTimeFormat('en-us', {\n month: 'long',\n year: 'numeric',\n }).format(optionDate)\n\n return {\n label,\n value: `${year}-${twoDigitMonth}`,\n }\n })\n\n return (\n <>\n \n Find escapes with an available weekend in...\n \n \n Weekends are considered Friday to Sunday (2-night stay). Long weekends\n and holidays may have longer minimum stays, so use specific dates when\n booking for these periods.\n \n\n \n {options.map(({ label, value }) => {\n const checked = selectedValues.includes(value)\n return (\n \n \n onChange({\n checked: event.target.checked,\n value,\n })\n }\n checked={checked}\n />\n \n \n \n \n\n \n {label.split(' ').map((word) => (\n
\n {word}\n
\n ))}\n
\n\n \n \n \n \n \n )\n })}\n \n >\n )\n}\n\nexport default AvailableWeekendsInput\n","import React, { useEffect, useState } from 'react'\nimport styled from 'styled-components'\n\nimport { mediaMax } from 'styles/media'\n\nimport FilterButton from '../desktop/FilterButton'\nimport { Label, CheckboxToggle } from '../../../components/form'\n\ntype BookingOptionValues = {\n instantBook?: boolean\n fullRefund?: boolean\n oneNightStayWeekday?: boolean\n oneNightStayWeekend?: boolean\n}\n\nexport const BOOKING_OPTIONS_FILTERS: (keyof BookingOptionValues)[] = [\n 'instantBook',\n 'fullRefund',\n 'oneNightStayWeekday',\n 'oneNightStayWeekend',\n]\n\nconst BookingOptionsPopupContents = styled.div`\n max-width: 360px;\n`\n\nconst BookingOptionToggleLabel = styled(Label)`\n cursor: pointer;\n overflow: auto;\n margin-bottom: 10px;\n\n & + & {\n margin-top: 26px;\n }\n\n > span {\n float: left;\n padding-right: 3.5em;\n\n > .description {\n display: block;\n font-size: 16px;\n font-weight: 300;\n color: #999;\n }\n }\n\n > .toggle-checkbox {\n margin-left: auto;\n }\n\n ${mediaMax.md`\n overflow: hidden;\n `}\n`\n\ntype BookingOptionToggleProps = {\n id: string\n name?: string\n label: string\n description: React.ReactNode\n isChecked?: boolean\n onChange: (isChecked: boolean) => void\n}\nconst BookingOptionToggle = ({\n id,\n name,\n label,\n description,\n isChecked,\n onChange,\n}: BookingOptionToggleProps) => (\n \n \n {label}\n {description}\n \n onChange(e.target.checked)}\n style={{ marginTop: '0.1em' }}\n />\n \n)\n\ntype BookingOptionsProps = {\n showOneNightStayOptions: boolean\n values: BookingOptionValues\n onChange: (nextFilters: BookingOptionValues) => void\n}\n\nexport const BookingOptions = ({\n showOneNightStayOptions,\n values,\n onChange,\n}: BookingOptionsProps) => {\n return (\n <>\n onChange({ instantBook: isChecked })}\n />\n onChange({ fullRefund: isChecked })}\n />\n {showOneNightStayOptions && (\n <>\n \n onChange({ oneNightStayWeekday: isChecked })\n }\n />\n \n onChange({ oneNightStayWeekend: isChecked })\n }\n />\n >\n )}\n >\n )\n}\n\ntype BookingOptionsFilterProps = BookingOptionsProps\n\nconst BookingOptionsFilter = ({\n showOneNightStayOptions,\n values,\n onChange,\n}: BookingOptionsFilterProps) => {\n const [state, setState] = useState(values)\n const activeFilters = Object.keys(values).length\n\n // Override state if values passed in via props changes:\n useEffect(() => setState(values), [values])\n\n const handleClear = () => {\n // Set all values to null so that the `onChange` handler knows to clear out\n // those values from the query string:\n const resetState: BookingOptionValues = {}\n BOOKING_OPTIONS_FILTERS.forEach((key) => {\n resetState[key] = null\n })\n\n setState(resetState)\n onChange(resetState)\n }\n\n const handleChange = (changes: BookingOptionValues) => {\n setState({ ...state, ...changes })\n }\n\n return (\n 0 ? activeFilters.toString() : null}\n isActive={activeFilters > 0}\n onApply={() => onChange(state)}\n onClear={handleClear}\n onReset={() => setState(values)}\n >\n \n \n \n \n )\n}\n\nexport default BookingOptionsFilter\n","import React, { useState, useEffect } from 'react'\nimport styled from 'styled-components'\n\nimport { mediaMax } from 'styles/media'\nimport FilterButton from '../desktop/FilterButton'\nimport QuantitySelect from './QuantitySelect'\n\ntype RoomsAndBedsFilters = {\n bedrooms?: number\n beds?: number\n}\n\ntype RoomsAndBedsProps = {\n values: RoomsAndBedsFilters\n onChange: (nextFilters: RoomsAndBedsFilters) => void\n}\n\nconst RoomsAndBedsWrapper = styled.div`\n ${mediaMax.xl`\n margin-bottom: 14px;\n `}\n`\n\nexport const RoomsAndBeds = ({ values, onChange }: RoomsAndBedsProps) => {\n return (\n \n onChange({ bedrooms: count })}\n />\n onChange({ beds: count })}\n />\n \n )\n}\n\ntype RoomsAndBedsFilterProps = RoomsAndBedsProps\n\nconst RoomsAndBedsFilter = ({ values, onChange }: RoomsAndBedsFilterProps) => {\n const [state, setState] = useState(values)\n const activeFilters = Object.keys(values).length\n\n // Override state if values passed in via props changes:\n useEffect(() => setState(values), [values])\n\n const handleClear = () => {\n // Set all values to null so that the `onChange` handler knows to clear out\n // those values from the query string:\n const resetState: RoomsAndBedsFilters = {\n bedrooms: null,\n beds: null,\n }\n\n setState(resetState)\n onChange(resetState)\n }\n\n const handleChange = (changes: RoomsAndBedsFilters) => {\n setState({ ...state, ...changes })\n }\n\n return (\n 0 ? activeFilters.toString() : null}\n isActive={activeFilters > 0}\n onApply={() => onChange(state)}\n onClear={handleClear}\n onReset={() => setState(values)}\n >\n \n \n )\n}\n\nexport default RoomsAndBedsFilter\n","import React, { useEffect, useMemo, useState } from 'react'\nimport styled from 'styled-components'\nimport Slider from 'rc-slider'\nimport debounce from 'lodash/debounce'\n\nimport { formatPrice } from '../../../../components/utils/pricing'\nimport styledTheme from '../../../../styles/theme'\n\nconst RangeWrapper = styled.div`\n padding-left: 20px;\n margin-bottom: 20px;\n`\n\nconst LabelWrapper = styled.div`\n display: flex;\n justify-content: space-between;\n margin-bottom: 10px;\n`\n\nconst Label = styled.div`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n line-height: 1.4;\n`\n\nconst handleStyle = {\n borderColor: styledTheme.brand.jungle,\n height: 20,\n width: 20,\n marginLeft: -10,\n marginTop: -8,\n backgroundColor: 'white',\n}\n\ntype TransformCurve = 'logarithmic' | 'linear'\n\nconst transformIn = (value: number, curve: TransformCurve) => {\n if (value === 0) {\n return 0\n }\n\n if (curve === 'logarithmic') {\n return Math.log(value)\n }\n\n return value\n}\n\nconst transformOut = (value: number, curve: TransformCurve) => {\n if (value === 0) {\n return 0\n }\n\n if (curve === 'logarithmic') {\n return Math.exp(value)\n }\n\n return value\n}\n\ntype PriceRangeProps = {\n initialPriceStart: number\n initialPriceEnd: number\n minPrice: number\n maxPrice: number\n onChange: (_: [number, number]) => any\n transformCurve?: TransformCurve\n}\n\ntype Value = [number, number]\n\nexport const BasePriceRange = ({\n onChange,\n minPrice,\n maxPrice,\n initialPriceStart,\n initialPriceEnd,\n transformCurve = 'logarithmic',\n}: PriceRangeProps) => {\n const [value, setValue] = useState([minPrice, maxPrice])\n\n useEffect(() => {\n setValue([initialPriceStart, initialPriceEnd])\n }, [initialPriceStart, initialPriceEnd])\n\n const debouncedOnChange = useMemo(() => debounce(onChange, 200), [onChange])\n\n const handleOnAfterChange = ([start, end]: Value) => {\n const nextStart = transformOut(start, transformCurve)\n const nextEnd = transformOut(end, transformCurve)\n\n if (nextStart != null && nextEnd != null) {\n debouncedOnChange([Math.round(nextStart), Math.round(nextEnd)])\n }\n }\n\n const handleChange = ([start, end]: Value) => {\n const nextStart = transformOut(start, transformCurve)\n const nextEnd = transformOut(end, transformCurve)\n\n setValue([nextStart, nextEnd])\n }\n\n return (\n \n \n \n \n \n\n {minPrice != null && maxPrice != null && (\n \n \n \n )}\n
\n )\n}\n\nexport default BasePriceRange\n","import partition from 'lodash/partition'\n\ntype SluggedDatum = { slug: string }\n\nexport const orderBySlug = (\n sluggedData: readonly T[] = [],\n topSlugs: readonly string[]\n): T[] => {\n const [top, rest] = partition(sluggedData, ({ slug }) =>\n topSlugs.includes(slug)\n )\n\n const orderedTop = topSlugs.reduce((acc, slug) => {\n const matching = top.find((datum) => datum.slug === slug)\n\n if (!matching) {\n return acc\n }\n\n return [...acc, matching]\n }, [] as typeof sluggedData)\n\n return [...orderedTop, ...rest]\n}\n\nexport const getPriceTitle = (filters: GQL_SearchFilters) => {\n if (\n (filters.startDate && filters.endDate) ||\n filters.weekendMonths?.length > 0\n ) {\n return 'Total price'\n }\n\n switch (filters.type) {\n case 'accommodation':\n return 'Price per night'\n case 'experiences':\n return 'Price per person'\n default:\n return 'Price per day'\n }\n}\n","import React from 'react'\nimport styled from 'styled-components'\n\nimport pluralize from 'pluralize'\n\nimport { SearchQueryResult } from '../../../hooks/useQueries'\nimport { CheckboxToggle } from '../../../components/form'\nimport {\n searchTypes,\n disallowedFiltersForType,\n} from '../../../actions/searchActions'\n\nimport { BOOKING_OPTIONS_FILTERS, BookingOptions } from './BookingOptionsFilter'\nimport { RoomsAndBeds } from './RoomsAndBedsFilter'\nimport PriceRange from './PriceRange'\nimport MultiSelectFilter from './MultiSelectFilter'\n\nimport { getPriceTitle, orderBySlug } from './helpers'\n\nconst FilterGroup = styled.div`\n padding: 24px 0;\n border-bottom: 1px solid ${({ theme }) => theme?.['-ds-neutral-300']?.value};\n`\n\nconst Label = styled.label`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n color: ${({ theme }) => theme?.['-ds-neutral-500']?.value};\n font-weight: 300;\n line-height: 1.4;\n`\n\nconst Count = styled.div`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xxs']?.['font-size']?.value};\n line-height: 1.4;\n font-weight: 400;\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n background-color: ${({ theme }) => theme?.['-ds-success-100']?.value};\n border-radius: 80px;\n display: inline-block;\n padding: 4px 10px;\n margin-left: 16px;\n position: absolute;\n top: -2px;\n`\n\nconst GroupTitle = styled.h4`\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-md']?.['font-size']?.value};\n position: relative;\n margin-bottom: 24px;\n`\n\nconst ContentWrapper = styled.div`\n padding: 0;\n`\nconst topSubcategoriesSlugs = [\n 'tiny-house',\n 'cabin',\n 'cottage',\n 'treehouse',\n 'beach-shack',\n 'farm',\n] as const\n\nconst topAmenitiesSlugs = [\n 'outdoor-shower-bath',\n 'hot-tub',\n 'indoor-fireplace',\n 'bath',\n 'outdoor-fireplace',\n 'wifi',\n] as const\n\ntype Filters = Omit & {\n state?: string\n}\n\ntype MoreFiltersProps = {\n appliedFilters: Filters\n defaults: SearchQueryResult['data']['search']['defaults']\n includeRegionsFilter?: boolean\n filterValuesState: Partial<{\n petFriendly: boolean\n regions: string[]\n priceStart: number\n priceEnd: number\n priceBounds: [number, number]\n subcategories: string[]\n amenities: string[]\n bedrooms: number\n beds: number\n fullRefund: boolean\n instantBook: boolean\n oneNightStayWeekday: boolean\n oneNightStayWeekend: boolean\n }>\n handleFiltersChange: (_: Filters) => any\n handlePriceRangeChange: (_: [number, number]) => any\n}\n\nconst MoreFilters = ({\n appliedFilters,\n defaults,\n includeRegionsFilter,\n handleFiltersChange,\n handlePriceRangeChange,\n filterValuesState: {\n petFriendly,\n regions,\n priceBounds,\n priceStart,\n priceEnd,\n subcategories,\n amenities,\n bedrooms,\n beds,\n fullRefund,\n instantBook,\n oneNightStayWeekday,\n oneNightStayWeekend,\n },\n}: MoreFiltersProps) => {\n const disallowedFilters = disallowedFiltersForType[appliedFilters.type]\n\n const currentType = searchTypes.find(\n (type) => type.slug === appliedFilters.type\n )\n\n const orderedSubcategories = orderBySlug(\n defaults?.subcategories,\n topSubcategoriesSlugs\n )\n const orderedAmenities = orderBySlug(defaults?.amenities, topAmenitiesSlugs)\n\n return (\n <>\n {disallowedFilters && !disallowedFilters.includes('petFriendly') && (\n \n {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}\n \n \n \n )}\n\n {disallowedFilters && !disallowedFilters.includes('priceRange') && (\n \n {getPriceTitle(appliedFilters)}\n \n \n \n \n )}\n\n {includeRegionsFilter &&\n appliedFilters.state &&\n appliedFilters.state !== 'all' && (\n \n \n Regions\n {regions?.length > 0 && {regions.length}}\n \n \n \n \n \n )}\n\n {disallowedFilters &&\n !disallowedFilters.includes('amenities') &&\n defaults && (\n \n \n Amenities\n {amenities?.length > 0 && {amenities.length}}\n \n \n \n \n \n )}\n\n {currentType && !disallowedFilters.includes('subcategories') && defaults && (\n \n \n {`${pluralize(currentType.name, 1)} type`}\n {subcategories?.length > 0 && {subcategories.length}}\n \n \n \n \n \n )}\n\n {!disallowedFilters?.includes('roomsAndBeds') && (\n \n Rooms and beds\n \n \n \n \n )}\n\n {!BOOKING_OPTIONS_FILTERS.every((filter) =>\n disallowedFilters?.includes(filter)\n ) && (\n \n Booking options\n \n \n \n \n )}\n >\n )\n}\n\nexport default MoreFilters\n","import styled from 'styled-components'\n\nconst ThemedCheckbox = styled.input.attrs({ type: 'checkbox' })`\n appearance: none;\n background-color: transparent;\n margin: 2px 0 0 !important; /* shared checkbox styles from rails asset pipeline clash with this property */\n\n font: inherit;\n height: 20px;\n width: 20px;\n border: 2px solid ${({ theme }) => theme?.['-ds-neutral-600']?.value};\n transform: translateY(\n -1px\n ); /* move upwards by half the width of the border */\n border-radius: 3px;\n\n flex-shrink: 0;\n display: grid;\n place-content: center;\n\n &:checked {\n background-color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n border-color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n }\n\n &::before {\n content: '';\n width: 10px;\n height: 10px;\n transform: scale(0); /* invisible */\n transition: 120ms transform ease-in-out;\n box-shadow: inset 20px 20px\n ${({ theme }) => theme?.['-ds-neutral-100']?.value};\n transform-origin: bottom left;\n clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);\n }\n\n &:checked::before {\n transform: scale(1); /* visible */\n }\n\n &:focus {\n /* needs important tag to avoid clashing with bootstrap styles */\n outline: 2px solid !important;\n outline-offset: 3px !important;\n }\n`\n\nexport default ThemedCheckbox\n","import React, { useState } from 'react'\nimport styled from 'styled-components'\n\nimport InvisibleButton from 'components/display/InvisibleButton'\nimport ThemedCheckbox from 'components/form/ThemedCheckbox'\nimport CaretDownFilledIcon from 'components/icons/CaretDownFilled'\nimport CaretUpFilledIcon from 'components/icons/CaretUpFilled'\nimport useWhichMapMode from 'components/layout/ItemGridWithMap/useWhichMapMode'\n\nimport { FilterWrapper } from '../mobile/shared'\n\nconst Columns = styled.div`\n width: 100%;\n display: flex;\n flex-wrap: wrap;\n`\n\nconst CheckboxLabel = styled.label<{ $desktop: boolean }>`\n display: flex;\n flex-shrink: 0;\n padding-right: 16px;\n\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n color: ${({ theme }) => theme?.['-ds-neutral-700']?.value};\n font-weight: 300;\n line-height: 1.4;\n\n height: 48px;\n width: 50%;\n\n ${({ $desktop }) =>\n $desktop &&\n `\n width: 33%;\n min-width: 200px;\n `}\n\n span {\n margin-left: 14px;\n }\n`\n\ninterface SelectItemProps {\n label: string\n name: string\n onChange: () => any\n selected?: boolean\n}\n\nconst SelectItem = ({ label, name, onChange, selected }: SelectItemProps) => {\n const mapMode = useWhichMapMode()\n const inlineMapMode = mapMode === 'inline'\n\n return (\n \n \n {label}\n \n )\n}\n\nconst ShowToggle = styled(InvisibleButton)`\n color: ${({ theme }) => theme?.['-ds-core-400']?.value};\n font-size: ${({ theme }) =>\n theme?.['-ds-font-size-xs']?.['font-size']?.value};\n font-weight: 400;\n line-height: 1.4;\n display: flex;\n align-items: center;\n\n svg {\n flex-shrink: 0;\n width: 10px;\n height: 5px;\n margin-left: 16px;\n }\n`\n\nconst Show = styled(Columns)<{ $show: boolean }>`\n visibility: ${({ $show }) => ($show ? 'visible' : 'hidden')};\n height: ${({ $show }) => ($show ? 'unset' : '0px')};\n`\n\nexport const TRUNCATE_TO = 6 as const\nexport const TRUNCATE_IF_MORE_THAN = 10 as const\n\ninterface MultiSelectFilterProps {\n name: string\n values: string[]\n valueKey: keyof GQL_SearchFilters\n onChange: (_: Partial) => any\n items: Array<{\n slug: string\n name: string\n }>\n noTruncate?: boolean\n}\n\nconst MultiSelectFilter = ({\n name,\n values = [],\n valueKey,\n onChange,\n items,\n noTruncate,\n}: MultiSelectFilterProps) => {\n const [showRest, setShowRest] = useState(false)\n\n const toggleShowRest = () => setShowRest(!showRest)\n\n const onItemClick = (slug: string) => {\n const newValues = values.slice()\n const indexOfSlug = newValues.indexOf(slug)\n\n if (indexOfSlug > -1) {\n newValues.splice(indexOfSlug, 1)\n return onChange({ [valueKey]: newValues })\n }\n\n newValues.push(slug)\n return onChange({ [valueKey]: newValues })\n }\n\n const shouldTruncateItems =\n !noTruncate && items.length > TRUNCATE_IF_MORE_THAN\n\n const topItems = shouldTruncateItems ? items.slice(0, TRUNCATE_TO) : items\n const restItems = shouldTruncateItems ? items.slice(TRUNCATE_TO) : []\n\n return (\n \n \n {topItems.map((item) => (\n