UNPKG

@kiwicom/smart-faq

Version:

Smart FAQ

187 lines (166 loc) 5.58 kB
// @flow import idx from 'idx'; import * as React from 'react'; import css from 'styled-jsx/css'; import { parsePhoneNumber } from 'libphonenumber-js'; import { CountryFlag } from '@kiwicom/orbit-components'; import { InformationCircle } from '@kiwicom/orbit-components/lib/icons'; import { graphql, createFragmentContainer } from 'react-relay'; import { CODES } from '@kiwicom/orbit-components/lib/CountryFlag/consts'; import addMinutes from 'date-fns/add_minutes'; import HoverHelpTooltip from '../SmartFAQ/common/Tooltip/HoverHelpTooltip'; import type { Phone as PhoneType } from './__generated__/Phone.graphql'; const styles = css` div.containerPhoneNumber { padding-bottom: 10px; } div.containerPhoneNumber :global(.Tooltip) { bottom: 110%; right: -100px; } div.containerPhoneNumber :global(.Tooltip-inner.Tooltip-inner) { max-width: 275px; width: 200px; } div.containerPhoneNumber :global(.HelpTooltip) { vertical-align: top; } span.phoneNumber { margin-left: 4px; margin-right: 4px; } a { color: #00ad98; text-decoration: none; font-family: 'Roboto', -apple-system, '.SFNSText-Regular', 'San Francisco', 'Segoe UI', 'Helvetica Neue', 'Lucida Grande', sans-serif; } `; type Props = {| data: PhoneType, |}; const getLocaleTimezoneAbbreviation = (dateInput: Date): ?string => { // extracts timezone abbreviation from stringified date using regexp // source: https://gist.github.com/redoPop/3915761 const dateString = dateInput.toString(); let shortTimezoneName = // Works for the majority of modern browsers dateString.match(/\(([^)]+)\)$/) || // IE outputs date strings in a different format: dateString.match(/([A-Z]+) [\d]{4}$/); if (shortTimezoneName) { // Old Firefox uses the long timezone name (e.g., "Central // Daylight Time" instead of "CDT") const matches = shortTimezoneName[1].match(/[A-Z]/g); if (matches) { shortTimezoneName = matches.join(''); } } if (shortTimezoneName) { return shortTimezoneName.toString(); } }; 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 formatOpenHours = (from: string, to: string): string => { const fromDate = convertToLocalTimezone(parseUTCTimeToDate(from)); const toDate = convertToLocalTimezone(parseUTCTimeToDate(to)); // fall back to long timezone name when shit hits the fan const timezoneName = getLocaleTimezoneAbbreviation(new Date()) || Intl.DateTimeFormat().resolvedOptions().timeZone || ''; return `${formatTime(fromDate)}-${formatTime(toDate)} ${timezoneName}`; }; const parseAvailabilityTimes = ( phoneLanguageAvailability, hasMultipleLanguages, language, ) => { const { type } = phoneLanguageAvailability; 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 ''; }; const Phone = ({ data }: Props) => { const { number: phoneNumber, localeTerritory, supportedLanguages } = data; const parsedPhoneNumber = parsePhoneNumber(phoneNumber).formatInternational(); const flagCode = localeTerritory && CODES[localeTerritory.toUpperCase()]; const hasMultipleLanguages = supportedLanguages && supportedLanguages.length > 1; const availabilityInfo = supportedLanguages && supportedLanguages.reduce((acc, supportedLanguage) => { const language = idx(supportedLanguage, _ => _.language); const languageAvailability = idx(supportedLanguage, _ => _.phoneLanguageAvailability) || {}; return ( `${parseAvailabilityTimes( languageAvailability, hasMultipleLanguages, language, )}` + acc ); }, 'English 24/7;'); return ( <div data-code={localeTerritory} className="containerPhoneNumber"> {flagCode && <CountryFlag code={flagCode} />} <span dir="ltr" className="phoneNumber"> {phoneNumber && ( <a href={`tel:${phoneNumber.replace(/\s/g, '')}`}> {parsedPhoneNumber} </a> )} </span> <span style={{ cursor: 'pointer' }}> <HoverHelpTooltip tooltip={availabilityInfo} placement="top"> <InformationCircle size="small" color="tertiary" /> </HoverHelpTooltip> </span> <style>{styles}</style> </div> ); }; export default createFragmentContainer( Phone, graphql` fragment Phone on CustomerSupportNumber { number localeTerritory supportedLanguages { language languageCode phoneLanguageAvailability { type ... on CSPhoneAvailabilityWorkingDays { from to } } } } `, );