From 3204bb00376e90a832f9665959412d9603e654ab Mon Sep 17 00:00:00 2001 From: Anish Date: Sun, 2 Jun 2024 14:44:57 +0500 Subject: [PATCH] [Feat] Show user detail in accordion (#2569) * feat: member not found * feat: member not found * feat: member not found page working * feat: working on user detail section * feat: added accordion for user detail * feat: added accordion for user detail * feat: added accordion for user detail * feat: added accordion for user detail * feat: added accordion for user detail --- .../app/[locale]/profile/[memberId]/page.tsx | 3 +- .../app/hooks/features/useUserProfilePage.ts | 8 +- apps/web/app/stores/user.ts | 4 + .../features/team/user-team-card/index.tsx | 85 ++++++++++++++++--- .../team/user-team-card/user-info.tsx | 5 +- 5 files changed, 86 insertions(+), 19 deletions(-) diff --git a/apps/web/app/[locale]/profile/[memberId]/page.tsx b/apps/web/app/[locale]/profile/[memberId]/page.tsx index 1a537833a..49355dc2e 100644 --- a/apps/web/app/[locale]/profile/[memberId]/page.tsx +++ b/apps/web/app/[locale]/profile/[memberId]/page.tsx @@ -23,10 +23,11 @@ import { AppsTab } from 'lib/features/activity/apps'; import { VisitedSitesTab } from 'lib/features/activity/visited-sites'; import { activityTypeState } from '@app/stores/activity-type'; -type FilterTab = 'Tasks' | 'Screenshots' | 'Apps' | 'Visited Sites'; +export type FilterTab = 'Tasks' | 'Screenshots' | 'Apps' | 'Visited Sites'; const Profile = React.memo(function ProfilePage({ params }: { params: { memberId: string } }) { const profile = useUserProfilePage(); + const { user } = useAuthenticateUser(); const { isTrackingEnabled, activeTeam, activeTeamManagers } = useOrganizationTeams(); const members = activeTeam?.members; diff --git a/apps/web/app/hooks/features/useUserProfilePage.ts b/apps/web/app/hooks/features/useUserProfilePage.ts index 9a67841bd..037059780 100644 --- a/apps/web/app/hooks/features/useUserProfilePage.ts +++ b/apps/web/app/hooks/features/useUserProfilePage.ts @@ -8,19 +8,21 @@ import { useAuthTeamTasks } from './useAuthTeamTasks'; import { useOrganizationTeams } from './useOrganizationTeams'; import { useTaskStatistics } from './useTaskStatistics'; import { useTeamTasks } from './useTeamTasks'; +import { useRecoilValue } from 'recoil'; +import { userDetailAccordion } from '@app/stores'; export function useUserProfilePage() { const { activeTeam } = useOrganizationTeams(); const { activeTeamTask, updateTask } = useTeamTasks(); + const userMemberId = useRecoilValue(userDetailAccordion); const { user: auth } = useAuthenticateUser(); const { getTasksStatsData } = useTaskStatistics(); - const params = useParams(); const memberId: string = useMemo(() => { - return (params?.memberId ?? '') as string; + return (params?.memberId ?? userMemberId) as string; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [params]); + }, [params, userMemberId]); const members = activeTeam?.members || []; diff --git a/apps/web/app/stores/user.ts b/apps/web/app/stores/user.ts index c5fcb7c58..17396c06d 100644 --- a/apps/web/app/stores/user.ts +++ b/apps/web/app/stores/user.ts @@ -5,3 +5,7 @@ export const userState = atom({ key: 'userState', default: null }); +export const userDetailAccordion = atom({ + key: 'userDetailAccordion', + default: '' +}); diff --git a/apps/web/lib/features/team/user-team-card/index.tsx b/apps/web/lib/features/team/user-team-card/index.tsx index 0f7de2723..96f2f8db9 100644 --- a/apps/web/lib/features/team/user-team-card/index.tsx +++ b/apps/web/lib/features/team/user-team-card/index.tsx @@ -7,26 +7,32 @@ import { useTaskStatistics, useOrganizationTeams, useAuthenticateUser, - useTeamMemberCard + useTeamMemberCard, + useUserProfilePage } from '@app/hooks'; import { IClassName, IOrganizationTeamList, OT_Member } from '@app/interfaces'; -import { timerSecondsState } from '@app/stores'; +import { timerSecondsState, userDetailAccordion as userAccordion } from '@app/stores'; import { clsxm } from '@app/utils'; -import { Card, InputField, Text, VerticalSeparator } from 'lib/components'; -import { TaskTimes, TodayWorkedTime } from 'lib/features'; +import { Card, Container, InputField, Text, VerticalSeparator } from 'lib/components'; +import { TaskTimes, TodayWorkedTime, UserProfileTask, useTaskFilter } from 'lib/features'; import { useTranslations } from 'next-intl'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; import { TaskEstimateInfo } from './task-estimate'; import { TaskInfo } from './task-info'; import { UserInfo } from './user-info'; import { UserTeamCardMenu } from './user-team-card-menu'; -import React from 'react'; +import React, { useCallback, useState } from 'react'; import UserTeamActivity from './user-team-card-activity'; import { CollapseUpIcon, ExpandIcon } from '@components/ui/svgs/expand'; import { activityTypeState } from '@app/stores/activity-type'; import { SixSquareGridIcon } from 'assets/svg'; import { ChevronDoubleDownIcon } from '@heroicons/react/20/solid'; -import { useRouter } from 'next/navigation'; +import { ScreenshootTab } from 'lib/features/activity/screenshoots'; +import { AppsTab } from 'lib/features/activity/apps'; +import { VisitedSitesTab } from 'lib/features/activity/visited-sites'; +import { FilterTab } from '@app/[locale]/profile/[memberId]/page'; +import { Loader } from 'lucide-react'; +import { fullWidthState } from '@app/stores/fullWidth'; type IUserTeamCard = { active?: boolean; @@ -53,16 +59,18 @@ export function UserTeamCard({ onDragOver = () => null }: IUserTeamCard) { const t = useTranslations(); + const profile = useUserProfilePage(); + const [userDetailAccordion, setUserDetailAccordion] = useRecoilState(userAccordion); + const hook = useTaskFilter(profile); const memberInfo = useTeamMemberCard(member); const taskEdition = useTMCardTaskEdit(memberInfo.memberTask); - const { replace } = useRouter(); const { collaborativeSelect, user_selected, onUserSelect } = useCollaborative(memberInfo.memberUser); + const fullWidth = useRecoilValue(fullWidthState); const seconds = useRecoilValue(timerSecondsState); const setActivityFilter = useSetRecoilState(activityTypeState); const { activeTaskTotalStat, addSeconds } = useTaskStatistics(seconds); const [showActivity, setShowActivity] = React.useState(false); - const [userDetailAccordion, setUserDetailAccordion] = React.useState(false); const { activeTeamManagers } = useOrganizationTeams(); const { user } = useAuthenticateUser(); @@ -70,6 +78,7 @@ export function UserTeamCard({ const showActivityFilter = (type: 'DATE' | 'TICKET', member: OT_Member | null) => { setShowActivity((prev) => !prev); + setUserDetailAccordion(''); setActivityFilter((prev) => ({ ...prev, type, @@ -114,6 +123,21 @@ export function UserTeamCard({ )} ); + const [activityFilter, setActivity] = useState('Tasks'); + + const activityScreens = { + Tasks: , + Screenshots: , + Apps: , + 'Visited Sites': + }; + const changeActivityFilter = useCallback( + (filter: FilterTab) => { + setActivity(filter); + }, + [setActivity] + ); + const canSeeActivity = profile.userProfile?.id === user?.id || isManagerConnectedUser != -1; return (
{ - setUserDetailAccordion(!userDetailAccordion); - replace('/?memberId=' + (memberInfo?.memberUser?.id ?? '')); + setUserDetailAccordion( + userDetailAccordion == memberInfo.memberUser?.id + ? '' + : memberInfo.memberUser?.id ?? '' + ); }} className={clsxm('h-6 w-6 absolute right-4 top-0 cursor-pointer p-[3px]')} >
@@ -220,7 +250,36 @@ export function UserTeamCard({ {/* Card menu */}
{menu}
- {userDetailAccordion ?
: null} + {userDetailAccordion == memberInfo.memberUser?.id && + memberInfo.memberUser.id == profile.userProfile?.id ? ( +
+ {canSeeActivity && ( + +
+ {Object.keys(activityScreens).map((filter, i) => ( +
+ {i !== 0 && } +
changeActivityFilter(filter as FilterTab)} + > + {filter} +
+
+ ))} +
+
+ )} + {activityScreens[activityFilter] ?? null} +
+ ) : userDetailAccordion == memberInfo.memberUser?.id ? ( +
+ +
+ ) : null} - {publicTeam ? {fullname.slice(0, 1)} : fullname} - +
+ {publicTeam ? {fullname.slice(0, 1)} : fullname} +
{(member?.role?.name === 'MANAGER' || member?.role?.name === 'SUPER_ADMIN' || member?.role?.name === 'ADMIN') && (