Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(datatrak): RN-1313: My tasks section #5776

Merged
merged 16 commits into from
Jul 18, 2024
27 changes: 11 additions & 16 deletions packages/datatrak-web/src/api/queries/useTasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,35 @@ import { get } from '../api';

type Filter = {
id: string;
value: string;
value: string | object;
};

type SortBy = {
id: string;
desc: boolean;
};

export const useTasks = (
projectId?: string,
pageSize?: number,
page?: number,
filters: Filter[] = [],
sortBy?: SortBy[],
) => {
interface UseTasksOptions {
projectId?: string;
pageSize?: number;
page?: number;
filters?: Filter[];
sortBy?: SortBy[];
}

export const useTasks = ({ projectId, pageSize, page, filters = [], sortBy }: UseTasksOptions) => {
return useQuery(
['tasks', projectId, pageSize, page, filters, sortBy],
(): Promise<DatatrakWebTasksRequest.ResBody> =>
get('tasks', {
params: {
pageSize,
page,
filters: [
...filters,
{
id: 'survey.project_id',
value: projectId,
},
],
filters,
tcaiger marked this conversation as resolved.
Show resolved Hide resolved
sort: sortBy?.map(({ id, desc }) => `${id} ${desc ? 'DESC' : 'ASC'}`) ?? [],
},
}),
{
enabled: !!projectId,
tcaiger marked this conversation as resolved.
Show resolved Hide resolved
// This needs to be true so that when changing the page number, the total number of records is not reset
keepPreviousData: true,
},
Expand Down
50 changes: 50 additions & 0 deletions packages/datatrak-web/src/features/Tasks/NoTasksSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Tupaia
* Copyright (c) 2017 - 2023 Beyond Essential Systems Pty Ltd
*/
import React from 'react';
import styled from 'styled-components';
import { Typography } from '@material-ui/core';
import { Button as UIButton } from '@tupaia/ui-components';
import { Link } from 'react-router-dom';
import { ROUTES } from '../../constants';

const Container = styled.div`
text-align: center;
padding: 0.5rem 0.5rem 1rem;
`;

const Image = styled.img.attrs({
src: '/tupaia-high-five.svg',
alt: 'Illustration of two hands giving a high five',
})`
height: auto;
max-width: 100%;
width: 8rem;
margin: 0 auto 1rem;
`;

const Text = styled(Typography)`
text-align: center;
font-size: 0.93rem;
line-height: 1.5;
margin-bottom: 1rem;
tcaiger marked this conversation as resolved.
Show resolved Hide resolved
`;

const Button = styled(UIButton)`
font-size: 0.75rem;
max-width: 10rem;
padding: 0.25rem 1rem;
`;
export const NoTasksSection = () => (
<Container>
<Image />
<Text>
Congratulations, you have no tasks to complete! You can view all other tasks for your project
using the button below.
</Text>
<Button to={ROUTES.TASKS} component={Link}>
tcaiger marked this conversation as resolved.
Show resolved Hide resolved
View all tasks
</Button>
</Container>
);
4 changes: 2 additions & 2 deletions packages/datatrak-web/src/features/Tasks/StatusPill.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ const Pill = styled.span<{
}>`
background-color: ${({ $color }) => `${$color}22`};
color: ${({ $color }) => $color};
font-size: 0.7rem;
font-size: 0.625rem;
padding-inline: 0.7rem;
padding-block: 0.3rem;
padding-block: 0.2rem;
border-radius: 20px;
.cell-content > div:has(&) {
overflow: visible;
Expand Down
108 changes: 108 additions & 0 deletions packages/datatrak-web/src/features/Tasks/TaskTile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Tupaia
* Copyright (c) 2017 - 2023 Beyond Essential Systems Pty Ltd
*/

import React from 'react';
import styled from 'styled-components';
import { generatePath, Link } from 'react-router-dom';
import ChatIcon from '@material-ui/icons/ChatBubbleOutline';
import { ROUTES } from '../../constants';
import { StatusPill } from './StatusPill';
import { displayDate } from '../../utils';
import { ButtonLink } from '../../components';

const TileContainer = styled.div`
display: flex;
justify-content: space-between;
border-radius: 10px;
border: 1px solid ${({ theme }) => theme.palette.divider};
width: 100%;
padding: 0.4rem 0.7rem;
margin-block-end: 0.5rem;

.MuiButton-root {
padding: 0.2rem 1.2rem;
}

.MuiButton-label {
font-size: 0.75rem;
}
`;

const TileTitle = styled.div`
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-block-end: 0.25rem;
color: ${({ theme }) => theme.palette.text.primary};
`;

const TileLeft = styled.div`
flex: 1;
padding-inline-end: 1rem;
min-width: 0;
`;

const TileContent = styled.div`
display: flex;
font-size: 0.75rem;
color: ${({ theme }) => theme.palette.text.secondary};
align-items: center;

> span {
margin-inline-end: 0.6rem;
}
`;

const TileRight = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
`;

const CommentsContainer = styled.div`
display: flex;
align-items: center;

.MuiSvgIcon-root {
font-size: 1rem;
margin-inline-end: 0.2rem;
}
`;

// Todo: Update with actual comments count and set default to 0
tcaiger marked this conversation as resolved.
Show resolved Hide resolved
const Comments = ({ commentsCount = 2 }) => {
return (
<CommentsContainer>
<ChatIcon />
{commentsCount}
</CommentsContainer>
);
};

export const TaskTile = ({ task }) => {
const { survey, entity, taskStatus, dueDate } = task;
const surveyLink = generatePath(ROUTES.SURVEY, {
surveyCode: survey.code,
countryCode: entity.countryCode,
});
return (
<TileContainer>
<TileLeft>
<TileTitle>{survey.name}</TileTitle>
<TileContent>
<StatusPill status={taskStatus} />
<span>{displayDate(dueDate)}</span>
<Comments />
</TileContent>
</TileLeft>
<TileRight>
<ButtonLink to={surveyLink} component={Link}>
Complete
tcaiger marked this conversation as resolved.
Show resolved Hide resolved
</ButtonLink>
</TileRight>
</TileContainer>
);
};
2 changes: 2 additions & 0 deletions packages/datatrak-web/src/features/Tasks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@

export { TaskPageHeader } from './TaskPageHeader';
export { TasksTable } from './TasksTable';
export { NoTasksSection } from './NoTasksSection';
export { TaskTile } from './TaskTile';
export { CreateTaskModal } from './CreateTaskModal';
24 changes: 14 additions & 10 deletions packages/datatrak-web/src/views/LandingPage/LandingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { SurveyResponsesSection } from './SurveyResponsesSection';
import { LeaderboardSection } from './LeaderboardSection';
import { ActivityFeedSection } from './ActivityFeedSection';
import { RecentSurveysSection } from './RecentSurveysSection';
import { TasksSection } from './TasksSection';
import { DESKTOP_MEDIA_QUERY, HEADER_HEIGHT } from '../../constants';

const PageContainer = styled(BasePageContainer)`
Expand All @@ -21,20 +22,19 @@ const PageContainer = styled(BasePageContainer)`
const PageBody = styled.div`
display: flex;
flex-direction: column;
padding: 1.5rem 0;
padding: 0.5rem 0 1.5rem;
width: 100%;
max-width: 85rem;
margin: 0 auto;
height: auto;

${({ theme }) => theme.breakpoints.up('md')} {
height: calc(100vh - ${HEADER_HEIGHT});
padding: 2rem 2.75rem 0.8rem 2.75rem;
padding: 0.2rem 1rem 0.8rem;
}

${DESKTOP_MEDIA_QUERY} {
padding-top: 4rem;
padding-bottom: 2.5rem;
padding: 1rem 2.75rem 2rem;
}
`;

Expand All @@ -60,8 +60,9 @@ const Grid = styled.div`
grid-template-rows: auto auto;
grid-template-columns: 1fr 1fr;
grid-template-areas:
'recentSurveys leaderboard'
'recentResponses activityFeed';
'surveySelect surveySelect tasks tasks'
'recentSurveys recentSurveys recentResponses recentResponses'
'activityFeed activityFeed leaderboard leaderboard';

> section {
margin: 0;
Expand All @@ -70,27 +71,30 @@ const Grid = styled.div`
}

${({ theme }) => theme.breakpoints.up('lg')} {
grid-template-columns: 23% 1fr 1fr 28%;
grid-template-columns: 23% 1fr 1fr 30%;
grid-template-areas:
'recentSurveys recentSurveys recentSurveys leaderboard'
'surveySelect surveySelect surveySelect tasks'
'recentSurveys recentSurveys recentSurveys tasks'
'recentResponses activityFeed activityFeed leaderboard';
> div {
min-height: auto;
}
}

${DESKTOP_MEDIA_QUERY} {
margin-top: 2.5rem;
gap: 1.81rem;
}
`;

export const LandingPage = () => {
const showTasks = process.env.REACT_APP_TUPAIA_TASKS;
tcaiger marked this conversation as resolved.
Show resolved Hide resolved

return (
<PageContainer>
<PageBody>
<SurveySelectSection />
<Grid>
<SurveySelectSection />
{showTasks && <TasksSection />}
<LeaderboardSection />
<RecentSurveysSection />
<SurveyResponsesSection />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const SectionHeading = styled(Typography).attrs({
variant: 'h2',
})`
font-size: 1rem;
line-height: 1.2;
font-weight: 500;
margin-bottom: 0.75rem;
`;
Loading
Loading