@kiwicom/smart-faq
Version:
Smart FAQ
195 lines (175 loc) • 5.49 kB
JavaScript
// @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 { track } from '../shared/cuckoo/tracker';
import Tooltip from '../SmartFAQ/common/Tooltip/HoverHelpTooltip';
import type { Phone as PhoneType } from './__generated__/Phone.graphql';
const styles = css`
div.containerPhoneNumber {
display: flex;
align-items: center;
margin-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;
}
div.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 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';
} else {
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;
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,
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 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;')
: null;
return (
<div data-code={localeTerritory} className="containerPhoneNumber">
{flagCode &&
countryName && <CountryFlag code={flagCode} name={countryName} />}
<div dir="ltr" className="phoneNumber">
{phoneNumber && (
<a
href={`tel:${phoneNumber.replace(/\s/g, '')}`}
onClick={() =>
track('ContactForm', 'phoneClicked', { localeTerritory })
}
>
{parsedPhoneNumber}
</a>
)}
</div>
<div dir="ltr" style={{ cursor: 'pointer' }}>
<Tooltip content={availabilityInfo} placement="top">
<InformationCircle size="small" color="tertiary" />
</Tooltip>
</div>
<style>{styles}</style>
</div>
);
};
export default createFragmentContainer(
Phone,
graphql`
fragment Phone on CustomerSupportNumber {
number
countryName
localeTerritory
supportedLanguages {
language
languageCode
phoneLanguageAvailability {
type
... on CSPhoneAvailabilityWorkingDays {
from
to
}
}
}
}
`,
);