payment-error-notification.tsx 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { FetchError } from '@/infrastructure/fetch-json'
  2. import { Trans } from 'react-i18next'
  3. import OLNotification from '@/shared/components/ol/ol-notification'
  4. import { billingPortalUrl } from '../../data/subscription-url'
  5. type Props = {
  6. error: FetchError | null
  7. }
  8. export default function PaymentErrorNotification({ error }: Props) {
  9. if (!error) {
  10. return
  11. }
  12. let message
  13. switch (error.data?.adviceCode) {
  14. case 'try_again_later':
  15. message = (
  16. <Trans
  17. i18nKey="payment_error_intermittent_error"
  18. components={[
  19. /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
  20. <a href="/contact" target="_blank" />,
  21. ]}
  22. />
  23. )
  24. break
  25. case 'do_not_try_again':
  26. case 'confirm_card_data':
  27. message = (
  28. <Trans
  29. i18nKey="payment_error_update_payment_method"
  30. components={[
  31. /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
  32. <a href={billingPortalUrl} />,
  33. ]}
  34. />
  35. )
  36. break
  37. default:
  38. // clientSecret indicates they needed to pass a 3DS challenge
  39. if (error.data?.clientSecret) {
  40. message = (
  41. <Trans
  42. i18nKey="payment_error_3ds_failed"
  43. components={[
  44. /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
  45. <a href="/contact" target="_blank" />,
  46. ]}
  47. />
  48. )
  49. } else {
  50. message = (
  51. <Trans
  52. i18nKey="payment_error_generic"
  53. components={[
  54. /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
  55. <a href="/contact" target="_blank" />,
  56. ]}
  57. />
  58. )
  59. }
  60. }
  61. return <OLNotification type="error" aria-live="polite" content={message} />
  62. }