Skip to content

Commit

Permalink
feat(datatrakWeb): RN-1339: View completed survey response from task (#…
Browse files Browse the repository at this point in the history
…5789)

* Create survey_response_id column

* Update change handler

* View completed survey

* Error handling

* Fix comment

* fix tasks button

* removeTaskFilterSetting on logout

* PR fixes

---------

Co-authored-by: Tom Caiger <caigertom@gmail.com>
  • Loading branch information
alexd-bes and tcaiger authored Jul 18, 2024
1 parent 5bc63ed commit 212dfcc
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 77 deletions.
1 change: 1 addition & 0 deletions packages/datatrak-web-server/src/routes/TaskRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const FIELDS = [
'repeat_schedule',
'survey_id',
'entity_id',
'survey_response_id',
];

export class TaskRoute extends Route<TaskRequest> {
Expand Down
8 changes: 4 additions & 4 deletions packages/datatrak-web/src/api/mutations/useLogout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@

import { useMutation, useQueryClient } from 'react-query';
import { post } from '../api';
import { setTaskFilterSetting } from '../../utils';
import { removeTaskFilterSetting } from '../../utils';

export const useLogout = () => {
const queryClient = useQueryClient();

return useMutation('logout', () => post('logout'), {
onSuccess: () => {
queryClient.invalidateQueries();
setTaskFilterSetting('all_assignees_tasks', false);
setTaskFilterSetting('show_completed_tasks', false);
setTaskFilterSetting('show_cancelled_tasks', false);
removeTaskFilterSetting('all_assignees_tasks');
removeTaskFilterSetting('show_completed_tasks');
removeTaskFilterSetting('show_cancelled_tasks');
},
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ export const ActionButton = ({ task }: ActionButtonProps) => {
);
}

const surveyLink = generatePath(ROUTES.SURVEY, {
const path = generatePath(ROUTES.SURVEY, {
surveyCode: survey.code,
countryCode: entity.countryCode,
});
// Link needs to include page number because if the redirect happens, the "from" state is lost
const surveyLink = `${path}/1`;

return (
<ActionButtonComponent
Expand Down

This file was deleted.

6 changes: 5 additions & 1 deletion packages/datatrak-web/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ export { useFromLocation } from './useFromLocation';
export * from './date';
export * from './detectDevice';
export { gaEvent } from './ga';
export { setTaskFilterSetting, getTaskFilterSetting } from './taskFilterSettings';
export {
setTaskFilterSetting,
getTaskFilterSetting,
removeTaskFilterSetting,
} from './taskFilterSettings';
4 changes: 4 additions & 0 deletions packages/datatrak-web/src/utils/taskFilterSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ export const setTaskFilterSetting = (cookieName: TaskFilterType, value: boolean)
...(!isDev && { domain: '.tupaia.org' }),
});
};

export const removeTaskFilterSetting = (cookieName: TaskFilterType): boolean => {
return Cookies.remove(cookieName);
};
78 changes: 62 additions & 16 deletions packages/datatrak-web/src/views/Tasks/TaskDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,53 @@
* Copyright (c) 2017 - 2024 Beyond Essential Systems Pty Ltd
*/

import React from 'react';
import React, { useState } from 'react';
import { generatePath, useParams } from 'react-router-dom';
import styled from 'styled-components';
import { Typography } from '@material-ui/core';
import { TaskStatus } from '@tupaia/types';
import { SpinningLoader } from '@tupaia/ui-components';
import { Modal, ModalCenteredContent, SpinningLoader } from '@tupaia/ui-components';
import { Button } from '../../components';
import { TaskDetails, TaskPageHeader, TaskActionsMenu } from '../../features';
import { useTask } from '../../api';
import { ROUTES } from '../../constants';
import { useFromLocation } from '../../utils';
import { Task } from '../../types';

const ButtonWrapper = styled.div`
display: flex;
justify-content: space-between;
flex: 1;
`;

export const TaskDetailsPage = () => {
const { taskId } = useParams();
const { data: task, isLoading } = useTask(taskId);
const ErrorModal = ({ isOpen, onClose }) => {
return (
<Modal
title="Error loading survey response"
isOpen={isOpen}
onClose={onClose}
buttons={[
{
text: 'Close',
onClick: onClose,
id: 'close',
},
]}
>
<ModalCenteredContent>
<Typography>
This response has since been deleted in the admin panel. Please contact your system
administrator for further questions.
</Typography>
</ModalCenteredContent>
</Modal>
);
};

const ButtonComponent = ({ task, openErrorModal }: { task?: Task; openErrorModal: () => void }) => {
const from = useFromLocation();

const showCompleteButton =
task && task.taskStatus !== TaskStatus.completed && task.taskStatus !== TaskStatus.cancelled;
if (!task) return null;

const surveyUrl = task
? generatePath(ROUTES.SURVEY_SCREEN, {
Expand All @@ -35,21 +59,43 @@ export const TaskDetailsPage = () => {
})
: '';

const from = useFromLocation();
if (task.taskStatus === TaskStatus.cancelled) return null;
if (task.taskStatus === TaskStatus.completed) {
if (!task.surveyResponseId)
return (
<Button onClick={openErrorModal} variant="outlined">
View completed survey
</Button>
);
return (
<Button to={`?responseId=${task.surveyResponseId}`} variant="outlined">
View completed survey
</Button>
);
}
return (
<Button to={surveyUrl} state={{ from }}>
Complete task
</Button>
);
};

export const TaskDetailsPage = () => {
const [errorModalOpen, setErrorModalOpen] = useState(false);
const { taskId } = useParams();
const { data: task, isLoading } = useTask(taskId);

return (
<>
<TaskPageHeader title="Task details">
{showCompleteButton && (
<ButtonWrapper>
<Button to={surveyUrl} state={{ from }}>
Complete
</Button>
<TaskActionsMenu {...task} />
</ButtonWrapper>
)}
<ButtonWrapper>
<ButtonComponent task={task} openErrorModal={() => setErrorModalOpen(true)} />
{task && <TaskActionsMenu {...task} />}
</ButtonWrapper>
</TaskPageHeader>
{isLoading && <SpinningLoader />}
{task && <TaskDetails task={task} />}
<ErrorModal isOpen={errorModalOpen} onClose={() => setErrorModalOpen(false)} />
</>
);
};

0 comments on commit 212dfcc

Please sign in to comment.