pause-modal.tsx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import { useTranslation } from 'react-i18next'
  2. import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context'
  3. import { useCallback, useMemo, useState } from 'react'
  4. import { postJSON } from '@/infrastructure/fetch-json'
  5. import { useLocation } from '@/shared/hooks/use-location'
  6. import {
  7. OLModal,
  8. OLModalBody,
  9. OLModalHeader,
  10. } from '@/shared/components/ol/ol-modal'
  11. import { Select } from '@/shared/components/select'
  12. import OLFormGroup from '@/shared/components/ol/ol-form-group'
  13. import Button from '@/shared/components/button/button'
  14. import { Stack } from 'react-bootstrap'
  15. import { debugConsole } from '@/utils/debugging'
  16. import * as eventTracking from '../../../../infrastructure/event-tracking'
  17. import PauseDuck from '../../images/pause-duck.svg'
  18. import GenericErrorAlert from './generic-error-alert'
  19. import { PaidSubscription } from '../../../../../../types/subscription/dashboard/subscription'
  20. const pauseMonthDurationOptions = [1, 2, 3]
  21. export const PAUSE_SUB_MODAL_ID = 'pause-subscription'
  22. export default function PauseSubscriptionModal() {
  23. const { t } = useTranslation()
  24. const {
  25. handleCloseModal,
  26. modalIdShown,
  27. setShowCancellation,
  28. personalSubscription,
  29. } = useSubscriptionDashboardContext()
  30. const [inflight, setInflight] = useState(false)
  31. const [pauseError, setPauseError] = useState(false)
  32. const [selectedDuration, setSelectedDuration] = useState(1)
  33. const location = useLocation()
  34. function handleCancelSubscriptionClick() {
  35. const subscription = personalSubscription as PaidSubscription
  36. eventTracking.sendMB('subscription-page-cancel-button-click', {
  37. plan_code: subscription?.planCode,
  38. is_trial:
  39. subscription?.payment.trialEndsAtFormatted &&
  40. subscription?.payment.trialEndsAt &&
  41. new Date(subscription.payment.trialEndsAt).getTime() > Date.now(),
  42. })
  43. setShowCancellation(true)
  44. }
  45. const pauseSelectItems = useMemo(
  46. () =>
  47. pauseMonthDurationOptions.map(month => ({
  48. key: month,
  49. value: `${month} ${t('month', { count: month })}`,
  50. })),
  51. [t]
  52. )
  53. const handleConfirmPauseSubscriptionClick = useCallback(async () => {
  54. if (!selectedDuration) {
  55. return
  56. }
  57. setPauseError(false)
  58. setInflight(true)
  59. try {
  60. await postJSON(`/user/subscription/pause/${selectedDuration}`)
  61. const newUrl = new URL(location.toString())
  62. newUrl.searchParams.set('flash', 'paused')
  63. window.history.replaceState(null, '', newUrl)
  64. location.reload()
  65. } catch (err) {
  66. debugConsole.error('error pausing subscription', err)
  67. setInflight(false)
  68. setPauseError(true)
  69. }
  70. }, [location, selectedDuration])
  71. if (modalIdShown !== PAUSE_SUB_MODAL_ID) {
  72. return null
  73. }
  74. return (
  75. <OLModal
  76. id={PAUSE_SUB_MODAL_ID}
  77. show
  78. animation
  79. onHide={handleCloseModal}
  80. backdrop="static"
  81. >
  82. <OLModalBody>
  83. <OLModalHeader style={{ border: 0 }} />
  84. <img
  85. src={PauseDuck}
  86. alt="Need to duck out for a while?"
  87. style={{ display: 'block', margin: '-32px auto 0 auto' }}
  88. />
  89. {pauseError && <GenericErrorAlert />}
  90. <h4>{t('why_not_pause_instead')}</h4>
  91. <p>{t('your_current_plan_gives_you')}</p>
  92. <span>{t('dont_forget_you_currently_have')}</span>
  93. <ul>
  94. {personalSubscription?.plan?.features?.collaborators !== 1 && (
  95. <li>{t('more_collabs_per_project')}</li>
  96. )}
  97. <li>{t('more_compile_time')}</li>
  98. <li>{t('features_like_track_changes')}</li>
  99. <li>{t('integrations_like_github')}</li>
  100. </ul>
  101. <OLFormGroup>
  102. <Select
  103. label={t('pause_subscription_for')}
  104. items={pauseSelectItems}
  105. itemToString={x => String(x?.value)}
  106. itemToKey={x => String(x.key)}
  107. defaultText={`1 ${t('month')}`}
  108. onSelectedItemChanged={item => setSelectedDuration(item?.key || 0)}
  109. />
  110. </OLFormGroup>
  111. <Stack gap={2}>
  112. <Button
  113. onClick={handleConfirmPauseSubscriptionClick}
  114. disabled={inflight}
  115. >
  116. {t('pause_subscription')}
  117. </Button>
  118. <Button
  119. onClick={handleCancelSubscriptionClick}
  120. disabled={inflight}
  121. variant="danger-ghost"
  122. >
  123. {t('cancel_subscription')}
  124. </Button>
  125. </Stack>
  126. </OLModalBody>
  127. </OLModal>
  128. )
  129. }