@kiwicom/smart-faq
Version:
160 lines (143 loc) • 4.58 kB
JavaScript
// @flow
import * as React from 'react';
import { graphql, createFragmentContainer } from 'react-relay';
import { Heading } from '@kiwicom/orbit-components';
import Button from '@kiwicom/nitro/lib/components/Button';
import ValueBind from '@kiwicom/nitro/lib/components/ValueBind';
import OneWayBooking from './BookingTypes/OneWayBooking';
import ReturnBooking from './BookingTypes/ReturnBooking';
import MulticityBooking from './BookingTypes/MulticityBooking';
import type { BookingCardsList_bookings as BookingCardListType } from './__generated__/BookingCardsList_bookings.graphql';
import { SelectedBooking } from '../context/SelectedBooking';
import type { State } from '../context/SelectedBooking';
type Props = {|
loadMore: () => void,
hasMore: boolean,
isLoading: boolean,
bookings: BookingCardListType,
title: string,
|};
type BookingVariants = {
BookingOneWay: React.Node,
BookingReturn: React.Node,
BookingMulticity: React.Node,
};
class BookingCardsList extends React.Component<Props, State> {
endOfAllBookings: { current: ?HTMLDivElement };
constructor(props: Props) {
super(props);
this.endOfAllBookings = React.createRef();
}
componentDidUpdate() {
this.scrollToBottom();
}
scrollToBottom = () => {
if (this.endOfAllBookings.current) {
this.endOfAllBookings.current.scrollIntoView({ behavior: 'smooth' });
}
};
render() {
const { title, bookings, hasMore, isLoading, loadMore } = this.props;
return (
<div>
{bookings.length > 0 && (
<div className="subtitle">
<Heading type="title3">{title}</Heading>
</div>
)}
{bookings.map(booking => {
const id = parseInt(booking.databaseId, 10);
const type = booking.type;
const variants: BookingVariants = {
BookingOneWay: <OneWayBooking booking={booking} />,
BookingReturn: <ReturnBooking booking={booking} />,
BookingMulticity: <MulticityBooking booking={booking} />,
};
let bookingComponent = null;
if (type && variants[type]) {
bookingComponent = variants[type];
}
if (bookingComponent) {
if (!id) {
return bookingComponent;
}
return (
<SelectedBooking.Consumer key={id}>
{({ onSelectBooking }: State) => (
// $FlowExpectedError: ValueBind accepts only string in type definition
<ValueBind value={id} onChange={onSelectBooking}>
{({ onClick }) => (
<div
onClick={onClick}
className="bookingCard"
data-cy="booking-card"
role="button"
onKeyUp={onClick}
tabIndex={0}
>
{bookingComponent}
</div>
)}
</ValueBind>
)}
</SelectedBooking.Consumer>
);
}
return null;
})}
{hasMore && !isLoading && (
<div className="loadMoreButton" data-cy="loadMoreButton">
<Button
onClick={loadMore}
block={false}
type="secondary"
size="small"
t="smartfaq.all_bookings.load_more_button"
/>
</div>
)}
<div
style={{ float: 'left', clear: 'both' }}
ref={this.endOfAllBookings}
/>
<style jsx>
{`
.bookingCard {
cursor: pointer;
outline: none;
}
div.subtitle {
margin-top: 14px;
margin-bottom: 12px;
}
@media only screen and (max-width: 901px) {
div.loadMoreButton {
margin-bottom: 30px;
}
}
`}
</style>
</div>
);
}
}
export const RawBookingCardsList = BookingCardsList;
export default createFragmentContainer(
BookingCardsList,
graphql`
fragment BookingCardsList_bookings on BookingInterface
@relay(plural: true) {
databaseId: id(opaque: false)
type: __typename
... on BookingOneWay {
...OneWayBooking_booking
}
... on BookingReturn {
...ReturnBooking_booking
}
... on BookingMulticity {
...MulticityBooking_booking
}
}
`,
);