Skip to content

Commit

Permalink
Build nav and existing responses table for launch questionnaire view
Browse files Browse the repository at this point in the history
  • Loading branch information
fongsean committed Aug 1, 2023
1 parent 489d98b commit d6ab3bb
Show file tree
Hide file tree
Showing 18 changed files with 551 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
getExistingResponsesToolBarColors,
StyledRoot
} from '../../../dashboard/components/DashboardPages/QuestionnairePage/TableComponents/QuestionnaireListToolbar.styles.ts';
import { Box, LinearProgress } from '@mui/material';
import type { QuestionnaireResponse } from 'fhir/r4';
import ExistingResponsesTableToolbarButtons from './ExistingResponsesTableToolbarButtons.tsx';
import ExistingResponsesTableToolbarLeftSection from './ExistingResponsesTableToolbarLeftSection.tsx';

interface ExistingResponseTableToolbarProps {
selectedResponse: QuestionnaireResponse | null;
isFetching: boolean;
onClearSelection: () => void;
}

function ExistingResponseTableToolbar(props: ExistingResponseTableToolbarProps) {
const { selectedResponse, isFetching, onClearSelection } = props;

const toolBarColors = getExistingResponsesToolBarColors(selectedResponse);

return (
<>
<StyledRoot sx={{ ...toolBarColors }}>
<ExistingResponsesTableToolbarLeftSection selectedResponse={selectedResponse} />
<ExistingResponsesTableToolbarButtons
selectedResponse={selectedResponse}
onClearSelection={onClearSelection}
/>
</StyledRoot>
{isFetching ? <LinearProgress /> : <Box pt={0.5} sx={{ ...toolBarColors }} />}
</>
);
}

export default ExistingResponseTableToolbar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2023 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Card, Container, Fade } from '@mui/material';
import { Helmet } from 'react-helmet';
import PageHeading from '../../../dashboard/components/DashboardPages/PageHeading.tsx';
import ExistingResponsesTable from './ExistingResponsesTable.tsx';

function ExistingResponsesPage() {
return (
<>
<Helmet>
<title>Existing Responses</title>
</Helmet>
<Fade in={true}>
<Container data-test="dashboard-existing-container">
<PageHeading>Existing Responses</PageHeading>

<Card>
<ExistingResponsesTable />
</Card>
</Container>
</Fade>
</>
);
}

export default ExistingResponsesPage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2023 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { useMemo, useState } from 'react';
import useFetchExistingResponses from '../../../dashboard/hooks/useFetchExistingResponses.ts';
import type { QuestionnaireResponse } from 'fhir/r4';
import { createResponseTableColumns } from '../../../dashboard/utils/tableColumns.ts';
import type { SortingState } from '@tanstack/react-table';
import {
getCoreRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable
} from '@tanstack/react-table';
import ExistingResponsesTableView from './ExistingResponsesTableView.tsx';

function ExistingResponsesTable() {
const [selectedResponse, setSelectedResponse] = useState<QuestionnaireResponse | null>(null);

const { existingResponses, fetchError, isFetching } = useFetchExistingResponses();

const columns = useMemo(() => createResponseTableColumns(), []);

const [sorting, setSorting] = useState<SortingState>([{ id: 'authored', desc: true }]);

const table = useReactTable({
data: existingResponses,
columns: columns,
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getPaginationRowModel: getPaginationRowModel(),
state: {
sorting
}
});

function handleRowClick(id: string) {
const response = existingResponses.find((response) => response.id === id);

if (response) {
if (response.id === selectedResponse?.id) {
setSelectedResponse(null);
} else {
setSelectedResponse(response);
}
}
}

return (
<ExistingResponsesTableView
table={table}
isFetching={isFetching}
fetchError={fetchError}
selectedResponse={selectedResponse}
onRowClick={handleRowClick}
onSelectResponse={setSelectedResponse}
/>
);
}

export default ExistingResponsesTable;
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2023 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { useSnackbar } from 'notistack';
import { Stack, TableBody, TableCell, TableRow } from '@mui/material';
import DashboardFeedbackMessage from '../../../dashboard/components/DashboardPages/DashboardFeedbackMessage.tsx';

interface ExistingResponsesListFeedbackProps {
isEmpty: boolean;
isFetching: boolean;
fetchError?: unknown;
}

function ExistingResponsesTableFeedback(props: ExistingResponsesListFeedbackProps) {
const { isEmpty, isFetching, fetchError } = props;

const { enqueueSnackbar } = useSnackbar();

let feedbackType: 'error' | 'empty' | 'loading' | null = null;
if (fetchError) {
feedbackType = 'error';
} else if (isFetching) {
feedbackType = 'loading';
} else if (isEmpty) {
feedbackType = 'empty';
}

if (feedbackType === 'error') {
console.error(fetchError);
enqueueSnackbar('An error occurred while fetching responses', {
variant: 'error',
preventDuplicate: true
});
}

return feedbackType ? (
<TableBody>
<TableRow>
<TableCell align="center" colSpan={6}>
<Stack rowGap={3} my={5}>
<DashboardFeedbackMessage
itemType={'responses'}
feedbackType={feedbackType}
searchInput={''}
/>
</Stack>
</TableCell>
</TableRow>
</TableBody>
) : null;
}

export default ExistingResponsesTableFeedback;
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2023 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Box, IconButton, Stack, Typography } from '@mui/material';
import ClearIcon from '@mui/icons-material/Clear';
import CreateNewResponseButton from '../../../dashboard/components/DashboardPages/QuestionnairePage/Buttons/CreateNewResponseButton.tsx';
import type { QuestionnaireResponse } from 'fhir/r4';
import OpenResponseButton from '../../../dashboard/components/DashboardPages/ResponsesPage/Buttons/OpenResponseButton.tsx';

interface ExistingResponsesTableToolbarButtonsProps {
selectedResponse: QuestionnaireResponse | null;
onClearSelection: () => void;
}

function ExistingResponsesTableToolbarButtons(props: ExistingResponsesTableToolbarButtonsProps) {
const { selectedResponse, onClearSelection } = props;

if (selectedResponse) {
return (
<Box display="flex" alignItems="center" columnGap={2}>
<OpenResponseButton selectedResponse={selectedResponse} />
<Stack alignItems="center">
<IconButton onClick={onClearSelection}>
<ClearIcon />
</IconButton>
<Typography
fontSize={9}
variant="subtitle2"
color={'text.secondary'}
sx={{ mt: -0.5, mb: 0.5 }}>
Unselect
</Typography>
</Stack>
</Box>
);
}

return (
<Box display="flex" alignItems="center" columnGap={2}>
<CreateNewResponseButton />
</Box>
);
}

export default ExistingResponsesTableToolbarButtons;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2023 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import type { QuestionnaireResponse } from 'fhir/r4';
import { createResponseListItem } from '../../../dashboard/utils/dashboard.ts';
import { Box, Typography } from '@mui/material';
import dayjs from 'dayjs';
import BackToQuestionnairesButton from '../../../dashboard/components/DashboardPages/ResponsesPage/Buttons/BackToQuestionnairesButton.tsx';
import useConfigStore from '../../../../stores/useConfigStore.ts';

interface ExistingResponsesTableToolbarLeftSectionProps {
selectedResponse: QuestionnaireResponse | null;
}

function ExistingResponsesTableToolbarLeftSection(
props: ExistingResponsesTableToolbarLeftSectionProps
) {
const { selectedResponse } = props;
const launchQuestionnaire = useConfigStore((state) => state.launchQuestionnaire);

if (selectedResponse) {
const listItem = createResponseListItem(selectedResponse, -1);
return (
<Typography component="div" variant="subtitle1">
{listItem.title}{dayjs(listItem.authored).format('LL')} selected
</Typography>
);
}

const selectedQuestionnaireTitle = launchQuestionnaire?.title ?? 'selected questionnaire';
return (
<Box display="flex" alignItems="center">
<BackToQuestionnairesButton />
<Typography variant="subtitle1">
Displaying responses of the <b>{selectedQuestionnaireTitle}</b> questionnaire
</Typography>
</Box>
);
}

export default ExistingResponsesTableToolbarLeftSection;
Loading

0 comments on commit d6ab3bb

Please sign in to comment.