@kiwicom/smart-faq
Version:
Smart FAQ
290 lines (260 loc) • 7.22 kB
JavaScript
// @flow
import * as React from 'react';
import idx from 'idx';
import { graphql } from 'react-relay';
import css from 'styled-jsx/css';
import { Consumer as IntlConsumer } from '@kiwicom/nitro/lib/services/intl/context';
import Button from '@kiwicom/orbit-components/lib/Button';
import Stack from '@kiwicom/orbit-components/lib/Stack';
import QueryRenderer from '../../../SmartFAQ/relay/QueryRenderer';
import Loader from '../../../SmartFAQ/common/Loader';
import {
SidebarVersion,
FullPageVersion,
} from '../../../SmartFAQ/common/PageVariant';
import FAQArticleDetailContent from './ArticleContent';
import FAQArticleNotFound from './FAQArticleNotFound';
import type { ArticleDetailQueryResponse } from './__generated__/ArticleDetailQuery.graphql';
import type { ArticleDetailSearchResultQueryResponse } from './__generated__/ArticleDetailSearchResultQuery.graphql';
import CustomBreadcrumbs from '../breadcrumbs/CustomBreadcrumbs';
import sectionFAQCategories from '../sectionFAQCategories';
import StaticFAQError from '../StaticFAQError';
import ScrollableContent from '../../../SmartFAQ/common/ScrollableContent';
const queryFAQArticleDetail = graphql`
query ArticleDetailQuery(
$id: ID!
$categoryId: ID!
$isSubcategory: Boolean!
) {
FAQArticle(id: $id) {
title
...ArticleContent_article
}
FAQCategory(id: $categoryId) @include(if: $isSubcategory) {
title
id
ancestors {
id
title
}
}
}
`;
const queryFAQArticleDetailSearchResult = graphql`
query ArticleDetailSearchResultQuery($id: ID!) {
FAQArticle(id: $id) {
title
...ArticleContent_article
}
}
`;
type ArticleCategoryProps = {
props: ?ArticleDetailQueryResponse,
error: ?Error,
};
type ArticleSearchProps = {
props: ?ArticleDetailSearchResultQueryResponse,
error: ?Error,
};
type Props = {
match: {
params: {
articleId: string,
categoryId: string,
[key: string]: ?string,
},
isExact: boolean,
path: string,
url: string,
},
};
const style = css`
.breadcrumbs {
margin: 24px 36px;
margin-bottom: -2px;
}
@media only screen and (max-width: 901px) {
.breadcrumbs {
margin: 0 auto;
background-color: #f5f7f9;
}
}
`;
class Article extends React.Component<Props> {
renderLoading = () => {
return (
<div style={{ height: '100%' }}>
<Loader fullHeight />
</div>
);
};
renderError = () => {
return (
<div className="errorWrapper">
<StaticFAQError />
<style jsx>
{`
.errorWrapper {
height: 100%;
padding: 24px 40px;
}
`}
</style>
</div>
);
};
renderArticleFromSearch = (params: ArticleSearchProps) => {
if (params.error) {
return this.renderError();
}
if (params.props) {
const article = params.props.FAQArticle;
if (!article) {
return <FAQArticleNotFound />;
}
return (
<>
<IntlConsumer>
{intl => (
<CustomBreadcrumbs
breadcrumbs={[
{
title: intl.translate(__('smartfaq.breadcrumb.search')),
},
{ title: article.title },
]}
/>
)}
</IntlConsumer>
<FAQArticleDetailContent article={article} />
<style jsx>{style}</style>
</>
);
}
return this.renderLoading();
};
renderArticleFromCategory = (params: ArticleCategoryProps) => {
if (params.error) {
return this.renderError();
}
if (params.props) {
const category = params.props.FAQCategory;
const article = params.props.FAQArticle;
let breadcrumbs = null;
if (!article) {
return <FAQArticleNotFound />;
}
if (this.isSectionCategory()) {
breadcrumbs = (
<IntlConsumer>
{intl => (
<CustomBreadcrumbs
breadcrumbs={[
{ title: intl.translate(__('smartfaq.breadcrumb.home')) },
{ title: article.title },
]}
/>
)}
</IntlConsumer>
);
} else if (category) {
breadcrumbs = (
<IntlConsumer>
{intl => (
<CustomBreadcrumbs
breadcrumbs={[
{ title: intl.translate(__('smartfaq.breadcrumb.home')) },
]
.concat(
category.ancestors
? category.ancestors.filter(Boolean)
: [],
)
.concat(category)
.concat([
{
title: intl.translate(__('smartfaq.breadcrumb.article')),
},
])}
/>
)}
</IntlConsumer>
);
}
return (
<>
{breadcrumbs}
<FAQArticleDetailContent article={article} />
<style jsx>{style}</style>
</>
);
}
return this.renderLoading();
};
getCategoryId = () => {
return idx(this.props.match, _ => _.params.categoryId);
};
isSectionCategory = () => {
const categoryId = this.getCategoryId();
return categoryId && sectionFAQCategories.includes(categoryId);
};
getQueryRenderer() {
const categoryId = this.getCategoryId();
const articleId = idx(this.props.match, _ => _.params.articleId);
const isSearchResult = categoryId === 'search';
if (isSearchResult) {
return (
<QueryRenderer
query={queryFAQArticleDetailSearchResult}
variables={{ id: articleId }}
render={this.renderArticleFromSearch}
/>
);
}
return (
<QueryRenderer
query={queryFAQArticleDetail}
variables={{
id: articleId,
categoryId,
isSubcategory: !this.isSectionCategory(),
}}
render={this.renderArticleFromCategory}
/>
);
}
render() {
return (
<>
<FullPageVersion>
<div style={{ marginBottom: '40px' }}>{this.getQueryRenderer()}</div>
<Stack direction="row" flex={false} spacing="loose">
<Button>Sign In</Button>
<p>
Sign In with your booking and we will try to personalise the help
towards your case as much as possible.
</p>
</Stack>
</FullPageVersion>
<SidebarVersion>
<ScrollableContent styles="background-color: #ffffff">
<div className="faq-article-detail">
{this.getQueryRenderer()}
<style jsx>
{`
.faq-article-detail {
background-color: #ffffff;
width: 100%;
max-width: 100vw;
height: 100%;
}
`}
</style>
</div>
</ScrollableContent>
</SidebarVersion>
</>
);
}
}
export default Article;