Skip to content

Commit

Permalink
Merge pull request #2124 from ever-co/feat/taskActivity
Browse files Browse the repository at this point in the history
Feat: user Activity on Task ( Hooks, API Routes)
  • Loading branch information
evereq authored Jan 28, 2024
2 parents 2e48d41 + 9309b58 commit dfcf3e1
Show file tree
Hide file tree
Showing 17 changed files with 260 additions and 54 deletions.
3 changes: 2 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,8 @@
"Screenshoot",
"screenshoots",
"tota",
"Intervall"
"Intervall",
"Timesheets"
],
"useGitignore": true,
"ignorePaths": [
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/[locale]/task/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const TaskDetails = () => {
{/* <IssueCard related={true} /> */}

{/* <CompletionBlock /> */}
<TaskActivity />
{task && <TaskActivity task={task} />}
</div>
</section>
<div className="flex flex-col mt-4 lg:mt-0 3xl:min-w-[24rem] w-full lg:w-[30%]">
Expand Down
23 changes: 21 additions & 2 deletions apps/web/app/api/timer/timesheet/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
import { authenticatedGuard } from '@app/services/server/guards/authenticated-guard-app';
import { taskActivityRequest } from '@app/services/server/requests';
import { NextResponse } from 'next/server';

export async function GET(req: Request) {
const res = new NextResponse();
const { $res, user } = await authenticatedGuard(req, res);
if (!user) return $res('unauthorized');
const { $res, user, tenantId, organizationId, access_token } = await authenticatedGuard(req, res);
if (!user) return $res('Unauthorized');

const { searchParams } = new URL(req.url);

const { taskId } = searchParams as unknown as {
taskId: string;
};

const { data } = await taskActivityRequest(
{
'taskIds[0]': taskId,
tenantId,
organizationId,
defaultRange: 'false'
},
access_token
);

return $res(data);
}
21 changes: 21 additions & 0 deletions apps/web/app/helpers/array-data.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ITimerSlot } from '@app/interfaces/timer/ITimerSlot';
import { pad } from './number';
import { ITimerApps } from '@app/interfaces/timer/ITimerApp';
import { ITaskTimesheet } from '@app/interfaces';
export function groupDataByHour(data: ITimerSlot[]) {
const groupedData: { startedAt: string; stoppedAt: string; items: ITimerSlot[] }[] = [];

Expand Down Expand Up @@ -47,6 +48,26 @@ export function groupAppsByHour(apps: ITimerApps[]) {
return groupedData.sort((a, b) => (new Date(a.hour) > new Date(b.hour) ? -1 : 1));
}

export function groupByTime(data: ITaskTimesheet[]) {
const groupedData: { date: string; items: ITaskTimesheet[] }[] = [];

data.forEach((item) => {
const date = new Date(item.date).toDateString();

const dateDataIndex = groupedData.findIndex((el) => el.date == date);

if (dateDataIndex !== -1) {
groupedData[dateDataIndex].items.push(item);
} else
groupedData.push({
date,
items: [item]
});
});

return groupedData.sort((a, b) => (new Date(a.date) > new Date(b.date) ? -1 : 1));
}

const formatTime = (d: Date | string, addHour: boolean) => {
d = d instanceof Date ? d : new Date(d);
if (addHour)
Expand Down
46 changes: 46 additions & 0 deletions apps/web/app/hooks/features/useTaskActivity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use client';

import { useCallback, useEffect } from 'react';
import { useQuery } from '../useQuery';
import { useRecoilState, useRecoilValue } from 'recoil';

import { useAuthenticateUser } from './useAuthenticateUser';
import { useUserProfilePage } from './useUserProfilePage';
import { activityTypeState } from '@app/stores/activity-type';
import { taskTimesheetState } from '@app/stores/task-timesheet';
import { getTaskTimesheetRequestAPI } from '@app/services/client/api';

export function useTaskTimeSheets(id: string) {
const { user } = useAuthenticateUser();
const [taskTimesheets, setTaskTimesheets] = useRecoilState(taskTimesheetState);
const activityFilter = useRecoilValue(activityTypeState);
const profile = useUserProfilePage();

const { loading, queryCall } = useQuery(getTaskTimesheetRequestAPI);
const getTaskTimesheets = useCallback(() => {
if (activityFilter.member?.employeeId === user?.employee.id || user?.role?.name?.toUpperCase() == 'MANAGER') {
queryCall({
tenantId: user?.tenantId ?? '',
organizationId: user?.employee.organizationId ?? '',
taskId: id
}).then((response) => {
console.log(response);
if (response.data) {
console.log(response.data);
setTaskTimesheets(response.data);
}
});
} else setTaskTimesheets([]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activityFilter.member?.employeeId, profile.member?.employeeId, user?.id, queryCall, setTaskTimesheets]);

useEffect(() => {
getTaskTimesheets();
}, [getTaskTimesheets]);

return {
taskTimesheets,
getTaskTimesheets,
loading
};
}
24 changes: 24 additions & 0 deletions apps/web/app/interfaces/ITaskTimesheet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IEmployee } from './IEmployee';
import { IProject } from './IProject';
import { ITeamTask } from './ITask';
import { ITimerSlot } from './timer/ITimerSlot';

export interface ITaskTimesheet {
id: string
title: string;
description?: string;
metaData?: string;
date: Date;
time: string;
duration?: number;
type?: string;
source?: string;
employee?: IEmployee;
employeeId?: IEmployee['id'];
project?: IProject;
projectId?: IProject['id'];
timeSlot?: ITimerSlot;
timeSlotId?: ITimerSlot['id'];
task?: ITeamTask;
taskId?: ITeamTask['id'];
}
1 change: 1 addition & 0 deletions apps/web/app/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export * from './ITaskStatus';
export * from './ITaskVersion';
export * from './ITaskPriorities';
export * from './ITaskSizes';
export * from './ITaskTimesheet';
export * from './ITaskLabels';
export * from './ITaskRelatedIssueType';
export * from './IColor';
Expand Down
37 changes: 37 additions & 0 deletions apps/web/app/services/client/api/activity/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ITaskTimesheet } from '@app/interfaces';
import { get } from '@app/services/client/axios';
import { GAUZY_API_BASE_SERVER_URL } from '@app/constants';

export async function getTaskTimesheetRequestAPI({
taskId,
tenantId,
organizationId,
defaultRange,
unitOfTime
}: {
tenantId: string;
organizationId: string;
defaultRange?: string;
taskId?: string;
unitOfTime?: 'day';
}) {
const params: {
tenantId: string;
organizationId: string;
defaultRange?: string;
'taskIds[0]'?: string;
unitOfTime?: 'day';
} = {
'taskIds[0]': taskId,
tenantId,
organizationId,
defaultRange,
unitOfTime
};
const query = new URLSearchParams(params);
const endpoint = GAUZY_API_BASE_SERVER_URL.value
? `/timesheet/activity?${query.toString()}`
: `/timer/timesheet?${query.toString()}`;

return get<ITaskTimesheet[]>(endpoint);
}
1 change: 1 addition & 0 deletions apps/web/app/services/client/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ export * from './organization-projects';

export * from './activity/time-slots';
export * from './activity/activity';
export * from './activity';
export * from './default';
export * from './projects';
2 changes: 1 addition & 1 deletion apps/web/app/services/client/api/organization-team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export async function getOrganizationTeamAPI(teamId: string, organizationId: str
params[`relations[${i}]`] = rl;
});

const queries = new URLSearchParams(params || {});
const queries = new URLSearchParams(params);

const endpoint = `/organization-team/${teamId}?${queries.toString()}`;

Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/services/server/requests/organization-team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export function getOrganizationTeamRequest(
params[`relations[${i}]`] = rl;
});

const queries = new URLSearchParams(params || {});
const queries = new URLSearchParams(params);
return serverFetch<IOrganizationTeamWithMStatus>({
path: `/organization-team/${teamId}?${queries.toString()}`,
method: 'GET',
Expand Down
19 changes: 19 additions & 0 deletions apps/web/app/services/server/requests/timesheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,22 @@ export function tasksTimesheetStatisticsRequest(params: TTasksTimesheetStatistic
tenantId: params.tenantId
});
}

export type TTaskActivityParams = {
tenantId: string;
organizationId: string;
defaultRange?: string;
'taskIds[0]'?: string;
unitOfTime?: 'day';
};

export function taskActivityRequest(params: TTaskActivityParams, bearer_token: string) {
const queries = new URLSearchParams(params);

return serverFetch<ITasksTimesheet[]>({
path: `/timesheet/activity?${queries.toString()}`,
method: 'GET',
bearer_token,
tenantId: params.tenantId
});
}
7 changes: 7 additions & 0 deletions apps/web/app/stores/task-timesheet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ITaskTimesheet } from '@app/interfaces';
import { atom } from 'recoil';

export const taskTimesheetState = atom<ITaskTimesheet[]>({
key: 'taskTimesheetState',
default: []
});
4 changes: 2 additions & 2 deletions apps/web/components/pages/maintenance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ function Maintenance() {
const t = useTranslations();
return (
<div className="mt-28 flex flex-col gap-7 items-center">
<RocketIcon width={200} height={200} className="text-xl text-chetwodeBlue" />
<div className="m-auto relative my-6 pt-12 flex justify-center items-center gap-4 text-center ">
<div className="m-auto relative flex justify-center items-center gap-4 text-center ">
<RocketIcon width={97} height={97} className="text-xl text-chetwodeBlue" />
<Text className="text-[78px] text-center font-semibold text-chetwodeBlue">Maintenance</Text>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const TaskEstimationsInfo = () => {
</Disclosure.Button>
<Disclosure.Panel>
<div className="flex flex-col gap-[0.5625rem] mt-2">
{task?.members.map((member) => {
{task?.members?.map((member) => {
// TODO
// Enable other users estimations in v2
return (
Expand Down
44 changes: 44 additions & 0 deletions apps/web/lib/features/task/activity/user-task-activity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { clsxm } from '@app/utils';
import { Tab } from '@headlessui/react';
import { ActivityFilters } from '@app/constants';

export const UserTaskActivity = () => {
// get slots related to Task Id
// get apps visited related to Task Id
// get visited Sites related to Task Id
return (
<div className="shadow-md rounded-md p-4 my-4 bg-[#00000014] dark:bg-[#26272C]">
<div className="flex items-center gap-2 my-2">
<h4 className="text-lg">{'Cedric medium'}</h4>
<span>{'05:30'}</span>
</div>
<Tab.Group>
<Tab.List className="w-full flex rounded-xl bg-gray-200 dark:bg-[#FFFFFF14] p-2">
{Object.values(ActivityFilters)
.filter((filter) => filter !== 'Tasks')
.map((filter: string) => (
<Tab
key={filter}
className={({ selected }) =>
clsxm(
'w-full rounded-lg py-2.5 text-sm font-medium leading-5',
' focus:outline-none focus:ring-2',
selected
? 'bg-white dark:bg-dark text-blue-700 shadow'
: ' hover:bg-white/[0.50]'
)
}
>
{filter}
</Tab>
))}
</Tab.List>
<Tab.Panels>
<Tab.Panel className="w-full mx-4 py-4">{'Screenshoot Team Tab'}</Tab.Panel>
<Tab.Panel className="w-full mx-4 py-4">{'Apps Tab'}</Tab.Panel>
<Tab.Panel className="w-full mx-4 py-4">{'VisitedSites Tab'}</Tab.Panel>
</Tab.Panels>
</Tab.Group>
</div>
);
};
Loading

0 comments on commit dfcf3e1

Please sign in to comment.