use-tutorial.tsx 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import { useCallback, useState } from 'react'
  2. import * as eventTracking from '@/infrastructure/event-tracking'
  3. import { postJSON } from '@/infrastructure/fetch-json'
  4. import { debugConsole } from '@/utils/debugging'
  5. import { useEditorContext } from '@/shared/context/editor-context'
  6. export const useTutorial = (
  7. tutorialKey: string,
  8. eventData: Record<string, any> = {}
  9. ) => {
  10. const [showPopup, setShowPopup] = useState(false)
  11. const { deactivateTutorial, currentPopup, setCurrentPopup } =
  12. useEditorContext()
  13. const completeTutorial = useCallback(
  14. async ({
  15. event = 'promo-click',
  16. action = 'complete',
  17. ...rest
  18. }: {
  19. event: 'promo-click' | 'promo-dismiss'
  20. action: 'complete' | 'postpone'
  21. } & Record<string, any>) => {
  22. eventTracking.sendMB(event, { ...eventData, ...rest })
  23. try {
  24. await postJSON(`/tutorial/${tutorialKey}/${action}`)
  25. } catch (err) {
  26. debugConsole.error(err)
  27. }
  28. setShowPopup(false)
  29. deactivateTutorial(tutorialKey)
  30. },
  31. [deactivateTutorial, eventData, tutorialKey]
  32. )
  33. const dismissTutorial = useCallback(async () => {
  34. await completeTutorial({
  35. event: 'promo-dismiss',
  36. action: 'complete',
  37. })
  38. }, [completeTutorial])
  39. const maybeLater = useCallback(async () => {
  40. await completeTutorial({
  41. event: 'promo-click',
  42. action: 'postpone',
  43. button: 'maybe-later',
  44. })
  45. }, [completeTutorial])
  46. // try to show the popup if we don't already have one showing, returns true if it can show, false if it can't
  47. const tryShowingPopup = useCallback(
  48. (eventName: string = 'promo-prompt') => {
  49. if (currentPopup === null) {
  50. setCurrentPopup(tutorialKey)
  51. setShowPopup(true)
  52. eventTracking.sendMB(eventName, eventData)
  53. return true
  54. }
  55. return false
  56. },
  57. [currentPopup, setCurrentPopup, tutorialKey, eventData]
  58. )
  59. const clearPopup = useCallback(() => {
  60. // popups should only clear themselves, in cases they need to cleanup or shouldnt show anymore
  61. // allow forcing the clear if needed, eg: higher prio alert needs to show
  62. if (currentPopup === tutorialKey) {
  63. setCurrentPopup(null)
  64. setShowPopup(false)
  65. }
  66. }, [setCurrentPopup, setShowPopup, currentPopup, tutorialKey])
  67. const clearAndShow = useCallback(
  68. (eventName: string = 'promo-prompt') => {
  69. setCurrentPopup(tutorialKey)
  70. setShowPopup(true)
  71. eventTracking.sendMB(eventName, eventData)
  72. },
  73. [setCurrentPopup, setShowPopup, tutorialKey, eventData]
  74. )
  75. return {
  76. completeTutorial,
  77. dismissTutorial,
  78. maybeLater,
  79. tryShowingPopup,
  80. clearPopup,
  81. clearAndShow,
  82. showPopup,
  83. }
  84. }
  85. export default useTutorial