tf-checkout-react 1.4.18 → 1.4.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ /* eslint-disable max-len */
1
2
  import './style.css'
2
3
 
3
4
  import { ThemeOptions } from '@mui/material'
@@ -22,32 +23,32 @@ import { nanoid } from 'nanoid'
22
23
  import React, { useEffect, useState } from 'react'
23
24
 
24
25
  import {
26
+ createPaymentPlan,
25
27
  getConditions,
26
28
  getPaymentData,
27
29
  handleFreeSuccess,
28
30
  handlePaymentSuccess,
29
31
  } from '../../api'
30
32
  import { usePixel } from '../../hooks/usePixel'
31
- import {
32
- createFixedFloatNormalizer,
33
- currencyNormalizerCreator,
34
- } from '../../normalizers'
33
+ import { createFixedFloatNormalizer, currencyNormalizerCreator } from '../../normalizers'
35
34
  import { IAddOn, IOrderData, IPaymentField } from '../../types'
35
+ import {
36
+ IPaymentPlanConfig,
37
+ IPaymentPlanConfigCard,
38
+ } from '../../types/payment-plan-configuration'
36
39
  import { CONFIGS, isBrowser } from '../../utils'
37
40
  import { getQueryVariable } from '../../utils/getQueryVariable'
38
- import { Loader } from '../common/index'
41
+ import { CheckboxField, Loader } from '../common/index'
39
42
  import StripePayment from '../stripePayment'
40
43
  import TimerWidget from '../timerWidget'
44
+ import { PaymentPlanSection } from './PaymentPlanSection'
41
45
 
42
46
  const publishableKey = CONFIGS.STRIPE_PUBLISHABLE_KEY || ''
43
47
 
44
48
  const getStripePromise = (reviewData: any) => {
45
49
  const stripePublishableKey =
46
50
  _get(reviewData, 'payment_method.stripe_publishable_key') || publishableKey
47
- const stripeAccount = _get(
48
- reviewData,
49
- 'payment_method.stripe_connected_account'
50
- )
51
+ const stripeAccount = _get(reviewData, 'payment_method.stripe_connected_account')
51
52
 
52
53
  const options: StripeConstructorOptions = {}
53
54
  if (stripeAccount) {
@@ -81,6 +82,24 @@ export interface IPaymentPage {
81
82
  orderInfoLabel?: string;
82
83
  }
83
84
 
85
+ const initialPaymentPlanConfiguration: IPaymentPlanConfig = {
86
+ requires_deposit: false,
87
+ deposit: 0,
88
+ interval: 0,
89
+ non_refundable_amount: 0,
90
+ non_refundable_type: null,
91
+ has_admin_fee: false,
92
+ admin_fee: 0,
93
+ total_installments: 0,
94
+ price_per_installment: 0,
95
+ stripe_setup_intent_secret: '',
96
+ total: 0,
97
+ saved_card: {
98
+ last_4_digits: null,
99
+ stripe_payment_method_id: null,
100
+ } as IPaymentPlanConfigCard,
101
+ }
102
+
84
103
  const initialOrderValues: IOrderData = {
85
104
  id: '',
86
105
  product_name: '',
@@ -96,10 +115,13 @@ const initialOrderValues: IOrderData = {
96
115
 
97
116
  const initialReviewValues = {
98
117
  order_details: {
118
+ id: '',
99
119
  order_hash: '',
100
120
  },
101
121
  payment_method: {
102
122
  stripe_client_secret: '',
123
+ stripe_payment_plan_enabled: false,
124
+ stripe_payment_plan_configuration: null,
103
125
  },
104
126
  billing_info: {},
105
127
  }
@@ -120,7 +142,7 @@ export const PaymentContainer = ({
120
142
  elementsOptions,
121
143
  onCountdownFinish = _identity,
122
144
  enableTimer = false,
123
- enablePaymentPlan = false,
145
+ enablePaymentPlan = true,
124
146
  paymentButtonText,
125
147
  orderInfoLabel = 'Order Review',
126
148
  paymentInfoLabel = 'Order Confirmation',
@@ -131,9 +153,13 @@ export const PaymentContainer = ({
131
153
  const [showPaymentPlanSection, setShowPaymentPlanSection] = useState(false)
132
154
  const [paymentIsLoading, setPaymentIsLoading] = useState(false)
133
155
  const [paymentDataIsLoading, setPaymentDataIsLoading] = useState(true)
134
- const [conditions, setConditions] = useState<{ id: string, text: string }[]>(
135
- []
156
+ const [conditions, setConditions] = useState<{ id: string, text: string }[]>([])
157
+ const [paymentPlanIsAvailable, setPaymentPlanIsAvailable] = useState(false)
158
+ const [paymentPlanConfig, setPaymentPlanConfig] = useState(
159
+ initialPaymentPlanConfiguration
136
160
  )
161
+ const [paymentPlanUseSavedCard, setPaymentPlanUseSavedCard] = useState(true)
162
+ const [currency, setCurrency] = useState('')
137
163
 
138
164
  const showFormTitle = Boolean(formTitle)
139
165
  const showErrorText = Boolean(errorText)
@@ -147,6 +173,32 @@ export const PaymentContainer = ({
147
173
  const pageUrl = isBrowser ? window.location.href.split('?')[0] : ''
148
174
  usePixel(eventId, { page: 'review', pageUrl })
149
175
 
176
+ useEffect(() => {
177
+ const paymentMethod = reviewData.payment_method || {}
178
+ const paymentPlanAvailable =
179
+ paymentMethod.stripe_payment_plan_enabled && enablePaymentPlan
180
+ setPaymentPlanIsAvailable(paymentPlanAvailable)
181
+
182
+ if (paymentPlanAvailable) {
183
+ const paymentPlanConfig =
184
+ paymentMethod.stripe_payment_plan_configuration || initialPaymentPlanConfiguration
185
+ setPaymentPlanConfig(paymentPlanConfig)
186
+ setPaymentPlanUseSavedCard(!!paymentPlanConfig.saved_card?.stripe_payment_method_id)
187
+ if (typeof window !== 'undefined') {
188
+ const sessionData = window.localStorage.getItem('paymentConfiguration')
189
+ const session = sessionData ? JSON.parse(sessionData) : {}
190
+ if (!!session && session?.orderId == reviewData.order_details?.id) {
191
+ setPaymentPlanUseSavedCard(session.paymentPlanUseSavedCard ?? false)
192
+ setShowPaymentPlanSection(session.showPaymentPlanSection ?? false)
193
+ }
194
+ }
195
+ }
196
+ }, [enablePaymentPlan, reviewData])
197
+
198
+ useEffect(() => {
199
+ updateSessionInformation()
200
+ }, [showPaymentPlanSection, paymentPlanUseSavedCard])
201
+
150
202
  useEffect(() => {
151
203
  (async () => {
152
204
  try {
@@ -183,6 +235,7 @@ export const PaymentContainer = ({
183
235
  tableTypes: orderDataArray,
184
236
  }
185
237
  setOrderData(orderData)
238
+ setCurrency(order_details?.currency)
186
239
  onGetPaymentDataSuccess(response.data)
187
240
  }
188
241
  } catch (e) {
@@ -204,10 +257,10 @@ export const PaymentContainer = ({
204
257
  setConditions(
205
258
  conditionsInfo
206
259
  ? conditionsInfo.map((item: string) => ({
207
- id: nanoid(),
208
- text: item,
209
- checked: false,
210
- }))
260
+ id: nanoid(),
261
+ text: item,
262
+ checked: false,
263
+ }))
211
264
  : []
212
265
  )
213
266
  }
@@ -218,7 +271,7 @@ export const PaymentContainer = ({
218
271
  // 1. get payment data ---> v1/order/${hash}/review/ done
219
272
  // 2. handle payment ---> v1/order/${orderHash}/pay/
220
273
  // 3. redirect to confirmation page
221
- const handlePaymentMiddleWare = async (error: any) => {
274
+ const handlePaymentMiddleWare = async (error: any, data?: object) => {
222
275
  try {
223
276
  if (error) {
224
277
  throw error
@@ -226,9 +279,20 @@ export const PaymentContainer = ({
226
279
  const {
227
280
  order_details: { order_hash },
228
281
  } = reviewData
229
- const paymentSuccessResponse = isFreeTickets
230
- ? await handleFreeSuccess(order_hash)
231
- : await handlePaymentSuccess(order_hash)
282
+
283
+ let paymentSuccessResponse
284
+
285
+ if (isFreeTickets) {
286
+ paymentSuccessResponse = await handleFreeSuccess(order_hash)
287
+ } else if (paymentPlanIsAvailable && showPaymentPlanSection) {
288
+ paymentSuccessResponse = await createPaymentPlan(
289
+ order_hash,
290
+ _get(data, 'paymentMethodId', '')
291
+ )
292
+ } else {
293
+ paymentSuccessResponse = await handlePaymentSuccess(order_hash)
294
+ }
295
+
232
296
  if (paymentSuccessResponse.status === 200) {
233
297
  handlePayment(paymentSuccessResponse)
234
298
  setPaymentIsLoading(false)
@@ -239,13 +303,13 @@ export const PaymentContainer = ({
239
303
  localStorage.removeItem('ownReservations')
240
304
  localStorage.removeItem('tierId')
241
305
 
242
- const isWindowDefined = typeof window !== "undefined"
306
+ const isWindowDefined = typeof window !== 'undefined'
243
307
  if (isWindowDefined) {
244
308
  (window as any)?.dataLayer.push({
245
- 'event': 'Purchase',
246
- 'orderValue': orderData.total,
247
- 'orderCurrency': orderData.currency,
248
- 'orderId': orderData.id
309
+ event: 'Purchase',
310
+ orderValue: orderData.total,
311
+ orderCurrency: orderData.currency,
312
+ orderId: orderData.id,
249
313
  })
250
314
  }
251
315
  }
@@ -256,46 +320,72 @@ export const PaymentContainer = ({
256
320
  }
257
321
  }
258
322
 
323
+ const showPaymentForm = () => {
324
+ let showPaymentForm = !isFreeTickets
325
+
326
+ if (
327
+ paymentPlanIsAvailable &&
328
+ showPaymentPlanSection &&
329
+ !!paymentPlanConfig.saved_card?.stripe_payment_method_id
330
+ ) {
331
+ showPaymentForm = !paymentPlanUseSavedCard
332
+ }
333
+
334
+ return showPaymentForm
335
+ }
336
+ const updateSessionInformation = () => {
337
+ if (typeof window !== 'undefined' && !!orderData?.id) {
338
+ window.localStorage.setItem(
339
+ 'paymentConfiguration',
340
+ JSON.stringify({
341
+ paymentPlanUseSavedCard,
342
+ showPaymentPlanSection,
343
+ orderId: orderData?.id,
344
+ })
345
+ )
346
+ }
347
+ }
348
+
259
349
  const themeMui = createTheme(themeOptions)
260
350
  const hasTableTypes = Boolean(Number(orderData.guest_count))
261
351
  const paymentFieldsData = hasTableTypes
262
352
  ? [
263
- {
264
- label: 'Event',
265
- id: 'product_name',
266
- },
267
- {
268
- label: '',
269
- id: 'tableTypes',
270
- },
271
- {
272
- label: 'Total (incl. fees, card processing and taxes)',
273
- id: 'total',
274
- normalizer: (value: string, currency: any) =>
275
- currencyNormalizerCreator(
276
- createFixedFloatNormalizer(2)(parseFloat(value)),
277
- currency
278
- ),
279
- },
280
- {
281
- label: 'Pay Now',
282
- id: 'pay_now',
283
- normalizer: (value: string, currency: any) =>
284
- currencyNormalizerCreator(
285
- createFixedFloatNormalizer(2)(parseFloat(value)),
286
- currency
287
- ),
288
- },
289
- {
290
- label: 'Pay On Check-in',
291
- id: 'debt',
292
- normalizer: (value: string, currency: any) =>
293
- currencyNormalizerCreator(
294
- createFixedFloatNormalizer(2)(parseFloat(value)),
295
- currency
296
- ),
297
- },
298
- ]
353
+ {
354
+ label: 'Event',
355
+ id: 'product_name',
356
+ },
357
+ {
358
+ label: '',
359
+ id: 'tableTypes',
360
+ },
361
+ {
362
+ label: 'Total (incl. fees, card processing and taxes)',
363
+ id: 'total',
364
+ normalizer: (value: string, currency: string) =>
365
+ currencyNormalizerCreator(
366
+ createFixedFloatNormalizer(2)(parseFloat(value)),
367
+ currency
368
+ ),
369
+ },
370
+ {
371
+ label: 'Pay Now',
372
+ id: 'pay_now',
373
+ normalizer: (value: string, currency: string) =>
374
+ currencyNormalizerCreator(
375
+ createFixedFloatNormalizer(2)(parseFloat(value)),
376
+ currency
377
+ ),
378
+ },
379
+ {
380
+ label: 'Pay On Check-in',
381
+ id: 'debt',
382
+ normalizer: (value: string, currency: string) =>
383
+ currencyNormalizerCreator(
384
+ createFixedFloatNormalizer(2)(parseFloat(value)),
385
+ currency
386
+ ),
387
+ },
388
+ ]
299
389
  : paymentFields
300
390
  const isTable = orderData?.guest_count
301
391
  return (
@@ -316,29 +406,29 @@ export const PaymentContainer = ({
316
406
  {paymentDataIsLoading && <Loader />}
317
407
  {!paymentDataIsLoading && (
318
408
  <Container maxWidth="md">
319
- {showFormTitle && (
320
- <h1>{isTable ? 'Get Your Tables' : formTitle}</h1>
321
- )}
409
+ {showFormTitle && <h1>{isTable ? 'Get Your Tables' : formTitle}</h1>}
322
410
  <div className="order_info_text">{orderInfoLabel}</div>
323
411
  <div
324
412
  className="order_info_section"
325
413
  style={{ display: hasTableTypes ? 'block' : 'grid' }}
326
414
  >
327
415
  {_map(paymentFieldsData, field => {
328
- const {
329
- id,
330
- label,
331
- className = '',
332
- normalizer = _identity,
333
- } = field
334
- const { currency } = orderData
335
- const value = orderData[id as keyof IOrderData]
416
+ const { id, label, className = '', normalizer = _identity } = field
417
+ let value = orderData[id as keyof IOrderData]
336
418
  let component = null
337
419
 
338
420
  if (field.id === 'add_ons' && _isEmpty(value)) {
339
421
  return false
340
422
  }
341
423
 
424
+ if (
425
+ field.id === 'total' &&
426
+ paymentPlanIsAvailable &&
427
+ showPaymentPlanSection
428
+ ) {
429
+ value = '' + paymentPlanConfig.total
430
+ }
431
+
342
432
  if (field.id === 'tableTypes') {
343
433
  const valueArray = value as Array<any>
344
434
 
@@ -367,9 +457,7 @@ export const PaymentContainer = ({
367
457
  </div>
368
458
  </div>
369
459
  <div className="order_info_block">
370
- <div className="order_info_title">
371
- Number of Tables
372
- </div>
460
+ <div className="order_info_title">Number of Tables</div>
373
461
  <div className={`${className} order_info_text`}>
374
462
  {tableTypeItem.count}
375
463
  </div>
@@ -394,101 +482,65 @@ export const PaymentContainer = ({
394
482
  {typeof value === 'string'
395
483
  ? normalizer(value, currency)
396
484
  : _map(value, item => (
397
- <div key={item.id} className="add-on-container">
398
- <span>{item.quantity}</span>
399
- <span className="add-on-x">{' x '}</span>
400
- <span>
401
- {item.groupName ? item.groupName + ' - ' : ''}
402
- </span>
403
- <span>{item.name}</span>
404
- <span>{' - '}</span>
405
- <span>
406
- {currencyNormalizerCreator(
407
- createFixedFloatNormalizer(2)(
408
- parseFloat(item.price)
409
- ),
410
- currency
411
- )}
412
- </span>
413
- <span className="add-on-each">{' each'}</span>
414
- </div>
415
- ))}
485
+ <div key={item.id} className="add-on-container">
486
+ <span>{item.quantity}</span>
487
+ <span className="add-on-x">{' x '}</span>
488
+ <span>
489
+ {item.groupName ? item.groupName + ' - ' : ''}
490
+ </span>
491
+ <span>{item.name}</span>
492
+ <span>{' - '}</span>
493
+ <span>
494
+ {currencyNormalizerCreator(
495
+ createFixedFloatNormalizer(2)(parseFloat(item.price)),
496
+ currency
497
+ )}
498
+ </span>
499
+ <span className="add-on-each">{' each'}</span>
500
+ </div>
501
+ ))}
416
502
  </div>
417
503
  </div>
418
504
  )
419
505
  )
420
506
  })}
421
507
  </div>
422
- {enablePaymentPlan && (
508
+ {!isFreeTickets && paymentPlanIsAvailable && (
423
509
  <div className="payment_toggle">
424
- <label htmlFor="togBtn" className="switch">
425
- <input
426
- type="checkbox"
427
- id="togBtn"
428
- disabled={true}
429
- onChange={() =>
430
- setShowPaymentPlanSection(!showPaymentPlanSection)
431
- }
432
- />
433
- <div className="slider round" />
434
- <span className="tog_text">
435
- Click to checkout using Payment Plan
436
- </span>
437
- </label>
510
+ <CheckboxField
511
+ label={<span className='payment_plan_toggle_label'>Click to checkout using Payment Plan</span>}
512
+ required={true}
513
+ onChange={(_: any) => {
514
+ setShowPaymentPlanSection(!showPaymentPlanSection)
515
+ }}
516
+ checked={showPaymentPlanSection}
517
+ />
438
518
  </div>
439
519
  )}
440
520
  {showPaymentPlanSection && (
441
- <div className="payment_plan">
442
- <h2>PAYMENT PLAN</h2>
443
- <div className="plan_block">
444
- <h3>Mbrand Payment Plan Terms</h3>
445
- <p>
446
- By clicking on the “Confirm Payment Plan” button, you are
447
- starting your payment plan of 2 payments of $115.00, which
448
- will be drawn from your account every 2 weeks, with the
449
- first payment taken later today.
450
- </p>
451
- <p>
452
- This includes a non-refundable admin fee of $3.00 per
453
- payment.
454
- </p>
455
- <p className="payment_note">
456
- NOTE: If today’s payment fails, your payment plan will not
457
- activate, and your tickets will not be issued until you
458
- complete your final payment.
459
- </p>
460
- <p>
461
- If you do not complete your payements, your order will be
462
- canceled. Your first payment of $115.00, plus the
463
- non-refundable admin fee of $3.00 will not be refunded.
464
- </p>
465
- <p>
466
- Your payment will proceed with the card ending in **** 4242.
467
- </p>
468
- </div>
469
- </div>
521
+ <PaymentPlanSection
522
+ paymentPlanConfig={paymentPlanConfig}
523
+ currency={currency}
524
+ paymentPlanUseSavedCard={paymentPlanUseSavedCard}
525
+ setPaymentPlanUseSavedCard={setPaymentPlanUseSavedCard}
526
+ />
470
527
  )}
471
- {!isFreeTickets ? (
528
+ {showPaymentForm() ? (
472
529
  <div className="payment_info">
473
530
  <div className="payment_info_label">{paymentInfoLabel}</div>
474
- {showErrorText && (
475
- <p className="payment_info__error">{errorText}</p>
476
- )}
531
+ {showErrorText && <p className="payment_info__error">{errorText}</p>}
477
532
  <div>
478
533
  <Elements
479
534
  stripe={getStripePromise(reviewData)}
480
535
  options={elementsOptions}
481
536
  >
482
537
  <StripePayment
483
- stripe_client_secret={_get(
484
- reviewData,
485
- 'payment_method.stripe_client_secret'
486
- )}
487
- total={
488
- orderData.guest_count
489
- ? orderData.pay_now
490
- : orderData.total
538
+ stripe_client_secret={
539
+ paymentPlanIsAvailable && showPaymentPlanSection
540
+ ? paymentPlanConfig.stripe_setup_intent_secret
541
+ : _get(reviewData, 'payment_method.stripe_client_secret')
491
542
  }
543
+ total={orderData.guest_count ? orderData.pay_now : orderData.total}
492
544
  onSubmit={handlePaymentMiddleWare}
493
545
  error={error}
494
546
  currency={orderData.currency}
@@ -499,27 +551,44 @@ export const PaymentContainer = ({
499
551
  stripeCardOptions={stripeCardOptions}
500
552
  disableZipSection={disableZipSection}
501
553
  paymentButtonText={paymentButtonText}
554
+ forPaymentPlan={paymentPlanIsAvailable && showPaymentPlanSection}
502
555
  />
503
556
  </Elements>
504
557
  </div>
505
558
  </div>
506
559
  ) : (
507
560
  <div
508
- className={`payment_button ${paymentIsLoading ? 'disabled-payment-button' : ''
509
- }`}
561
+ className={`payment_button ${
562
+ paymentIsLoading ? 'disabled-payment-button' : ''
563
+ }`}
510
564
  >
511
565
  <button
512
566
  disabled={paymentIsLoading}
513
567
  type="button"
514
568
  onClick={() => {
515
569
  setPaymentIsLoading(true)
516
- handlePaymentMiddleWare(null)
570
+ let data
571
+
572
+ if (
573
+ paymentPlanIsAvailable &&
574
+ showPaymentPlanSection &&
575
+ paymentPlanUseSavedCard
576
+ ) {
577
+ data = {
578
+ paymentMethodId:
579
+ paymentPlanConfig.saved_card?.stripe_payment_method_id,
580
+ }
581
+ }
582
+
583
+ handlePaymentMiddleWare(null, data)
517
584
  }}
518
585
  >
519
586
  {paymentIsLoading ? (
520
587
  <CircularProgress size={26} />
521
- ) : (
588
+ ) : isFreeTickets ? (
522
589
  'Complete Registration'
590
+ ) : (
591
+ 'Confirm Payment Plan'
523
592
  )}
524
593
  </button>
525
594
  </div>
@@ -45,3 +45,11 @@
45
45
  padding-top: 20px;
46
46
  text-align: center;
47
47
  }
48
+
49
+ .payment_page .payment_plan .payment_plan_block .payment_plan_text {
50
+ padding-bottom: 10px;
51
+ }
52
+
53
+ .payment_page .payment_plan .payment_plan_highlight {
54
+ font-weight: bold;
55
+ }
@@ -4,6 +4,7 @@ import React, { useEffect } from 'react'
4
4
  import ReactDom from 'react-dom'
5
5
  import SeatMapView from 'tf-seat-map-view'
6
6
 
7
+ import { Loader } from '../common'
7
8
  import { getTierRelationsArray } from './utils'
8
9
 
9
10
  const CONTAINER_DEFAULT_ID = 'seat_map_default_container'
@@ -26,35 +27,38 @@ export const SeatMapComponent = (props: ISeatMapContainerProps) => {
26
27
  tierPrices,
27
28
  isReserving,
28
29
  predefinedSeats,
30
+ isLoadingSeatMapData,
29
31
  } = seatMapProps
30
32
 
31
33
  useEffect(() => {
32
- const parentElement = document.getElementById(
33
- mapContainerId || CONTAINER_DEFAULT_ID
34
- )
34
+ const parentElement = document.getElementById(mapContainerId || CONTAINER_DEFAULT_ID)
35
35
 
36
36
  // Temp solution
37
37
  window.tierPrices = tierPrices
38
38
 
39
- if (Boolean(parentElement)) {
40
- const mapComponent = (
41
- <SeatMapView
42
- disabled={isReserving}
43
- loading={isReserving}
44
- events={seatMapEvents}
45
- isSelectionOn={false}
46
- seatData={seatData}
47
- statuses={statuses}
48
- ticketTypeTireRelationsArray={getTierRelationsArray(
49
- ticketTypeTierRelations
50
- )}
51
- width={Math.min(parentElement?.clientWidth || 800, 800)}
52
- height={Math.min(parentElement?.clientWidth || 800, 800)}
53
- isBlockMap={seatMapType === 'block'}
54
- isTableMap={seatMapType === 'table'}
55
- predefinedSeats={predefinedSeats}
56
- />
57
- )
39
+ if (parentElement) {
40
+ let mapComponent = null
41
+
42
+ if (!(seatData && statuses) || isLoadingSeatMapData) {
43
+ mapComponent = <Loader />
44
+ } else {
45
+ mapComponent = (
46
+ <SeatMapView
47
+ disabled={isReserving}
48
+ loading={isReserving}
49
+ events={seatMapEvents}
50
+ isSelectionOn={false}
51
+ seatData={seatData}
52
+ statuses={statuses}
53
+ ticketTypeTireRelationsArray={getTierRelationsArray(ticketTypeTierRelations)}
54
+ width={Math.min(parentElement?.clientWidth || 800, 800)}
55
+ height={Math.min(parentElement?.clientWidth || 800, 800)}
56
+ isBlockMap={seatMapType === 'block'}
57
+ isTableMap={seatMapType === 'table'}
58
+ predefinedSeats={predefinedSeats}
59
+ />
60
+ )
61
+ }
58
62
 
59
63
  ReactDom.render(mapComponent, parentElement)
60
64
  }