@kiwicom/smart-faq
Version:
Smart FAQ
156 lines (133 loc) • 4.12 kB
JavaScript
// @flow
import * as React from 'react';
import classNames from 'classnames';
import { Prompt } from 'react-router-dom';
import { Consumer as IntlConsumer } from '@kiwicom/nitro/lib/services/intl/context';
import * as chatUtils from './utils';
import { simpleTracker } from '../helpers/analytics/trackers';
import type {
ChatConfig,
GuaranteeChatBookingInfo,
} from '../context/GuaranteeChatInfo';
import { GuaranteeChatInfoState } from '../context/GuaranteeChatInfo';
import { track } from '../cuckoo/tracker';
export type RenderButtonProps = {|
isChatReady: boolean,
onClickDisplayChat: () => void,
|};
type ContainerProps = {
withPrompt?: boolean,
eventSource: 'smartFAQ' | 'contactForm',
elementId: string,
children: (props: RenderButtonProps) => React.Node,
};
type Props = ContainerProps & {
guaranteeChatBookingInfo: ?GuaranteeChatBookingInfo,
chatConfig: ChatConfig,
onToggleIsClosable: boolean => void,
};
type State = {|
showButton: boolean,
isClosable: boolean,
isChatReady: boolean,
|};
class GuaranteeChatWrapper extends React.Component<Props, State> {
chatContainer: ?Element;
state = {
showButton: true,
isClosable: true,
isChatReady: false,
};
async componentDidMount() {
if (typeof window !== 'object') {
return;
}
const { chatConfig, elementId } = this.props;
await chatUtils.initialize(chatConfig, elementId);
window.webchat.chatEnded = this.onChatEnded;
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({ isChatReady: true });
if (window.webchat.isAutoJoined()) {
this.onChangeIsClosable(false);
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({ showButton: false });
}
}
onChangeIsClosable = (isClosable: boolean) => {
this.setState({ isClosable });
this.props.onToggleIsClosable(isClosable);
};
onClickDisplayChat = () => {
this.setState({ showButton: false });
if (!window.webchat) {
throw new Error('Unexpected: webchat not initialized.');
}
const { guaranteeChatBookingInfo } = this.props;
chatUtils.setData(window.webchat, guaranteeChatBookingInfo);
simpleTracker('smartFAQBookingOverview', {
action: 'chatOpened',
where: this.props.eventSource,
});
track('Guarantee Chat', 'chatOpened', { where: this.props.eventSource });
window.webchat.renderFrame({ containerEl: this.props.elementId });
this.onChangeIsClosable(false);
};
onChatEnded = () => {
this.onChangeIsClosable(true);
};
render() {
const { showButton, isChatReady, isClosable } = this.state;
return (
<React.Fragment>
{showButton &&
this.props.children({
isChatReady,
onClickDisplayChat: this.onClickDisplayChat,
})}
<div
id={this.props.elementId}
ref={c => {
this.chatContainer = c;
}}
className={classNames('guaranteeChat', {
open: !showButton,
})}
data-cy="guaranteeChatIFrame"
/>
{this.props.withPrompt && (
<IntlConsumer>
{intl => (
<Prompt
when={!isClosable}
message={intl.translate(
__('smartfaq.guarantee_chat.confirmation'),
)}
/>
)}
</IntlConsumer>
)}
<style jsx>
{`
.guaranteeChat.open {
height: 500px;
}
`}
</style>
</React.Fragment>
);
}
}
export const GuaranteeChatWrapperRaw = GuaranteeChatWrapper;
const WrappedGuaranteeChat = (props: ContainerProps) => (
<GuaranteeChatInfoState.Consumer>
{({ guaranteeChatBookingInfo, chatConfig, onToggleIsClosable }) => (
<GuaranteeChatWrapper
{...props}
guaranteeChatBookingInfo={guaranteeChatBookingInfo}
chatConfig={chatConfig}
onToggleIsClosable={onToggleIsClosable}
/>
)}
</GuaranteeChatInfoState.Consumer>
);
export default WrappedGuaranteeChat;