import React, { createContext, useCallback, useContext, useEffect, useState, } from 'react' import PropTypes from 'prop-types' import ShareProjectModalContent from './share-project-modal-content' import { useProjectContext, projectShape, } from '../../../shared/context/project-context' import { useSplitTestContext } from '../../../shared/context/split-test-context' import { sendMB } from '../../../infrastructure/event-tracking' type ShareProjectContextValue = { updateProject: (data: unknown) => void monitorRequest: >(request: () => T) => T inFlight: boolean setInFlight: React.Dispatch< React.SetStateAction > error: string | undefined setError: React.Dispatch< React.SetStateAction > } const ShareProjectContext = createContext( undefined ) export function useShareProjectContext() { const context = useContext(ShareProjectContext) if (!context) { throw new Error( 'useShareProjectContext is only available inside ShareProjectProvider' ) } return context } type ShareProjectModalProps = { handleHide: () => void show: boolean animation?: boolean } const ShareProjectModal = React.memo(function ShareProjectModal({ handleHide, show, animation = true, }: ShareProjectModalProps) { const [inFlight, setInFlight] = useState(false) const [error, setError] = useState() const project = useProjectContext(projectShape) const { splitTestVariants } = useSplitTestContext({ splitTestVariants: PropTypes.object, }) // send tracking event when the modal is opened useEffect(() => { if (show) { sendMB('share-modal-opened', { splitTestVariant: splitTestVariants['null-test-share-modal'], project_id: project._id, }) } }, [splitTestVariants, project._id, show]) // reset error when the modal is opened useEffect(() => { if (show) { setError(undefined) } }, [show]) // close the modal if not in flight const cancel = useCallback(() => { if (!inFlight) { handleHide() } }, [handleHide, inFlight]) // update `error` and `inFlight` while sending a request const monitorRequest = useCallback(request => { setError(undefined) setInFlight(true) const promise = request() promise.catch((error: { data?: Record }) => { setError( error.data?.errorReason || error.data?.error || 'generic_something_went_wrong' ) }) promise.finally(() => { setInFlight(false) }) return promise }, []) // merge the new data with the old project data const updateProject = useCallback( data => Object.assign(project, data), [project] ) if (!project) { return null } return ( ) }) export default ShareProjectModal