mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2025-07-29 23:00:08 +02:00
211 lines
5.8 KiB
TypeScript
211 lines
5.8 KiB
TypeScript
import OLButton from '@/features/ui/components/ol/ol-button'
|
|
import OLForm from '@/features/ui/components/ol/ol-form'
|
|
import OLFormCheckbox from '@/features/ui/components/ol/ol-form-checkbox'
|
|
import OLFormGroup from '@/features/ui/components/ol/ol-form-group'
|
|
import OLIconButton from '@/features/ui/components/ol/ol-icon-button'
|
|
import { OLToast } from '@/features/ui/components/ol/ol-toast'
|
|
import { OLToastContainer } from '@/features/ui/components/ol/ol-toast-container'
|
|
import { useEditorContext } from '@/shared/context/editor-context'
|
|
import useTutorial from '@/shared/hooks/promotions/use-tutorial'
|
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
import { sendMB } from '@/infrastructure/event-tracking'
|
|
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
type EditorSurveyPage = 'ease-of-use' | 'meets-my-needs' | 'thank-you'
|
|
|
|
export default function EditorSurvey() {
|
|
return (
|
|
<OLToastContainer className="editor-survey-toast">
|
|
<EditorSurveyContent />
|
|
</OLToastContainer>
|
|
)
|
|
}
|
|
|
|
const TUTORIAL_KEY = 'editor-popup-ux-survey'
|
|
|
|
const EditorSurveyContent = () => {
|
|
const [easeOfUse, setEaseOfUse] = useState<number | null>(null)
|
|
const [meetsMyNeeds, setMeetsMyNeeds] = useState<number | null>(null)
|
|
const [page, setPage] = useState<EditorSurveyPage>('ease-of-use')
|
|
const { inactiveTutorials } = useEditorContext()
|
|
const hasCompletedSurvey = inactiveTutorials.includes(TUTORIAL_KEY)
|
|
const newEditor = useIsNewEditorEnabled()
|
|
|
|
const { t } = useTranslation()
|
|
|
|
const {
|
|
tryShowingPopup: tryShowingSurvey,
|
|
showPopup: showSurvey,
|
|
dismissTutorial: dismissSurvey,
|
|
completeTutorial: completeSurvey,
|
|
} = useTutorial(TUTORIAL_KEY, {
|
|
name: TUTORIAL_KEY,
|
|
})
|
|
|
|
useEffect(() => {
|
|
if (!hasCompletedSurvey) {
|
|
tryShowingSurvey()
|
|
}
|
|
}, [hasCompletedSurvey, tryShowingSurvey])
|
|
|
|
const onSubmit = useCallback(() => {
|
|
sendMB('editor-survey-submit', {
|
|
easeOfUse,
|
|
meetsMyNeeds,
|
|
newEditor,
|
|
})
|
|
setPage('thank-you')
|
|
completeSurvey({ event: 'promo-click', action: 'complete' })
|
|
}, [easeOfUse, meetsMyNeeds, completeSurvey, newEditor])
|
|
|
|
if (!showSurvey && page !== 'thank-you') {
|
|
return null
|
|
}
|
|
|
|
if (page === 'ease-of-use') {
|
|
return (
|
|
<OLToast
|
|
className="editor-survey-question-toast"
|
|
content={
|
|
<EditorSurveyQuestion
|
|
questionText={t('overleaf_is_easy_to_use')}
|
|
name="ease-of-use"
|
|
buttonText={t('next')}
|
|
onButtonClick={() => setPage('meets-my-needs')}
|
|
value={easeOfUse}
|
|
onValueChange={setEaseOfUse}
|
|
onDismiss={dismissSurvey}
|
|
/>
|
|
}
|
|
type="info"
|
|
/>
|
|
)
|
|
}
|
|
if (page === 'meets-my-needs') {
|
|
return (
|
|
<OLToast
|
|
className="editor-survey-question-toast"
|
|
content={
|
|
<EditorSurveyQuestion
|
|
questionText={t('overleafs_functionality_meets_my_needs')}
|
|
name="meets-my-needs"
|
|
buttonText={t('submit_title')}
|
|
onButtonClick={onSubmit}
|
|
value={meetsMyNeeds}
|
|
onValueChange={setMeetsMyNeeds}
|
|
onDismiss={dismissSurvey}
|
|
/>
|
|
}
|
|
type="info"
|
|
/>
|
|
)
|
|
}
|
|
|
|
return <OLToast type="info" content={t('thank_you')} autoHide delay={3000} />
|
|
}
|
|
|
|
const EditorSurveyQuestion = ({
|
|
onDismiss,
|
|
name,
|
|
questionText,
|
|
buttonText,
|
|
onButtonClick,
|
|
value,
|
|
onValueChange,
|
|
}: {
|
|
onDismiss: () => void
|
|
name: string
|
|
questionText: string
|
|
buttonText: string
|
|
onButtonClick: () => void
|
|
value: number | null
|
|
onValueChange: (newValue: number) => void
|
|
}) => {
|
|
const { t } = useTranslation()
|
|
|
|
const options = useMemo(
|
|
() => [
|
|
{
|
|
value: 1,
|
|
description: t('strongly_disagree'),
|
|
},
|
|
{
|
|
value: 2,
|
|
description: t('disagree'),
|
|
},
|
|
{
|
|
value: 3,
|
|
description: t('neither_agree_nor_disagree'),
|
|
},
|
|
{
|
|
value: 4,
|
|
description: t('agree'),
|
|
},
|
|
{
|
|
value: 5,
|
|
description: t('strongly_agree'),
|
|
},
|
|
],
|
|
[t]
|
|
)
|
|
|
|
const onChange = useCallback(
|
|
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const newValue = event.target.value
|
|
if (newValue) {
|
|
onValueChange(Number(newValue))
|
|
}
|
|
},
|
|
[onValueChange]
|
|
)
|
|
|
|
return (
|
|
<div className="editor-survey-question">
|
|
<div className="editor-survey-question-top-line">
|
|
<div>{t('your_feedback_matters_answer_two_quick_questions')}</div>
|
|
<OLIconButton
|
|
variant="ghost"
|
|
size="sm"
|
|
icon="close"
|
|
accessibilityLabel={t('close')}
|
|
onClick={onDismiss}
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="editor-survey-question-label" htmlFor={name}>
|
|
{questionText}
|
|
</label>
|
|
<OLForm className="editor-survey-question-form">
|
|
<OLFormGroup className="editor-survey-question-options">
|
|
{options.map(({ value: optionValue, description }) => (
|
|
<OLFormCheckbox
|
|
key={optionValue}
|
|
name={name}
|
|
type="radio"
|
|
value={optionValue}
|
|
id={optionValue.toString()}
|
|
label={optionValue}
|
|
checked={optionValue === value}
|
|
onChange={onChange}
|
|
aria-label={`${optionValue} ${description}`}
|
|
/>
|
|
))}
|
|
</OLFormGroup>
|
|
</OLForm>
|
|
<div className="editor-survey-option-labels">
|
|
<div>{t('strongly_disagree')}</div>
|
|
<div>{t('strongly_agree')}</div>
|
|
</div>
|
|
</div>
|
|
<OLButton
|
|
size="sm"
|
|
variant="secondary"
|
|
onClick={onButtonClick}
|
|
disabled={!value}
|
|
>
|
|
{buttonText}
|
|
</OLButton>
|
|
</div>
|
|
)
|
|
}
|