import { useState, useRef, useEffect } from 'react' import cx from 'classnames' import { useRouter } from 'next/router' import { ThumbsdownIcon, ThumbsupIcon } from '@primer/octicons-react' import { useTranslation } from 'components/hooks/useTranslation' import { Link } from 'components/Link' import { sendEvent, EventType } from 'components/lib/events' import styles from './Survey.module.scss' enum ViewState { START = 'START', YES = 'YES', NO = 'NO', END = 'END', } export const Survey = () => { const { asPath } = useRouter() const { t } = useTranslation('survey') const [state, setState] = useState(ViewState.START) const [isEmailError, setIsEmailError] = useState(false) const formRef = useRef(null) useEffect(() => { // Always reset the form if navigating to a new page because what // you might have said or started to say belongs exclusively to // to the page you started on. setState(ViewState.START) }, [asPath]) useEffect(() => { // After the form is submitted we need to manually set the focus since we // remove the form inputs after submit. The privacy policy link is the // next focusable element in the footer so we focus that. if (state === ViewState.END) { document .querySelector( 'footer a[href="/github/site-policy/github-privacy-statement"]' ) ?.focus() } }, [state]) function vote(state: ViewState) { return () => { trackEvent(getFormData()) setState(state) } } // Though we set `type="email"` on the email address input which gives us browser // validation of the field, that has accessibility issues (e.g. some screen // readers won't read the error message) so we need to do manual validation // ourselves. function handleEmailInputChange() { const emailRegex = /[^@\s.][^@\s]*@\[?[a-z0-9.-]+\]?/i const surveyEmail = getFormData()?.get('survey-email')?.toString() if (surveyEmail?.length === 0 || surveyEmail?.match(emailRegex)) { setIsEmailError(false) } else { setIsEmailError(true) } } function submit(evt: React.FormEvent) { evt.preventDefault() trackEvent(getFormData()) if (!isEmailError) { setState(ViewState.END) setIsEmailError(false) } } function getFormData() { if (!formRef.current) return return new FormData(formRef.current) } return (

{t`able_to_find`}

{/* Honeypot: token isn't a real field */} {state !== ViewState.END && (
)} {[ViewState.YES, ViewState.NO].includes(state) && ( <>

{isEmailError && (

{t`email_validation`}

)}
{t`not_support`}
)} {state === ViewState.END && (

{t`feedback`}

)} {t`privacy_policy`}
) } function trackEvent(formData: FormData | undefined) { if (!formData) return // Nota bene: convert empty strings to undefined return sendEvent({ type: EventType.survey, survey_token: (formData.get('survey-token') as string) || undefined, // Honeypot survey_vote: formData.get('survey-vote') === 'Y', survey_comment: (formData.get('survey-comment') as string) || undefined, survey_email: (formData.get('survey-email') as string) || undefined, }) }