import { durationFormatted } from 'App/date';
import usePageTitle from 'App/hooks/usePageTitle';
import { numberWithCommas } from 'App/utils';
import { getPdf2 } from 'Components/AssistStats/pdfGenerator';
import { useModal } from 'Components/Modal';
import LiveTestsModal from 'Components/UsabilityTesting/LiveTestsModal';
import React from 'react';
import { Button, Typography, Select, Space, Popover, Dropdown } from 'antd';
import { withSiteId, usabilityTesting, usabilityTestingEdit } from 'App/routes';
import { useParams, useHistory } from 'react-router-dom';
import Breadcrumb from 'Shared/Breadcrumb';
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
import {
EditOutlined,
ShareAltOutlined,
ArrowRightOutlined,
MoreOutlined,
UserOutlined,
UserDeleteOutlined,
CheckCircleOutlined,
FastForwardOutlined,
PauseCircleOutlined,
StopOutlined,
HourglassOutlined,
FilePdfOutlined,
DeleteOutlined,
ClockCircleOutlined,
} from '@ant-design/icons';
import SessionItem from 'Shared/SessionItem';
import { CopyButton, Loader, NoContent, Pagination } from 'UI';
import copy from 'copy-to-clipboard';
import { Stage } from 'Components/Funnels/FunnelWidget/FunnelWidget';
import { confirm } from 'UI';
import ResponsesOverview from './ResponsesOverview';
import ParticipantOverviewItem from 'Components/UsabilityTesting/ParticipantOverview';
const { Option } = Select;
const statusItems = [
{ value: 'in-progress', label: 'Ongoing', icon: },
{ value: 'paused', label: 'On Hold', icon: },
{ value: 'closed', label: 'Closed', icon: },
];
const menuItems = [
{
key: '1',
label: 'Download Results',
icon: ,
},
{
key: '2',
label: 'Edit',
icon: ,
},
{
key: '3',
label: 'Delete',
icon: ,
},
];
function TestOverview() {
// @ts-ignore
const { siteId, testId } = useParams();
const { showModal, hideModal } = useModal();
const { uxtestingStore } = useStore();
React.useEffect(() => {
uxtestingStore.getTest(testId);
}, [testId]);
if (!uxtestingStore.instance) {
return No data.;
} else {
document.title = `Usability Tests | ${uxtestingStore.instance.title}`;
}
const onPageChange = (page: number) => {
uxtestingStore.setSessionsPage(page);
};
return (
{uxtestingStore.instance.liveCount ? (
{uxtestingStore.instance.liveCount} participants are engaged in this usability test at
the moment.
) : null}
Open-ended task responses
{uxtestingStore.instance.responsesCount ? (
) : (
0 at the moment.
)}
Sessions
{/*
in your selection*/}
{/*
clear selection
*/}
{uxtestingStore.testSessions.list.map((session) => (
// @ts-ignore
))}
Showing{' '}
{(uxtestingStore.testSessions.page - 1) * 10 + 1}
{' '}
to{' '}
{(uxtestingStore.page - 1) * 10 + uxtestingStore.testSessions.list.length}
{' '}
of{' '}
{numberWithCommas(uxtestingStore.testSessions.total)}
{' '}
tests.
);
}
const ParticipantOverview = observer(() => {
const { uxtestingStore } = useStore();
return (
Participant Overview
{uxtestingStore.testStats ? (
Total Participants
>
}
firstNum={uxtestingStore.testStats.tests_attempts?.toString()}
/>
Completed all tasks
>
}
firstNum={
uxtestingStore.testStats.tests_attempts > 0
? `${Math.round(
(uxtestingStore.testStats.completed_all_tasks /
uxtestingStore.testStats.tests_attempts) *
100
)}%`
: undefined
}
addedNum={uxtestingStore.testStats.completed_all_tasks.toString()}
/>
Skipped tasks
>
}
firstNum={
uxtestingStore.testStats.tests_attempts > 0
? `${Math.round(
(uxtestingStore.testStats.tasks_skipped /
uxtestingStore.testStats.tests_attempts) *
100
)}%`
: undefined
}
addedNum={uxtestingStore.testStats.tasks_skipped.toString()}
/>
Aborted the test
>
}
firstNum={
uxtestingStore.testStats.tests_attempts > 0
? `${Math.round(
(uxtestingStore.testStats.tests_skipped /
uxtestingStore.testStats.tests_attempts) *
100
)}%`
: undefined
}
addedNum={uxtestingStore.testStats.tests_skipped.toString()}
/>
) : null}
);
});
const TaskSummary = observer(() => {
const { uxtestingStore } = useStore();
const [showAll, setShowAll] = React.useState(false);
const totalAttempts = uxtestingStore.testStats?.tests_attempts ?? 0;
const shouldHide = uxtestingStore.taskStats.length > 5;
const shownTasks = shouldHide
? showAll
? uxtestingStore.taskStats
: uxtestingStore.taskStats.slice(0, 5)
: uxtestingStore.taskStats;
return (
Task Summary
{uxtestingStore.taskStats.length ? (
Average completion time for all tasks:
{uxtestingStore.taskStats
? durationFormatted(
uxtestingStore.taskStats.reduce(
(stats, task) => stats + task.avgCompletionTime,
0
) / uxtestingStore.taskStats.length
)
: null}
) : null}
{!uxtestingStore.taskStats.length ?
: null}
{shownTasks.map((tst, index) => (
))}
{shouldHide ? (
setShowAll(!showAll)} className={'link mt-4'}>
{showAll ? 'Hide' : 'Show All'}
) : null}
);
});
const Title = observer(({ testId, siteId }: any) => {
const [truncate, setTruncate] = React.useState(true);
const { uxtestingStore } = useStore();
const history = useHistory();
const handleChange = (value: string) => {
uxtestingStore.updateTestStatus(value);
};
const onMenuClick = async ({ key }: any) => {
if (key === '1') {
void getPdf2();
}
if (key === '2') {
await redirectToEdit();
}
if (key === '3') {
if (
await confirm({
confirmation:
'Are you sure you want to delete this usability test? This action cannot be undone.',
})
) {
uxtestingStore.deleteTest(testId).then(() => {
history.push(withSiteId(usabilityTesting(), siteId));
});
}
}
};
if (!uxtestingStore.instance) {
return null;
}
const truncatedDescr =
uxtestingStore.instance.description.length > 250 && truncate
? uxtestingStore.instance?.description.substring(0, 250) + '...'
: uxtestingStore.instance?.description;
const redirectToEdit = async () => {
if (
await confirm({
confirmation:
'This test already has responses, making edits at this stage may result in confusing outcomes.',
confirmButton: 'Edit',
})
) {
history.push(withSiteId(usabilityTestingEdit(testId), siteId));
}
};
return (
{uxtestingStore.instance!.title}
{`${uxtestingStore.instance!.startingPath}?oruxt=${
uxtestingStore.instance!.testId
}`}
}
>
}>
{truncatedDescr}
{uxtestingStore.instance.description.length > 250 ? (
setTruncate(!truncate)}>
{truncate ? 'Show more' : 'Show less'}
) : null}
);
});
export default observer(TestOverview);