Skip to content

Commit

Permalink
Merge branch 'develop' into feature/multi-select-dropdown
Browse files Browse the repository at this point in the history
  • Loading branch information
Innocent-Akim authored Aug 28, 2024
2 parents 2fa088d + 35abf3c commit 541995b
Show file tree
Hide file tree
Showing 28 changed files with 724 additions and 341 deletions.
4 changes: 2 additions & 2 deletions apps/web/app/[locale]/calendar/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const CalendarPage = () => {
params='AddManuelTime'
/>
<div
className='fixed top-20 flex flex-col border-b-[1px] dark:border-[#26272C] z-10 mx-0 w-full bg-white dark:bg-dark-high shadow-lg shadow-gray-100 dark:shadow-gray-700 '
className='fixed top-20 flex flex-col border-b-[1px] dark:border-gray-800 z-10 mx-0 w-full bg-white dark:bg-dark-high shadow-lg shadow-gray-100 dark:shadow-gray-700 '
>
<Container fullWidth={fullWidth}>
<div className="flex bg-white dark:bg-dark-high flex-row items-start justify-between mt-12">
Expand All @@ -82,7 +82,7 @@ const CalendarPage = () => {
setCalendarTimeSheet={setCalendarTimeSheet}

/>
<div className='border border-gray-100 dark:border-gray-700 w-full'></div>
<div className='border border-gray-100 dark:border-gray-800 w-full'></div>
</div>
</Container>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { useTimer } from '@app/hooks';
import { ITimerStatusEnum, OT_Member } from '@app/interfaces';
import { isValidUrl } from '@app/utils';
import { getTimerStatusValue, TimerStatus } from 'lib/features';
import { cn } from 'lib/utils';
import { useMemo } from 'react';
import stc from 'string-to-color';
import { Avatar, Text } from 'lib/components';
import { imgTitle } from '@app/helpers';
import { TableActionPopover } from 'lib/settings/table-action-popover';

export function UserProfileDetail({ member }: { member?: OT_Member }) {
const user = useMemo(() => member?.employee.user, [member?.employee.user]);

const userName = `${user?.firstName || ''} ${user?.lastName || ''}`;
const imgUrl = user?.image?.thumbUrl || user?.image?.fullUrl || user?.imageUrl;
const imageUrl = useMemo(() => imgUrl, [imgUrl]);
const size = 100;
const { timerStatus } = useTimer();
// const isManager = activeTeamManagers.find((member) => member.employee.user?.id === member?.employee.user?.id);
const timerStatusValue: ITimerStatusEnum = useMemo(() => {
return getTimerStatusValue(timerStatus, member, false);
}, [timerStatus, member]);
return (
<div className="flex items-center mb-4 space-x-4 md:mb-0">
<div
className={cn(
`w-[100px] h-[100px]`, // removed the size variable from width and height, as passing variables is not supported by tailwind
'flex justify-center items-center relative',
'rounded-full text-white',
'shadow-md text-7xl dark:text-6xl font-thin font-PlusJakartaSans ',
!imageUrl && 'dark:border-[0.375rem] dark:border-[#26272C]'
)}
style={{
backgroundColor: `${stc(userName)}80`
}}
>
{imageUrl && isValidUrl(imageUrl) ? (
<Avatar
size={size}
className="relative dark:border-[0.375rem] dark:border-[#26272C]"
imageUrl={imageUrl}
alt={userName}
imageTitle={userName.charAt(0)}
>
<TimerStatus
status={timerStatusValue}
className="absolute z-20 bottom-3 right-[10%] -mb-5 border-[0.2956rem] border-white dark:border-[#26272C]"
tooltipClassName="mt-24 dark:mt-20 mr-3"
/>
</Avatar>
) : (
<>
{imgTitle(userName).charAt(0)}

<TimerStatus
status={timerStatusValue}
className="absolute z-20 border-[0.2956rem] border-white dark:border-[#26272C]"
tooltipClassName="absolute -bottom-[0.625rem] dark:-bottom-[0.75rem] right-[10%] w-[1.875rem] h-[1.875rem] rounded-full"
/>
</>
)}
</div>
<div className="flex flex-col gap-3.5 w-full">
<div className="flex items-center gap-x-4">
<Text.Heading as="h3" className="text-2xl md:text-4xl">
{user?.firstName} {user?.lastName}
</Text.Heading>
<div className="h-8 w-8">
<TableActionPopover member={member!} status="profile" />
</div>
</div>
<Text className="text-lg text-gray-500">{user?.email}</Text>
</div>
</div>
);
}
268 changes: 95 additions & 173 deletions apps/web/app/[locale]/profile/[memberId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
'use client';

/* eslint-disable no-mixed-spaces-and-tabs */
import { imgTitle } from '@app/helpers';
import { useAuthenticateUser, useDailyPlan, useOrganizationTeams, useTimer, useUserProfilePage } from '@app/hooks';
import { ITimerStatusEnum, OT_Member } from '@app/interfaces';
import { clsxm, isValidUrl } from '@app/utils';
import clsx from 'clsx';
import { useAuthenticateUser, useDailyPlan, useOrganizationTeams, useUserProfilePage } from '@app/hooks';
import { withAuthentication } from 'lib/app/authenticator';
import { Avatar, Breadcrumb, Button, Container, Text, VerticalSeparator } from 'lib/components';
import { Breadcrumb, Button, Container, Text, VerticalSeparator } from 'lib/components';
import { ArrowLeftIcon } from 'assets/svg';
import { TaskFilter, Timer, TimerStatus, UserProfileTask, getTimerStatusValue, useTaskFilter } from 'lib/features';
import { TaskFilter, Timer, UserProfileTask, useTaskFilter } from 'lib/features';
import { MainHeader, MainLayout } from 'lib/layout';
import Link from 'next/link';
import React, { useCallback, useMemo, useState } from 'react';
import { useTranslations } from 'next-intl';
import stc from 'string-to-color';

import { useRecoilValue, useSetRecoilState } from 'recoil';
import { fullWidthState } from '@app/stores/fullWidth';
Expand All @@ -23,7 +18,8 @@ import { AppsTab } from 'lib/features/activity/apps';
import { VisitedSitesTab } from 'lib/features/activity/visited-sites';
import { activityTypeState } from '@app/stores/activity-type';
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@components/ui/resizable';
import { TableActionPopover } from 'lib/settings/table-action-popover';
import { UserProfileDetail } from './components/UserProfileDetail';
import { cn } from 'lib/utils';
// import { ActivityCalendar } from 'lib/features/activity/calendar';

export type FilterTab = 'Tasks' | 'Screenshots' | 'Apps' | 'Visited Sites';
Expand Down Expand Up @@ -90,179 +86,105 @@ const Profile = React.memo(function ProfilePage({ params }: { params: { memberId
getEmployeeDayPlans(profile.member?.employeeId ?? '');
}, [getEmployeeDayPlans, profile.member?.employeeId]);

return (
<>
{Array.isArray(members) && members.length && !profile.member ? (
<MainLayout>
<div
ref={profile.loadTaskStatsIObserverRef}
className="absolute top-[50%] left-[50%] transform -translate-x-1/2 -translate-y-1/2"
>
<div className="flex flex-col justify-center items-center gap-5">
<Text className="text-[40px] font-bold text-center text-[#282048] dark:text-light--theme">
{t('common.MEMBER')} {t('common.NOT_FOUND')}!
</Text>

<Text className=" font-light text-center text-gray-400">
{t('pages.profile.MEMBER_NOT_FOUND_MSG_1')}
</Text>
if (Array.isArray(members) && members.length && !profile.member) {
return (
<MainLayout>
<div
ref={profile.loadTaskStatsIObserverRef}
className="absolute top-[50%] left-[50%] transform -translate-x-1/2 -translate-y-1/2"
>
<div className="flex flex-col justify-center items-center gap-5">
<Text className="text-[40px] font-bold text-center text-[#282048] dark:text-light--theme">
{t('common.MEMBER')} {t('common.NOT_FOUND')}!
</Text>

<Text className=" font-light text-center text-gray-400">
{t('pages.profile.MEMBER_NOT_FOUND_MSG_1')}
</Text>

<Button className="m-auto font-normal rounded-lg ">
<Link href="/">{t('pages.profile.GO_TO_HOME')}</Link>
</Button>
</div>
</div>
</MainLayout>
);
}

<Button className="m-auto font-normal rounded-lg ">
<Link href="/">{t('pages.profile.GO_TO_HOME')}</Link>
</Button>
return (
<MainLayout showTimer={(headerSize <= 11.8 && isTrackingEnabled) || !profileIsAuthUser}>
<ResizablePanelGroup direction="vertical">
<ResizablePanel
defaultSize={30}
maxSize={48}
className={cn(headerSize < 20 ? '!overflow-hidden' : '!overflow-visible')}
onResize={(size) => setHeaderSize(size)}
>
<MainHeader fullWidth={fullWidth} className={cn(hookFilterType && ['pb-0'], 'pb-2')}>
{/* Breadcrumb */}
<div className="flex items-center gap-8">
<Link href="/">
<ArrowLeftIcon className="w-6 h-6" />
</Link>

<Breadcrumb paths={breadcrumb} className="text-sm" />
</div>
</div>
</MainLayout>
) : (
<MainLayout showTimer={(headerSize <= 11.8 && isTrackingEnabled) || !profileIsAuthUser}>
<ResizablePanelGroup direction="vertical">
<ResizablePanel
defaultSize={30}
maxSize={48}
className={clsxm(headerSize < 20 ? '!overflow-hidden' : '!overflow-visible')}
onResize={(size) => setHeaderSize(size)}
>
<MainHeader fullWidth={fullWidth} className={clsxm(hookFilterType && ['pb-0'], 'pb-2')}>
{/* Breadcrumb */}
<div className="flex items-center gap-8">
<Link href="/">
<ArrowLeftIcon className="w-6 h-6" />
</Link>

<Breadcrumb paths={breadcrumb} className="text-sm" />
</div>
{/* User Profile Detail */}
<div className="flex flex-col items-center justify-between py-5 md:py-10 md:flex-row">
<UserProfileDetail member={profile.member} />

{/* User Profile Detail */}
<div className="flex flex-col items-center justify-between py-5 md:py-10 md:flex-row">
<UserProfileDetail member={profile.member} />
{profileIsAuthUser && isTrackingEnabled && (
<Timer
className={clsxm(
'p-5 rounded-2xl shadow-xlcard',
'dark:border-[0.125rem] dark:border-[#28292F]',
'dark:bg-[#1B1D22]'
)}
/>
{profileIsAuthUser && isTrackingEnabled && (
<Timer
className={cn(
'p-5 rounded-2xl shadow-xlcard',
'dark:border-[0.125rem] dark:border-[#28292F]',
'dark:bg-[#1B1D22]'
)}
</div>
{/* TaskFilter */}
<TaskFilter profile={profile} hook={hook} />
</MainHeader>
{/* <div className="p-1">
/>
)}
</div>
{/* TaskFilter */}
<TaskFilter profile={profile} hook={hook} />
</MainHeader>
{/* <div className="p-1">
<ActivityCalendar />
</div> */}
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={65} maxSize={95} className="!overflow-y-scroll custom-scrollbar">
{hook.tab == 'worked' && canSeeActivity && (
<Container fullWidth={fullWidth} className="py-8">
<div className={clsxm('flex justify-start items-center gap-4 mt-3')}>
{Object.keys(activityScreens).map((filter, i) => (
<div
key={i}
className="flex cursor-pointer justify-start items-center gap-4"
>
{i !== 0 && <VerticalSeparator />}
<div
className={clsxm(
'text-gray-500',
activityFilter == filter && 'text-black dark:text-white'
)}
onClick={() => changeActivityFilter(filter as FilterTab)}
>
{filter}
</div>
</div>
))}
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={65} maxSize={95} className="!overflow-y-scroll custom-scrollbar">
{hook.tab == 'worked' && canSeeActivity && (
<Container fullWidth={fullWidth} className="py-8">
<div className={cn('flex justify-start items-center gap-4 mt-3')}>
{Object.keys(activityScreens).map((filter, i) => (
<div key={i} className="flex cursor-pointer justify-start items-center gap-4">
{i !== 0 && <VerticalSeparator />}
<div
className={cn(
'text-gray-500',
activityFilter == filter && 'text-black dark:text-white'
)}
onClick={() => changeActivityFilter(filter as FilterTab)}
>
{filter}
</div>
</div>
</Container>
)}

<Container fullWidth={fullWidth} className="mb-10">
{hook.tab !== 'worked' || activityFilter == 'Tasks' ? (
<UserProfileTask profile={profile} tabFiltered={hook} />
) : (
activityScreens[activityFilter] ?? null
)}
</Container>
</ResizablePanel>
</ResizablePanelGroup>
</MainLayout>
)}
</>
))}
</div>
</Container>
)}

<Container fullWidth={fullWidth} className="mb-10">
{hook.tab !== 'worked' || activityFilter == 'Tasks' ? (
<UserProfileTask profile={profile} tabFiltered={hook} paginateTasks={true} />
) : (
activityScreens[activityFilter] ?? null
)}
</Container>
</ResizablePanel>
</ResizablePanelGroup>
</MainLayout>
);
});

function UserProfileDetail({ member }: { member?: OT_Member }) {
const user = useMemo(() => member?.employee.user, [member?.employee.user]);

const userName = `${user?.firstName || ''} ${user?.lastName || ''}`;
const imgUrl = user?.image?.thumbUrl || user?.image?.fullUrl || user?.imageUrl;
const imageUrl = useMemo(() => imgUrl, [imgUrl]);
const size = 100;
const { timerStatus } = useTimer();
// const isManager = activeTeamManagers.find((member) => member.employee.user?.id === member?.employee.user?.id);
const timerStatusValue: ITimerStatusEnum = useMemo(() => {
return getTimerStatusValue(timerStatus, member, false);
}, [timerStatus, member]);
return (
<div className="flex items-center mb-4 space-x-4 md:mb-0">

<div
className={clsx(
`w-[100px] h-[100px]`, // removed the size variable from width and height, as passing variables is not supported by tailwind
'flex justify-center items-center relative',
'rounded-full text-white',
'shadow-md text-7xl dark:text-6xl font-thin font-PlusJakartaSans ',
!imageUrl && 'dark:border-[0.375rem] dark:border-[#26272C]'
)}
style={{
backgroundColor: `${stc(userName)}80`
}}
>

{imageUrl && isValidUrl(imageUrl) ? (
<Avatar
size={size}
className="relative dark:border-[0.375rem] dark:border-[#26272C]"
imageUrl={imageUrl}
alt={userName}
imageTitle={userName.charAt(0)}
>

<TimerStatus
status={timerStatusValue}
className="absolute z-20 bottom-3 right-[10%] -mb-5 border-[0.2956rem] border-white dark:border-[#26272C]"
tooltipClassName="mt-24 dark:mt-20 mr-3"
/>

</Avatar>
) : (
<>

{imgTitle(userName).charAt(0)}

<TimerStatus
status={timerStatusValue}
className="absolute z-20 border-[0.2956rem] border-white dark:border-[#26272C]"
tooltipClassName="absolute -bottom-[0.625rem] dark:-bottom-[0.75rem] right-[10%] w-[1.875rem] h-[1.875rem] rounded-full"
/>
</>
)}
</div>
<div className="flex flex-col gap-3.5 w-full">
<div className='flex items-center gap-x-4'>
<Text.Heading as="h3" className="text-2xl md:text-4xl">
{user?.firstName} {user?.lastName}
</Text.Heading>
<div className='h-8 w-8'>
<TableActionPopover member={member!} status='profile' />
</div>
</div>
<Text className="text-lg text-gray-500">{user?.email}</Text>
</div>
</div>
);
}

export default withAuthentication(Profile, { displayName: 'ProfilePage' });
Loading

0 comments on commit 541995b

Please sign in to comment.