upgrade-prompt.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import OLBadge from '@/shared/components/ol/ol-badge'
  2. import OLButton from '@/shared/components/ol/ol-button'
  3. import OLCloseButton from '@/shared/components/ol/ol-close-button'
  4. import OLCol from '@/shared/components/ol/ol-col'
  5. import OLRow from '@/shared/components/ol/ol-row'
  6. import MaterialIcon from '@/shared/components/material-icon'
  7. import { PropsWithChildren } from 'react'
  8. import { Container } from 'react-bootstrap'
  9. import { Trans, useTranslation } from 'react-i18next'
  10. type IconListItemProps = PropsWithChildren<{
  11. icon: string
  12. }>
  13. function IconListItem({ icon, children }: IconListItemProps) {
  14. return (
  15. <li className="d-flex align-items-center">
  16. <div className="flex-shrink-0">
  17. <MaterialIcon type={icon} />
  18. </div>
  19. <div className="flex-grow-1 ms-2">{children}</div>
  20. </li>
  21. )
  22. }
  23. type PlansLinkProps = {
  24. itmCampaign: string
  25. onClick?: React.MouseEventHandler<HTMLAnchorElement>
  26. }
  27. function PlansLink({
  28. children,
  29. itmCampaign,
  30. onClick,
  31. }: PropsWithChildren<PlansLinkProps>) {
  32. return (
  33. <a
  34. key="compare_plans_link"
  35. href={`/user/subscription/choose-your-plan?itm-campaign=${itmCampaign}`}
  36. target="_blank"
  37. rel="noreferrer"
  38. onClick={onClick}
  39. >
  40. {children}
  41. <MaterialIcon type="open_in_new" />
  42. </a>
  43. )
  44. }
  45. type UpgradePromptProps = {
  46. title: string
  47. summary: string
  48. onClose: () => void
  49. planPricing: { student: string; standard: string }
  50. itmCampaign: string
  51. isStudent?: boolean
  52. onClickInfoLink?: React.MouseEventHandler<HTMLAnchorElement>
  53. onClickPaywall?: React.MouseEventHandler<HTMLAnchorElement>
  54. }
  55. export function UpgradePrompt({
  56. title,
  57. summary,
  58. onClose,
  59. planPricing,
  60. itmCampaign,
  61. isStudent = false,
  62. onClickInfoLink,
  63. onClickPaywall,
  64. }: UpgradePromptProps) {
  65. const { t } = useTranslation()
  66. const planPrice = isStudent ? planPricing.student : planPricing.standard
  67. const planCode = isStudent
  68. ? 'student_free_trial_7_days'
  69. : 'collaborator_free_trial_7_days'
  70. return (
  71. <Container className="upgrade-prompt">
  72. <OLRow className="justify-content-end">
  73. <OLCloseButton onClick={() => onClose()} />
  74. </OLRow>
  75. <OLRow className="text-center">
  76. <h2 className="my-0 upgrade-prompt-title">{title}</h2>
  77. <p className="upgrade-prompt-summary">{summary}</p>
  78. </OLRow>
  79. <OLRow className="g-3">
  80. <OLCol md={6} className="upgrade-prompt-card-container">
  81. <div className="g-0 upgrade-prompt-card upgrade-prompt-card-premium">
  82. <OLRow className="justify-content-between">
  83. <OLCol>
  84. <h3>{isStudent ? t('student') : t('standard')}</h3>
  85. </OLCol>
  86. <OLCol xs="auto">
  87. <OLBadge className="badge-premium-gradient">
  88. {t('recommended')}
  89. </OLBadge>
  90. </OLCol>
  91. </OLRow>
  92. <OLRow>
  93. <p className="upgrade-prompt-price">
  94. <span className="upgrade-prompt-price-number">{planPrice}</span>{' '}
  95. {t('per_month')}
  96. </p>
  97. </OLRow>
  98. <OLRow>
  99. <ul className="upgrade-prompt-list">
  100. <IconListItem icon="hourglass_top">
  101. {t('24x_more_compile_time')}
  102. </IconListItem>
  103. <IconListItem icon="group_add">
  104. {t('collabs_per_proj', { count: 10 })}
  105. </IconListItem>
  106. <IconListItem icon="history">
  107. {t('unlimited_document_history')}
  108. </IconListItem>
  109. </ul>
  110. </OLRow>
  111. <OLRow className="mt-auto">
  112. <a
  113. className="btn btn-premium"
  114. href={`/user/subscription/new?planCode=${planCode}&itm-campaign=${itmCampaign}`}
  115. onClick={onClickPaywall}
  116. target="_blank"
  117. rel="noreferrer"
  118. >
  119. {t('try_for_free')}
  120. </a>
  121. </OLRow>
  122. </div>
  123. </OLCol>
  124. <OLCol md={6} className="upgrade-prompt-card-container">
  125. <div className="g-0 upgrade-prompt-card upgrade-prompt-card-free">
  126. <OLRow>
  127. <h3>{t('free')}</h3>
  128. </OLRow>
  129. <OLRow>
  130. <p className="upgrade-prompt-price">
  131. {/* Invisible span here to hold the correct height to match a card with a price */}
  132. <span className="upgrade-prompt-price-number invisible" />
  133. {t('your_current_plan')}
  134. </p>
  135. </OLRow>
  136. <OLRow>
  137. <ul className="upgrade-prompt-list">
  138. <IconListItem icon="hourglass_bottom">
  139. {t('basic_compile_time')}
  140. </IconListItem>
  141. <IconListItem icon="person">
  142. {t('collabs_per_proj', { count: 1 })}
  143. </IconListItem>
  144. <IconListItem icon="history_off">
  145. {t('limited_document_history')}
  146. </IconListItem>
  147. </ul>
  148. </OLRow>
  149. <OLRow className="mt-auto">
  150. <OLButton variant="secondary" onClick={() => onClose()}>
  151. {t('continue_with_free_plan')}
  152. </OLButton>
  153. </OLRow>
  154. </div>
  155. </OLCol>
  156. </OLRow>
  157. <OLRow className="text-center">
  158. <p className="upgrade-prompt-all-plans">
  159. {/* eslint-disable react/jsx-key */}
  160. <Trans
  161. i18nKey="compare_all_plans"
  162. components={[
  163. <PlansLink onClick={onClickInfoLink} itmCampaign={itmCampaign} />,
  164. ]}
  165. />
  166. {/* eslint-disable react/jsx-key */}
  167. </p>
  168. </OLRow>
  169. </Container>
  170. )
  171. }