import { Button, Input, Typography, Dropdown, Modal } from 'antd'; import { isValidUrl } from 'App/utils'; import React from 'react'; import { withSiteId, usabilityTesting, usabilityTestingView, usabilityTestingEdit, } from 'App/routes'; import { useParams, useHistory, Prompt } from 'react-router-dom'; import Breadcrumb from 'Shared/Breadcrumb'; import { EditOutlined, DeleteOutlined, MoreOutlined } from '@ant-design/icons'; import { Power, Info, ListTodo } from 'lucide-react'; import { useModal } from 'App/components/Modal'; import { observer } from 'mobx-react-lite'; import { useStore } from 'App/mstore'; import { confirm } from 'UI'; import usePageTitle from 'App/hooks/usePageTitle'; import { toast } from 'react-toastify'; import StepsModal from './StepsModal'; import SidePanel from './SidePanel'; import { useTranslation } from 'react-i18next'; const menuItems = [ { key: '1', label: 'Edit Title and Description', icon: , }, { key: '2', label: 'Delete', icon: , }, ]; function TestEdit() { const { t } = useTranslation(); // @ts-ignore const { siteId, testId } = useParams(); const [hasChanged, setHasChanged] = React.useState(testId === 'new'); const [typingEnabled, setTypingEnabled] = React.useState(true); const { uxtestingStore } = useStore(); const [newTestTitle, setNewTestTitle] = React.useState(''); const [newTestDescription, setNewTestDescription] = React.useState(''); const [conclusion, setConclusion] = React.useState(''); const [guidelines, setGuidelines] = React.useState(''); const [isModalVisible, setIsModalVisible] = React.useState(false); const [isConclusionEditing, setIsConclusionEditing] = React.useState(false); const [isOverviewEditing, setIsOverviewEditing] = React.useState(false); const { showModal, hideModal } = useModal(); const history = useHistory(); usePageTitle( `Usability Tests | ${uxtestingStore.instance ? 'Edit' : 'Create'}`, ); React.useEffect(() => { if ( uxtestingStore.instanceCreationSiteId && siteId !== uxtestingStore.instanceCreationSiteId ) { history.push(withSiteId(usabilityTesting(), siteId)); } }, [siteId]); React.useEffect(() => { if (testId && testId !== 'new') { uxtestingStore.getTestData(testId).then((inst) => { if (inst) { setConclusion(inst.conclusionMessage || ''); setGuidelines(inst.guidelines || ''); } }); } else if (!uxtestingStore.instance) { history.push(withSiteId(usabilityTesting(), siteId)); } else { setConclusion(uxtestingStore.instance!.conclusionMessage); setGuidelines(uxtestingStore.instance!.guidelines); } }, []); if (!uxtestingStore.instance) { return
{t('Loading...')}
; } const onSave = (isPreview?: boolean) => { setHasChanged(false); if (testId && testId !== 'new') { uxtestingStore .updateTest(uxtestingStore.instance!, isPreview) .then((testId) => { if (isPreview) { window.open( `${uxtestingStore.instance!.startingPath}?oruxt=${testId}`, '_blank', 'noopener,noreferrer', ); } else { toast.success( t( 'The usability test is now live and accessible to participants.', ), ); history.push( withSiteId(usabilityTestingView(testId!.toString()), siteId), ); } }); } else { uxtestingStore.createNewTest(isPreview).then((test) => { if (isPreview) { window.open( `${test.startingPath}?oruxt=${test.testId}`, '_blank', 'noopener,noreferrer', ); history.replace( withSiteId(usabilityTestingEdit(test.testId), siteId), ); } else { history.push(withSiteId(usabilityTestingView(test.testId), siteId)); } }); } }; const onClose = (confirmed: boolean) => { if (confirmed) { uxtestingStore.instance!.setProperty('title', newTestTitle); uxtestingStore.instance!.setProperty('description', newTestDescription); } setNewTestDescription(''); setNewTestTitle(''); setIsModalVisible(false); }; const onMenuClick = async ({ key }: { key: string }) => { if (key === '1') { setNewTestTitle(uxtestingStore.instance!.title); setNewTestDescription(uxtestingStore.instance!.description); setIsModalVisible(true); } if (key === '2') { if ( await confirm({ confirmation: t( 'Are you sure you want to delete this usability test? This action cannot be undone.', ), }) ) { uxtestingStore.deleteTest(testId).then(() => { history.push(withSiteId(usabilityTesting(), siteId)); }); } } }; const isPublished = uxtestingStore.instance.status !== undefined && uxtestingStore.instance.status !== 'preview'; const isStartingPointValid = isValidUrl(uxtestingStore.instance.startingPath); return (
t('You have unsaved changes. Are you sure you want to leave?') } /> onClose(true)} onCancel={() => onClose(false)} footer={ } > {t('Title')} { setHasChanged(true); setNewTestTitle(e.target.value); }} /> {t('Test Objective (optional)')} { setHasChanged(true); setNewTestDescription(e.target.value); }} placeholder={t( 'Share a brief statement about what you aim to discover through this study.', )} />
{uxtestingStore.instance.title} {uxtestingStore.instance.description}
 {t('Starting point')} { setHasChanged(true); let { value } = e.target; if (value.startsWith('https://')) { value = value.replace('https://', ''); } uxtestingStore.instance!.setProperty( 'startingPath', `https://${value}`, ); }} /> {uxtestingStore.instance!.startingPath === 'https://' || isStartingPointValid ? ( {t('The test will start on this page. A special link from this will be created for you to share with participants only.')} ) : ( {t('Invalid starting point.')} )}
 {t('Introduction and Guidelines for Participants')} {isOverviewEditing ? ( { setHasChanged(true); setGuidelines(e.target.value); }} /> ) : (
{uxtestingStore.instance?.guidelines?.length ? uxtestingStore.instance.guidelines : t( 'Provide an overview of this usability test to and input guidelines that can be of assistance to users at any point during the test.', )}
)}
{isOverviewEditing ? ( <> ) : ( )}
 {t('Tasks')} {uxtestingStore.instance!.tasks.map((task, index) => (
{t('🎉 Conclusion')}
{isConclusionEditing ? ( { setHasChanged(true); setConclusion(e.target.value); }} /> ) : ( {uxtestingStore.instance!.conclusionMessage} )}
{isConclusionEditing ? ( <> ) : ( )}
onSave(false)} onPreview={() => onSave(true)} />
); } export function Step({ buttons, ind, title, description, hover, }: { buttons?: React.ReactNode; ind: number; title: string; description: string | null; hover?: boolean; }) { const safeTitle = title.length > 120 ? `${title.slice(0, 120)}...` : title; const safeDescription = description && description?.length > 300 ? `${description.slice(0, 300)}...` : description; return (
{ind + 1}
{safeTitle}
{safeDescription}
{buttons}
); } export default observer(TestEdit);