Skip to content

Commit

Permalink
[Fix bug] Daily Plan | Same tasks are shown for different users (#3481)
Browse files Browse the repository at this point in the history
* show relevant tasks for each member in the same team | team member card view

* fix deepSan

* add coderabbit ai suggest
  • Loading branch information
CREDO23 authored Dec 26, 2024
1 parent ee35122 commit 05eaa04
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 52 deletions.
20 changes: 18 additions & 2 deletions apps/web/lib/features/task/daily-plan/future-tasks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import { clsxm } from '@app/utils';
import { HorizontalSeparator, AlertPopup } from 'lib/components';
import { useEffect, useState } from 'react';
import { filterDailyPlan } from '@app/hooks/useFilterDateRange';
import { IDailyPlan } from '@app/interfaces';
import { IDailyPlan, IUser } from '@app/interfaces';
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
import { useDateRange } from '@app/hooks/useDateRange';
import DailyPlanTasksTableView from './table-view';

export function FutureTasks({ profile }: { profile: any }) {
export function FutureTasks({ profile, user }: { profile: any; user?: IUser }) {
const { deleteDailyPlan, deleteDailyPlanLoading, futurePlans } = useDailyPlan();
const canSeeActivity = useCanSeeActivityScreen();
const [popupOpen, setPopupOpen] = useState(false);
Expand All @@ -30,6 +30,22 @@ export function FutureTasks({ profile }: { profile: any }) {
}, [date, setDate, futurePlans]);
const view = useAtomValue(dailyPlanViewHeaderTabs);

useEffect(() => {
let filteredData = futurePlans;

// Filter tasks for specific user if provided
if (user) {
filteredData = filteredData
.map((plan) => ({
...plan,
tasks: plan.tasks?.filter((task) => task.members?.some((member) => member.userId === user.id))
}))
.filter((plan) => plan.tasks && plan.tasks.length > 0);

setFutureDailyPlanTasks(filterDailyPlan(date as any, filteredData));
}
}, [date, futurePlans, user]);

return (
<div className="flex flex-col gap-6">
{futureDailyPlanTasks?.length > 0 ? (
Expand Down
17 changes: 12 additions & 5 deletions apps/web/lib/features/task/daily-plan/outstanding-all.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,32 @@ import TaskBlockCard from '../task-block-card';
import { clsxm } from '@app/utils';
import { DragDropContext, Draggable, Droppable, DroppableProvided } from 'react-beautiful-dnd';
import { useState } from 'react';
import { ITeamTask } from '@app/interfaces';
import { ITeamTask, IUser } from '@app/interfaces';
import { handleDragAndDropDailyOutstandingAll } from '@app/helpers';

interface OutstandingAll {
profile: any;
user?: IUser;
}
export function OutstandingAll({ profile }: OutstandingAll) {
export function OutstandingAll({ profile, user }: OutstandingAll) {
const { outstandingPlans } = useDailyPlan();
const view = useAtomValue(dailyPlanViewHeaderTabs);
const displayedTaskId = new Set();

const tasks = outstandingPlans.map((plan) => plan.tasks).reduce((red, curr) => red?.concat(curr || []), []);
const [task, setTask] = useState<ITeamTask[]>(() => tasks ?? []);
const tasks = outstandingPlans.flatMap(
(plan) =>
(user
? plan.tasks?.filter((task) => task.members?.some((member) => member.userId === user.id))
: plan.tasks) ?? []
);

const [task, setTask] = useState<ITeamTask[]>(() => tasks);

return (
<div className="flex flex-col gap-6">
<TaskEstimatedCount outstandingPlans={outstandingPlans} />

{tasks && tasks?.length > 0 ? (
{tasks.length > 0 ? (
<>
<DragDropContext
onDragEnd={(result) => handleDragAndDropDailyOutstandingAll(result, task, setTask)}
Expand Down
37 changes: 27 additions & 10 deletions apps/web/lib/features/task/daily-plan/outstanding-date.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,45 @@ import { clsxm } from '@app/utils';
import { useAtomValue } from 'jotai';
import { dailyPlanViewHeaderTabs } from '@app/stores/header-tabs';
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
import { useState } from 'react';
import { IDailyPlan } from '@app/interfaces';
import { useEffect, useState } from 'react';
import { IDailyPlan, IUser } from '@app/interfaces';

interface IOutstandingFilterDate {
profile: any;
user?: IUser;
}
export function OutstandingFilterDate({ profile }: IOutstandingFilterDate) {
export function OutstandingFilterDate({ profile, user }: IOutstandingFilterDate) {
const { outstandingPlans } = useDailyPlan();
const view = useAtomValue(dailyPlanViewHeaderTabs);
const [outstandingTasks, setOutstandingTasks] = useState<IDailyPlan[]>(outstandingPlans);
const [plans, setPlans] = useState<IDailyPlan[]>(outstandingPlans);

useEffect(() => {
let data = [...outstandingPlans];

// Filter plans for specific user if provided
if (user) {
data = data
.map((plan) => ({
...plan,
tasks: plan.tasks?.filter((task) => task.members?.some((member) => member.userId === user.id))
}))
.filter((plan) => plan.tasks && plan.tasks.length > 0);

setPlans(data);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user]);

return (
<div className="flex flex-col gap-6">
{outstandingTasks?.length > 0 ? (
<DragDropContext
onDragEnd={(result) => handleDragAndDrop(result, outstandingTasks, setOutstandingTasks)}
>
{plans?.length > 0 ? (
<DragDropContext onDragEnd={(result) => handleDragAndDrop(result, plans, setPlans)}>
<Accordion
type="multiple"
className="text-sm"
defaultValue={outstandingTasks?.map((plan) => new Date(plan.date).toISOString().split('T')[0])}
defaultValue={plans?.map((plan) => new Date(plan.date).toISOString().split('T')[0])}
>
{outstandingTasks?.map((plan) => (
{plans?.map((plan) => (
<AccordionItem
value={plan.date.toString().split('T')[0]}
key={plan.id}
Expand Down
40 changes: 32 additions & 8 deletions apps/web/lib/features/task/daily-plan/past-tasks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,56 @@ import { clsxm } from '@app/utils';
import TaskBlockCard from '../task-block-card';
import { filterDailyPlan } from '@app/hooks/useFilterDateRange';
import { useEffect, useState } from 'react';
import { IDailyPlan } from '@app/interfaces';
import { IDailyPlan, IUser } from '@app/interfaces';
import { DragDropContext, Draggable, Droppable, DroppableProvided, DroppableStateSnapshot } from 'react-beautiful-dnd';
import { useDateRange } from '@app/hooks/useDateRange';
import DailyPlanTasksTableView from './table-view';

export function PastTasks({ profile, currentTab = 'Past Tasks' }: { profile: any; currentTab?: FilterTabs }) {
const { pastPlans } = useDailyPlan();
export function PastTasks({
user,
profile,
currentTab = 'Past Tasks'
}: {
profile: any;
currentTab?: FilterTabs;
user?: IUser;
}) {
const { pastPlans: _pastPlans } = useDailyPlan();

const view = useAtomValue(dailyPlanViewHeaderTabs);
const [pastTasks, setPastTasks] = useState<IDailyPlan[]>(pastPlans);
const [pastPlans, setPastPlans] = useState<IDailyPlan[]>(_pastPlans);
const { date } = useDateRange(window.localStorage.getItem('daily-plan-tab'));

useEffect(() => {
setPastTasks(filterDailyPlan(date as any, pastPlans));
setPastPlans(filterDailyPlan(date as any, pastPlans));
}, [date, pastPlans]);

useEffect(() => {
let filteredData = pastPlans;

// Filter tasks for specific user if provided
if (user) {
filteredData = filteredData
.map((plan) => ({
...plan,
tasks: plan.tasks?.filter((task) => task.members?.some((member) => member.userId === user.id))
}))
.filter((plan) => plan.tasks && plan.tasks.length > 0);
}

setPastPlans(filteredData);
}, [date, pastPlans, user]);

return (
<div className="flex flex-col gap-6">
{pastTasks?.length > 0 ? (
<DragDropContext onDragEnd={(result) => handleDragAndDrop(result, pastPlans, setPastTasks)}>
{pastPlans?.length > 0 ? (
<DragDropContext onDragEnd={(result) => handleDragAndDrop(result, pastPlans, setPastPlans)}>
<Accordion
type="multiple"
className="text-sm"
defaultValue={[yesterdayDate.toISOString().split('T')[0]]}
>
{pastTasks?.map((plan) => (
{pastPlans?.map((plan) => (
<AccordionItem
value={plan.date.toString().split('T')[0]}
key={plan.id}
Expand Down
19 changes: 11 additions & 8 deletions apps/web/lib/features/task/daily-plan/task-estimated-count.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { secondsToTime } from '@app/helpers';
import { IDailyPlan } from '@app/interfaces';
import { IDailyPlan, IUser } from '@app/interfaces';
import { VerticalSeparator } from 'lib/components';
import { useTranslations } from 'next-intl';

Expand Down Expand Up @@ -47,15 +47,18 @@ export function estimatedTotalTime(data: any) {
return { timesEstimated, totalTasks };
}

export const getTotalTasks = (plan: IDailyPlan[]) => {
if (!plan) {
export const getTotalTasks = (plans: IDailyPlan[], user?: IUser): number => {
if (!plans || plans.length === 0) {
return 0;
}
const tasksPerPlan = plan.map((plan) => plan.tasks?.length);

if (tasksPerPlan.length <= 0) {
return 0;
}
const tasksPerPlan = plans.map((plan) => {
const filteredTasks = user
? plan.tasks?.filter((task) => task.members?.some((member) => member.userId === user.id))
: plan.tasks;

return filteredTasks?.length || 0;
});

return tasksPerPlan.reduce((a, b) => (a ?? 0) + (b ?? 0)) ?? 0;
return tasksPerPlan.reduce((total, taskCount) => total + taskCount, 0);
};
2 changes: 1 addition & 1 deletion apps/web/lib/features/team/user-team-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export function UserTeamCard({
const [activityFilter, setActivity] = useState<FilterTab>('Tasks');

const activityScreens = {
Tasks: <UserProfileTask profile={profile} tabFiltered={hook} />,
Tasks: <UserProfileTask profile={profile} tabFiltered={hook} user={member?.employee.user} />,
Screenshots: <ScreenshootTab />,
Apps: <AppsTab />,
'Visited Sites': <VisitedSitesTab />
Expand Down
71 changes: 55 additions & 16 deletions apps/web/lib/features/user-profile-plans.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
HAS_SEEN_DAILY_PLAN_SUGGESTION_MODAL,
HAS_VISITED_OUTSTANDING_TASKS
} from '@app/constants';
import { IDailyPlan, ITeamTask } from '@app/interfaces';
import { IDailyPlan, ITeamTask, IUser } from '@app/interfaces';
import { dataDailyPlanState } from '@app/stores';
import { fullWidthState } from '@app/stores/fullWidth';
import { dailyPlanViewHeaderTabs } from '@app/stores/header-tabs';
Expand Down Expand Up @@ -55,9 +55,15 @@ import DailyPlanTasksTableView from './task/daily-plan/table-view';
export type FilterTabs = 'Today Tasks' | 'Future Tasks' | 'Past Tasks' | 'All Tasks' | 'Outstanding';
type FilterOutstanding = 'ALL' | 'DATE';

export function UserProfilePlans() {
interface IUserProfilePlansProps {
user?: IUser;
}

export function UserProfilePlans(props: IUserProfilePlansProps) {
const t = useTranslations();

const { user } = props;

const profile = useUserProfilePage();
const {
todayPlan,
Expand All @@ -76,14 +82,14 @@ export function UserProfilePlans() {
const { setDate, date } = useDateRange(currentTab);

const screenOutstanding = {
ALL: <OutstandingAll profile={profile} />,
DATE: <OutstandingFilterDate profile={profile} />
ALL: <OutstandingAll profile={profile} user={user} />,
DATE: <OutstandingFilterDate profile={profile} user={user} />
};
const tabsScreens = {
'Today Tasks': <AllPlans profile={profile} currentTab={currentTab} />,
'Future Tasks': <FutureTasks profile={profile} />,
'Past Tasks': <PastTasks profile={profile} />,
'All Tasks': <AllPlans profile={profile} />,
'Today Tasks': <AllPlans profile={profile} currentTab={currentTab} user={user} />,
'Future Tasks': <FutureTasks profile={profile} user={user} />,
'Past Tasks': <PastTasks profile={profile} user={user} />,
'All Tasks': <AllPlans profile={profile} user={user} />,
Outstanding: <Outstanding filter={screenOutstanding[currentOutstanding]} />
};
const [filterFuturePlanData, setFilterFuturePlanData] = useState<IDailyPlan[]>(futurePlans);
Expand Down Expand Up @@ -169,15 +175,24 @@ export function UserProfilePlans() {
currentTab == filter && 'dark:bg-gray-600'
)}
>
{filter === 'Today Tasks' && getTotalTasks(todayPlan)}
{filter === 'Future Tasks' && getTotalTasks(filterFuturePlanData)}
{filter === 'Past Tasks' && getTotalTasks(filterPastPlanData)}
{filter === 'All Tasks' && getTotalTasks(filterAllPlanData)}
{filter === 'Today Tasks' && getTotalTasks(todayPlan, user)}
{filter === 'Future Tasks' &&
getTotalTasks(filterFuturePlanData, user)}
{filter === 'Past Tasks' && getTotalTasks(filterPastPlanData, user)}
{filter === 'All Tasks' && getTotalTasks(filterAllPlanData, user)}
{filter === 'Outstanding' &&
estimatedTotalTime(
outstandingPlans.map((plan) =>
plan.tasks?.map((task) => task)
)
outstandingPlans.map((plan) => {
const tasks = plan.tasks ?? [];
if (user) {
return tasks.filter((task) =>
task.members?.some(
(member) => member.userId === user.id
)
);
}
return tasks;
})
).totalTasks}
</span>
</div>
Expand Down Expand Up @@ -285,7 +300,15 @@ export function UserProfilePlans() {
* @param {{ profile: any; currentTab?: FilterTabs }} { profile, currentTab = 'All Tasks' }
* @return {*}
*/
function AllPlans({ profile, currentTab = 'All Tasks' }: { profile: any; currentTab?: FilterTabs }) {
function AllPlans({
profile,
currentTab = 'All Tasks',
user
}: {
profile: any;
currentTab?: FilterTabs;
user?: IUser;
}) {
// Filter plans
const filteredPlans = useRef<IDailyPlan[]>([]);
const { sortedPlans, todayPlan } = useDailyPlan();
Expand All @@ -305,6 +328,22 @@ function AllPlans({ profile, currentTab = 'All Tasks' }: { profile: any; current
setPlans(filterDailyPlan(date as any, filteredPlans.current));
}, [date, todayPlan]);

useEffect(() => {
let filteredData = filterDailyPlan(date as any, filteredPlans.current);

// Filter tasks for specific user if provided
if (user) {
filteredData = filteredData
.map((plan) => ({
...plan,
tasks: plan.tasks?.filter((task) => task.members?.some((member) => member.userId === user.id))
}))
.filter((plan) => plan.tasks && plan.tasks.length > 0);
}

setPlans(filteredData);
}, [date, todayPlan, user]);

return (
<div className="flex flex-col gap-6">
{Array.isArray(plans) && plans?.length > 0 ? (
Expand Down
6 changes: 4 additions & 2 deletions apps/web/lib/features/user-profile-tasks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@ import { useEffect, useMemo, useState } from 'react';
import { ScreenCalendar } from './activity/screen-calendar';
import { cn } from 'lib/utils';
import { useScrollPagination } from '@app/hooks/features/usePagination';
import { IUser } from '@/app/interfaces';

type Props = {
tabFiltered: I_TaskFilter;
profile: I_UserProfilePage;
paginateTasks?: boolean;
user?: IUser;
};

/**
* It displays a list of tasks, the first task being the active task and the rest being the last 24 hours of tasks
* @param - `profile` - The user profile page data.
* @returns A component that displays a user's profile page.
*/
export function UserProfileTask({ profile, paginateTasks, tabFiltered }: Props) {
export function UserProfileTask({ profile, paginateTasks, tabFiltered, user }: Props) {
const [scrollableContainer, setScrollableContainer] = useState<HTMLDivElement | null>(null);

const t = useTranslations();
Expand Down Expand Up @@ -93,7 +95,7 @@ export function UserProfileTask({ profile, paginateTasks, tabFiltered }: Props)
/>
)}
{tabFiltered.tab === 'stats' && <ScreenCalendar />}
{tabFiltered.tab === 'dailyplan' && <UserProfilePlans />}
{tabFiltered.tab === 'dailyplan' && <UserProfilePlans user={user} />}

{tabFiltered.tab === 'worked' && otherTasks.length > 0 && (
<div className="flex items-center my-6 space-x-2">
Expand Down

0 comments on commit 05eaa04

Please sign in to comment.