widget.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import { useCallback, useState, ReactNode } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import AccessibleModal from '../../../../shared/components/accessible-modal'
  4. import { Modal } from 'react-bootstrap'
  5. type IntegrationLinkingWidgetProps = {
  6. logo: ReactNode
  7. title: string
  8. description: string
  9. helpPath: string
  10. hasFeature?: boolean
  11. statusIndicator?: ReactNode
  12. linked?: boolean
  13. linkPath: string
  14. unlinkPath: string
  15. unlinkConfirmationTitle: string
  16. unlinkConfirmationText: string
  17. }
  18. export function IntegrationLinkingWidget({
  19. logo,
  20. title,
  21. description,
  22. helpPath,
  23. hasFeature,
  24. statusIndicator,
  25. linked,
  26. linkPath,
  27. unlinkPath,
  28. unlinkConfirmationTitle,
  29. unlinkConfirmationText,
  30. }: IntegrationLinkingWidgetProps) {
  31. const { t } = useTranslation()
  32. const [showModal, setShowModal] = useState(false)
  33. const handleUnlinkClick = useCallback(() => {
  34. setShowModal(true)
  35. }, [])
  36. const handleModalHide = useCallback(() => {
  37. setShowModal(false)
  38. }, [])
  39. return (
  40. <div className="settings-widget-container">
  41. <div>{logo}</div>
  42. <div className="description-container">
  43. <div className="title-row">
  44. <h4>{title}</h4>
  45. {!hasFeature && (
  46. <span className="label label-info">{t('premium_feature')}</span>
  47. )}
  48. </div>
  49. <p>
  50. {description}{' '}
  51. <a href={helpPath} target="_blank" rel="noreferrer">
  52. {t('learn_more')}
  53. </a>
  54. </p>
  55. {linked && statusIndicator}
  56. </div>
  57. <div>
  58. <ActionButton
  59. hasFeature={hasFeature}
  60. upgradePath="user/subscription/plans"
  61. linked={linked}
  62. handleUnlinkClick={handleUnlinkClick}
  63. linkPath={linkPath}
  64. />
  65. </div>
  66. <UnlinkConfirmationModal
  67. show={showModal}
  68. title={unlinkConfirmationTitle}
  69. content={unlinkConfirmationText}
  70. unlinkPath={unlinkPath}
  71. handleHide={handleModalHide}
  72. />
  73. </div>
  74. )
  75. }
  76. type ActionButtonProps = {
  77. hasFeature?: boolean
  78. upgradePath: string
  79. linked?: boolean
  80. handleUnlinkClick: () => void
  81. linkPath: string
  82. }
  83. function ActionButton({
  84. hasFeature,
  85. upgradePath,
  86. linked,
  87. handleUnlinkClick,
  88. linkPath,
  89. }: ActionButtonProps) {
  90. const { t } = useTranslation()
  91. if (!hasFeature) {
  92. return (
  93. <a href={upgradePath} className="btn btn-info text-capitalize">
  94. {t('upgrade')}
  95. </a>
  96. )
  97. } else if (linked) {
  98. return (
  99. <button className="btn btn-danger" onClick={handleUnlinkClick}>
  100. {t('unlink')}
  101. </button>
  102. )
  103. } else {
  104. return (
  105. <a href={linkPath} className="btn btn-primary text-capitalize">
  106. {t('link')}
  107. </a>
  108. )
  109. }
  110. }
  111. type UnlinkConfirmModalProps = {
  112. show: boolean
  113. title: string
  114. content: string
  115. unlinkPath: string
  116. handleHide: () => void
  117. }
  118. function UnlinkConfirmationModal({
  119. show,
  120. title,
  121. content,
  122. unlinkPath,
  123. handleHide,
  124. }: UnlinkConfirmModalProps) {
  125. const { t } = useTranslation()
  126. return (
  127. <AccessibleModal show={show} onHide={handleHide}>
  128. <Modal.Header closeButton>
  129. <Modal.Title>{title}</Modal.Title>
  130. </Modal.Header>
  131. <Modal.Body className="modal-body-share">
  132. <p>{content}</p>
  133. </Modal.Body>
  134. <Modal.Footer>
  135. <button className="btn btn-default" onClick={handleHide}>
  136. {t('cancel')}
  137. </button>
  138. <a href={unlinkPath} className="btn btn-danger text-capitalize">
  139. {t('unlink')}
  140. </a>
  141. </Modal.Footer>
  142. </AccessibleModal>
  143. )
  144. }