-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.tsx
136 lines (121 loc) · 3.93 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import React from 'react';
import { Button, Divider, message, Modal, Typography } from 'antd';
import { KeyOutlined } from '@ant-design/icons';
import moment, { Moment } from 'moment';
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';
import { formatListingPrice, displayErrorMessage, displaySuccessNotification } from '../../../../lib/utils';
import { useMutation } from '@apollo/client';
import { CREATE_BOOKING } from '../../../../lib/graphql/mutations/CreateBooking';
import {
CreateBooking as CreateBookingData,
CreateBookingVariables,
} from '../../../../lib/graphql/mutations/CreateBooking/__generated__/CreateBooking';
interface Props {
id: string;
modalVisible: boolean;
checkInDate: Moment;
checkOutDate: Moment;
price: number;
setModalVisible: (modalVisible: boolean) => void;
clearBookingData: () => void;
refetchListing: () => Promise<void>;
}
const { Paragraph, Title, Text } = Typography;
export const ListingCreateBookingModal = ({
id,
checkInDate,
checkOutDate,
price,
modalVisible,
setModalVisible,
clearBookingData,
refetchListing,
}: Props) => {
const [createBooking, { loading }] = useMutation<CreateBookingData, CreateBookingVariables>(CREATE_BOOKING, {
onCompleted: () => {
clearBookingData();
displaySuccessNotification(
"You've successfully booked the listing!",
'Booking history can always be found in your Profile.'
);
refetchListing();
},
onError: () => {
displayErrorMessage("Sorry! We weren't able to book the listing. Please try again later!");
},
});
const daysBooked = checkOutDate.diff(checkInDate, 'days') + 1;
const listingPrice = price * daysBooked;
const stripe = useStripe();
const elements = useElements();
const handleClick = async () => {
if (!stripe || !elements) return;
const cardElement = elements?.getElement(CardElement);
if (!cardElement) return;
const { token: stripeToken, error } = await stripe.createToken(cardElement);
if (stripeToken) {
createBooking({
variables: {
input: {
id,
source: stripeToken.id,
checkIn: moment(checkInDate).format('YYYY-MM-DD'),
checkOut: moment(checkInDate).format('YYYY-MM-DD'),
},
},
});
} else {
displayErrorMessage(error && error.message ? error.message : 'Unable to Book the Listing. Try again later.');
}
};
return (
<Modal visible={modalVisible} centered footer={null} onCancel={() => setModalVisible(false)}>
<div className="listing-booking-modal">
<div className="listing-booking-modal__intro">
<Title className="listing-boooking-modal__intro-title">
<KeyOutlined />
</Title>
<Title level={3} className="listing-boooking-modal__intro-title">
Book your trip
</Title>
<Paragraph>
Enter your payment information to book the listing from the dates between{' '}
<Text mark strong>
{moment(checkInDate).format('MMMM Do YYYY')}
</Text>{' '}
and{' '}
<Text mark strong>
{moment(checkOutDate).format('MMMM Do YYYY')}
</Text>
, inclusive.
</Paragraph>
</div>
<Divider />
<div className="listing-booking-modal__charge-summary">
<Paragraph>
{formatListingPrice(price, false)} x {daysBooked} days ={' '}
<Text strong>{formatListingPrice(listingPrice, false)}</Text>
</Paragraph>
<Paragraph className="listing-booking-modal__charge-summary-total">
Total = <Text mark>{formatListingPrice(listingPrice, false)}</Text>
</Paragraph>
</div>
<div className="listing-booking-modal__stripe-card-section">
{/* Provided by react-stripe */}
<CardElement
options={{ hidePostalCode: true, style: { base: { fontFamily: 'Arial' } } }}
className="listing-booking-modal__stripe-card"
/>
<Button
loading={loading}
size="large"
type="primary"
className="listing-booking-modal__cta"
onClick={handleClick}>
Book
</Button>
</div>
</div>
</Modal>
);
};