UNPKG

@kiwicom/smart-faq

Version:

219 lines (189 loc) 6.55 kB
// @flow import * as React from 'react'; import { graphql, createFragmentContainer } from 'react-relay'; import { parsePhoneNumber } from 'libphonenumber-js'; import ValueBind from '@kiwicom/nitro/lib/components/ValueBind'; import Stack from '@kiwicom/orbit-components/lib/Stack'; import TextLink from '@kiwicom/orbit-components/lib/TextLink'; import Tooltip from '@kiwicom/orbit-components/lib/Tooltip'; import CountryFlag from '@kiwicom/orbit-components/lib/CountryFlag'; import { CODES } from '@kiwicom/orbit-components/lib/CountryFlag/consts'; import InformationCircle from '@kiwicom/orbit-components/lib/icons/InformationCircle'; import LogContext from '@kiwicom/nitro/lib/services/log/context'; import type { Context as LogContextType } from '@kiwicom/nitro/lib/services/log/context'; import addMinutes from 'date-fns/add_minutes'; import type { Phone as PhoneType } from './__generated__/Phone.graphql'; import { events } from '../const/events'; type Props = {| data: PhoneType, |}; const formatTime = (datetime: Date) => `${datetime.getUTCHours() % 12}${ datetime.getUTCMinutes() > 0 ? `:${datetime.getUTCMinutes()}` : '' } ${datetime.getUTCHours() >= 12 ? 'pm' : 'am'}`; const parseUTCTimeToDate = (utcString: string) => { const hour = parseInt(utcString.split(':')[0], 10); const minute = parseInt(utcString.split(':')[1], 10); const now = new Date(); return new Date( Date.UTC(now.getFullYear(), now.getMonth(), now.getDay(), hour, minute), ); }; const convertToTimezone = addMinutes; const convertToLocalTimezone = (datetime: Date) => { // it's negative because the offset has to be subtracted return convertToTimezone(datetime, -new Date().getTimezoneOffset()); }; const getTimezone = () => { const offset = new Date().getTimezoneOffset(); const offsetHours = Math.floor(Math.abs(offset / 60)); const offsetMinutes = Math.abs(offset % 60); const formattedOffset = `${'00' .concat(offsetHours.toString()) .slice(-2)}:${'00'.concat(offsetMinutes.toString()).slice(-2)}`; if (offset > 0) { return `GMT-${formattedOffset}`; } else if (offset === 0) { return 'GMT'; } return `GMT+${formattedOffset}`; }; const formatOpenHours = (from: string, to: string): string => { const fromDate = convertToLocalTimezone(parseUTCTimeToDate(from)); const toDate = convertToLocalTimezone(parseUTCTimeToDate(to)); return `${formatTime(fromDate)}-${formatTime(toDate)} ${getTimezone()}`; }; const parseAvailabilityTimes = ( phoneLanguageAvailability, hasMultipleLanguages, language, ) => { const { type } = phoneLanguageAvailability; // TODO refactor to translations with variables if (type === 'NONSTOP') { return 'Support Available in '; } else if (type === 'WORKING_DAYS') { const { to, from } = phoneLanguageAvailability; if (to && from && language) { return `${ hasMultipleLanguages ? language : '' } Mon - Fri ${formatOpenHours(from, to)}; `; } } return ''; }; class Phone extends React.Component<Props> { context: LogContextType; static contextType = LogContext; handleClickPhone = () => { this.context.log(events.CS_PHONES_CLICKED, {}); }; render() { const { data } = this.props; const { number: phoneNumber, localeTerritory, labels, countryName, supportedLanguages, } = data; let parsedPhoneNumber; try { parsedPhoneNumber = parsePhoneNumber(phoneNumber).formatInternational(); } catch (e) { parsedPhoneNumber = phoneNumber; } const flagCode = localeTerritory && CODES[localeTerritory.toUpperCase()]; const hasMultipleLanguages = supportedLanguages && supportedLanguages.length > 1; const extraInfo = (labels && labels.join(' ')) ?? ''; const availabilityInfo = supportedLanguages ? supportedLanguages.reduce((acc, supportedLanguage) => { const language = supportedLanguage?.language; const languageAvailability = supportedLanguage?.phoneLanguageAvailability ?? {}; return ( `${parseAvailabilityTimes( languageAvailability, hasMultipleLanguages, language, )}` + acc ); }, 'English 24/7;') + extraInfo : null; // remove this nasty hardcoding of opening hours, when API is ready // https://skypicker.slack.com/archives/CBPS7LHFD/p1561475172003700 const getTooltipContent = () => { const frenchOpeningHours = 'Mon - Fri 8 am-8 pm, Sat - Sun 9 am-6 pm GMT+02:00;'; if (countryName === 'Canada French') { return `French ${frenchOpeningHours} English 24/7;`; } if (countryName === 'France') { return `${frenchOpeningHours} English 24/7;`; } if (countryName === 'Switzerland') { return `Italian Mon - Fri 8 am-8 pm GMT+02:00; French ${frenchOpeningHours} German Mon - Fri 9 am-5 pm GMT+02:00; English 24/7;`; } return availabilityInfo; }; return ( <Stack direction="row" spacing="condensed"> {flagCode && countryName && ( <CountryFlag code={flagCode} name={countryName} /> )} <div dir="ltr"> {parsedPhoneNumber && phoneNumber && localeTerritory && ( <div className="Phone"> <ValueBind value={localeTerritory} onChange={this.handleClickPhone} > {({ onClick }) => ( <TextLink href={`tel:${phoneNumber.replace(/\s/g, '')}`} onClick={onClick} > {parsedPhoneNumber ?? ''} </TextLink> )} </ValueBind> </div> )} </div> <div dir="ltr" style={{ cursor: 'pointer' }}> <Tooltip content={getTooltipContent()} preferredPosition="top" size="medium" > <InformationCircle size="small" color="tertiary" /> </Tooltip> </div> </Stack> ); } } export default createFragmentContainer( Phone, graphql` fragment Phone on CustomerSupportNumber { number labels countryName localeTerritory supportedLanguages { language languageCode phoneLanguageAvailability { type ... on CSPhoneAvailabilityWorkingDays { from to } } } } `, );