diff --git a/apps/web/app/[locale]/auth/password/component.tsx b/apps/web/app/[locale]/auth/password/component.tsx index dec387ab3..ad22c6d7c 100644 --- a/apps/web/app/[locale]/auth/password/component.tsx +++ b/apps/web/app/[locale]/auth/password/component.tsx @@ -123,6 +123,7 @@ function WorkSpaceScreen({ form, className }: { form: TAuthenticationPassword } [form.workspaces] ); + useEffect(() => { if (form.workspaces.length === 1 && !hasMultipleTeams) { setTimeout(() => { @@ -149,6 +150,7 @@ function WorkSpaceScreen({ form, className }: { form: TAuthenticationPassword } ); setSelectedTeam(lastSelectedTeamId); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form.workspaces]); useEffect(() => { diff --git a/apps/web/app/[locale]/calendar/component.tsx b/apps/web/app/[locale]/calendar/component.tsx index 6656ec634..f000fa1d8 100644 --- a/apps/web/app/[locale]/calendar/component.tsx +++ b/apps/web/app/[locale]/calendar/component.tsx @@ -70,10 +70,16 @@ export function HeadTimeSheet({ timesheet, isOpen, openModal, closeModal }: { ti return (
- + { + closeModal ? ( + + ) : + <> + } +
{timesheet === 'TimeSheet' && (
diff --git a/apps/web/app/[locale]/kanban/page.tsx b/apps/web/app/[locale]/kanban/page.tsx index c7dff39c2..4b2aab1d7 100644 --- a/apps/web/app/[locale]/kanban/page.tsx +++ b/apps/web/app/[locale]/kanban/page.tsx @@ -62,7 +62,7 @@ const Kanban = () => { { title: activeTeam?.name || '', href: '/' }, { title: t('common.KANBAN'), href: `/${currentLocale}/kanban` } ], - [activeTeam?.name, currentLocale] + [activeTeam?.name, currentLocale, t] ); const activeTeamMembers = activeTeam?.members ? activeTeam.members : []; diff --git a/apps/web/app/[locale]/meet/livekit/component.tsx b/apps/web/app/[locale]/meet/livekit/component.tsx index f362623f0..ad382fc81 100644 --- a/apps/web/app/[locale]/meet/livekit/component.tsx +++ b/apps/web/app/[locale]/meet/livekit/component.tsx @@ -41,7 +41,7 @@ function LiveKitPage() {
{token && roomName &&
- + {member ? : <>}
{user?.email} diff --git a/apps/web/app/helpers/daily-plan-estimated.ts b/apps/web/app/helpers/daily-plan-estimated.ts index 1c18fb348..6d81d429d 100644 --- a/apps/web/app/helpers/daily-plan-estimated.ts +++ b/apps/web/app/helpers/daily-plan-estimated.ts @@ -20,9 +20,10 @@ export const dailyPlanCompareEstimated = (plans: IDailyPlan[]): IDailyPlanCompar }; } - const workTimePlanned = convertHourToSeconds(plan.workTimePlanned!); + const workTimePlanned = plan.workTimePlanned ? convertHourToSeconds(plan.workTimePlanned) : 0; const times = plan.tasks?.map((task) => task.estimate).filter((time): time is number => typeof time === 'number') ?? []; - const estimated = plan.tasks?.map((task) => task.estimate! > 0); + const estimated = plan.tasks?.map((task) => (task.estimate ?? 0) > 0); + let estimatedTime = 0; if (times.length > 0) { diff --git a/apps/web/app/helpers/drag-and-drop.ts b/apps/web/app/helpers/drag-and-drop.ts index c1d3af554..639766aca 100644 --- a/apps/web/app/helpers/drag-and-drop.ts +++ b/apps/web/app/helpers/drag-and-drop.ts @@ -1,48 +1,52 @@ -import { IDailyPlan, ITeamTask } from "@app/interfaces"; -import { DropResult } from "react-beautiful-dnd"; +import { IDailyPlan, ITeamTask } from '@app/interfaces'; +import { DropResult } from 'react-beautiful-dnd'; -export const handleDragAndDrop = (results: DropResult, plans: IDailyPlan[], setPlans: React.Dispatch>) => { - const { source, destination } = results; +export const handleDragAndDrop = ( + results: DropResult, + plans: IDailyPlan[], + setPlans: React.Dispatch> +) => { + const { source, destination } = results; - if (!destination || (source.droppableId === destination.droppableId && source.index === destination.index)) return; + if (!destination || (source.droppableId === destination.droppableId && source.index === destination.index)) return; - const newPlans = [...plans]; + const newPlans = [...plans]; - const planSourceIndex = newPlans.findIndex(plan => plan.id === source.droppableId); - const planDestinationIndex = newPlans.findIndex(plan => plan.id === destination.droppableId); + const planSourceIndex = newPlans.findIndex((plan) => plan.id === source.droppableId); + const planDestinationIndex = newPlans.findIndex((plan) => plan.id === destination.droppableId); - const newSourceTasks = [...newPlans[planSourceIndex].tasks!]; - const newDestinationTasks = source.droppableId !== destination.droppableId - ? [...newPlans[planDestinationIndex].tasks!] - : newSourceTasks; + const newSourceTasks = [...(newPlans[planSourceIndex].tasks ?? [])]; + const newDestinationTasks = + source.droppableId !== destination.droppableId + ? [...(newPlans[planDestinationIndex].tasks ?? [])] + : newSourceTasks; - const [deletedTask] = newSourceTasks.splice(source.index, 1); - newDestinationTasks.splice(destination.index, 0, deletedTask); + const [deletedTask] = newSourceTasks.splice(source.index, 1); + newDestinationTasks.splice(destination.index, 0, deletedTask); - newPlans[planSourceIndex] = { - ...newPlans[planSourceIndex], - tasks: newSourceTasks, - }; - newPlans[planDestinationIndex] = { - ...newPlans[planDestinationIndex], - tasks: newDestinationTasks, - }; - setPlans(newPlans); + newPlans[planSourceIndex] = { + ...newPlans[planSourceIndex], + tasks: newSourceTasks + }; + newPlans[planDestinationIndex] = { + ...newPlans[planDestinationIndex], + tasks: newDestinationTasks + }; + setPlans(newPlans); }; - export const handleDragAndDropDailyOutstandingAll = ( - results: DropResult, - tasks: ITeamTask[], - setTasks: React.Dispatch> + results: DropResult, + tasks: ITeamTask[], + setTasks: React.Dispatch> ) => { - const { source, destination } = results; + const { source, destination } = results; - if (!destination || (source.droppableId === destination.droppableId && source.index === destination.index)) return; + if (!destination || (source.droppableId === destination.droppableId && source.index === destination.index)) return; - const newTasks = [...tasks]; - const [movedTask] = newTasks.splice(source.index, 1); - newTasks.splice(destination.index, 0, movedTask); + const newTasks = [...tasks]; + const [movedTask] = newTasks.splice(source.index, 1); + newTasks.splice(destination.index, 0, movedTask); - setTasks(newTasks); + setTasks(newTasks); }; diff --git a/apps/web/app/helpers/plan-day-badge.ts b/apps/web/app/helpers/plan-day-badge.ts index 1bd23d610..409e350e7 100644 --- a/apps/web/app/helpers/plan-day-badge.ts +++ b/apps/web/app/helpers/plan-day-badge.ts @@ -29,26 +29,25 @@ export const planBadgeContent = ( } }; - -export const planBadgeContPast = ( - dailyPlan: IDailyPlan[], - taskId: ITeamTask['id'] -): string | null => { +export const planBadgeContPast = (dailyPlan: IDailyPlan[], taskId: ITeamTask['id']): string | null => { const today = new Date().toISOString().split('T')[0]; - const dailyPlanDataPast = dailyPlan.filter(plan => new Date(plan.date) < new Date(today)); - const allTasks = dailyPlanDataPast.flatMap(plan => plan.tasks); - const taskCount: { [key: string]: number } = allTasks?.reduce((acc, task) => { - if (task && task.id) { acc[task.id] = (acc[task.id] || 0) + 1; } - return acc; - }, {} as { [key: string]: number }); - - const dailyPlanPast = allTasks?.filter(task => task && taskCount[task.id] === 1); + const dailyPlanDataPast = dailyPlan.filter((plan) => new Date(plan.date) < new Date(today)); + const allTasks = dailyPlanDataPast.flatMap((plan) => plan.tasks); + const taskCount: { [key: string]: number } = allTasks?.reduce( + (acc, task) => { + if (task && task.id) { + acc[task.id] = (acc[task.id] || 0) + 1; + } + return acc; + }, + {} as { [key: string]: number } + ); + + const dailyPlanPast = allTasks?.filter((task) => task && taskCount[task.id] === 1); const filterDailyPlan = dailyPlanPast.filter((plan) => plan?.id === taskId); if (filterDailyPlan.length > 0) { return 'Planned'; } else { return null; } - - -} +}; diff --git a/apps/web/app/hooks/auth/useAuthenticationPasscode.ts b/apps/web/app/hooks/auth/useAuthenticationPasscode.ts index 724f309e1..9f2ecb175 100644 --- a/apps/web/app/hooks/auth/useAuthenticationPasscode.ts +++ b/apps/web/app/hooks/auth/useAuthenticationPasscode.ts @@ -14,6 +14,7 @@ import { usePathname, useSearchParams } from 'next/navigation'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useQuery } from '../useQuery'; import { useRouter } from 'next/navigation'; +import { useTranslations } from 'next-intl'; type AuthCodeRef = { focus: () => void; @@ -24,6 +25,7 @@ export function useAuthenticationPasscode() { const router = useRouter(); const pathname = usePathname(); const query = useSearchParams(); + const t = useTranslations(); const queryTeamId = query?.get('teamId'); @@ -72,83 +74,104 @@ export function useAuthenticationPasscode() { setFormValues((prevState) => ({ ...prevState, [name]: value })); }; + const signInToWorkspaceRequest = useCallback( + (params: { + email: string; + token: string; + selectedTeam: string; + code?: string; + defaultTeamId?: string; + lastTeamId?: string; + }) => { + signInWorkspaceQueryCall(params) + .then(() => { + setAuthenticated(true); + router.push('/'); + }) + .catch((err: AxiosError) => { + if (err.response?.status === 400) { + setErrors((err.response?.data as any)?.errors || {}); + } + + inputCodeRef.current?.clear(); + }); + }, + [signInWorkspaceQueryCall, router] + ); + /** * Verify auth request */ - const verifySignInEmailConfirmRequest = async ({ - email, - code, - lastTeamId - }: { - email: string; - code: string; - lastTeamId?: string; - }) => { - signInEmailConfirmQueryCall(email, code) - .then((res) => { - if ('team' in res.data) { - router.replace('/'); - return; - } - - const checkError: { - message: string; - } = res.data as any; - - const isError = checkError.message === 'Unauthorized'; - - if (isError) { - setErrors({ - code: 'Invalid code. Please try again.' - }); - } else { - setErrors({}); - } - - const data = res.data as ISigninEmailConfirmResponse; - if (!data.workspaces) { - return; - } - - if (data && Array.isArray(data.workspaces) && data.workspaces.length > 0) { - setWorkspaces(data.workspaces); - setDefaultTeamId(data.defaultTeamId); - - setScreen('workspace'); - } - - // If user tries to login from public Team Page as an Already a Member - // Redirect to the current team automatically - if (pathname === '/team/[teamId]/[profileLink]' && data.workspaces.length) { - if (queryTeamId) { - const currentWorkspace = data.workspaces.find((workspace) => - workspace.current_teams.map((item) => item.team_id).includes(queryTeamId as string) - ); - - signInToWorkspaceRequest({ - email: email, - code: code, - token: currentWorkspace?.token as string, - selectedTeam: queryTeamId as string, - lastTeamId + const verifySignInEmailConfirmRequest = useCallback( + async ({ email, code, lastTeamId }: { email: string; code: string; lastTeamId?: string }) => { + signInEmailConfirmQueryCall(email, code) + .then((res) => { + if ('team' in res.data) { + router.replace('/'); + return; + } + + const checkError: { + message: string; + } = res.data as any; + + const isError = checkError.message === 'Unauthorized'; + + if (isError) { + setErrors({ + code: t('pages.auth.INVALID_CODE_TRY_AGAIN') }); + } else { + setErrors({}); } - } - - // if (res.data?.status !== 200 && res.data?.status !== 201) { - // setErrors({ code: t('pages.auth.INVALID_INVITE_CODE_MESSAGE') }); - // } - }) - .catch((err: AxiosError<{ errors: Record }, any> | { errors: Record }) => { - if (isAxiosError(err)) { - if (err.response?.status === 400) { - setErrors(err.response.data?.errors || {}); + + const data = res.data as ISigninEmailConfirmResponse; + if (!data.workspaces) { + return; + } + + if (data && Array.isArray(data.workspaces) && data.workspaces.length > 0) { + setWorkspaces(data.workspaces); + setDefaultTeamId(data.defaultTeamId); + + setScreen('workspace'); + } + + // If user tries to login from public Team Page as an Already a Member + // Redirect to the current team automatically + if (pathname === '/team/[teamId]/[profileLink]' && data.workspaces.length) { + if (queryTeamId) { + const currentWorkspace = data.workspaces.find((workspace) => + workspace.current_teams.map((item) => item.team_id).includes(queryTeamId as string) + ); + + signInToWorkspaceRequest({ + email: email, + code: code, + token: currentWorkspace?.token as string, + selectedTeam: queryTeamId as string, + lastTeamId + }); + } } - } else { - setErrors(err.errors || {}); - } - }); - }; + + // if (res.data?.status !== 200 && res.data?.status !== 201) { + // setErrors({ code: t('pages.auth.INVALID_INVITE_CODE_MESSAGE') }); + // } + }) + .catch((err: AxiosError<{ errors: Record }, any> | { errors: Record }) => { + if (isAxiosError(err)) { + if (err.response?.status === 400) { + setErrors(err.response.data?.errors || {}); + } + } else { + setErrors(err.errors || {}); + } + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, + [signInEmailConfirmQueryCall, t, signInToWorkspaceRequest, router, pathname, queryTeamId] + ); const verifyPasscodeRequest = useCallback( ({ email, code }: { email: string; code: string }) => { @@ -175,28 +198,6 @@ export function useAuthenticationPasscode() { [queryCall] ); - const signInToWorkspaceRequest = (params: { - email: string; - token: string; - selectedTeam: string; - code?: string; - defaultTeamId?: string; - lastTeamId?: string; - }) => { - signInWorkspaceQueryCall(params) - .then(() => { - setAuthenticated(true); - router.push('/'); - }) - .catch((err: AxiosError) => { - if (err.response?.status === 400) { - setErrors((err.response?.data as any)?.errors || {}); - } - - inputCodeRef.current?.clear(); - }); - }; - const handleCodeSubmit = (e: React.FormEvent) => { e.preventDefault(); setErrors({}); diff --git a/apps/web/app/hooks/features/useDailyPlan.ts b/apps/web/app/hooks/features/useDailyPlan.ts index c8a561547..a8be0524c 100644 --- a/apps/web/app/hooks/features/useDailyPlan.ts +++ b/apps/web/app/hooks/features/useDailyPlan.ts @@ -1,7 +1,7 @@ 'use client'; import { useRecoilState, useRecoilValue } from 'recoil'; -import { useCallback, useEffect } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { useQuery } from '../useQuery'; import { activeTeamState, @@ -269,77 +269,87 @@ export function useDailyPlan() { ] ); - const ascSortedPlans = - profileDailyPlans.items && - [...profileDailyPlans.items].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); - const futurePlans = ascSortedPlans?.filter((plan) => { - const planDate = new Date(plan.date); - const today = new Date(); - today.setHours(23, 59, 59, 0); // Set today time to exclude timestamps in comparization - return planDate.getTime() >= today.getTime(); - }); - - const descSortedPlans = - profileDailyPlans.items && - [...profileDailyPlans.items].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); - const pastPlans = descSortedPlans?.filter((plan) => { - const planDate = new Date(plan.date); - const today = new Date(); - today.setHours(0, 0, 0, 0); // Set today time to exclude timestamps in comparization - return planDate.getTime() < today.getTime(); - }); - - const todayPlan = - profileDailyPlans.items && - [...profileDailyPlans.items].filter((plan) => + const ascSortedPlans = useMemo(() => { + return [...profileDailyPlans.items].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); + }, [profileDailyPlans]); + + const futurePlans = useMemo(() => { + return ascSortedPlans?.filter((plan) => { + const planDate = new Date(plan.date); + const today = new Date(); + today.setHours(23, 59, 59, 0); // Set today time to exclude timestamps in comparization + return planDate.getTime() >= today.getTime(); + }); + }, [ascSortedPlans]); + + const descSortedPlans = useMemo(() => { + return [...profileDailyPlans.items].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); + }, [profileDailyPlans]); + + const pastPlans = useMemo(() => { + return descSortedPlans?.filter((plan) => { + const planDate = new Date(plan.date); + const today = new Date(); + today.setHours(0, 0, 0, 0); // Set today time to exclude timestamps in comparization + return planDate.getTime() < today.getTime(); + }); + }, [descSortedPlans]); + + const todayPlan = useMemo(() => { + return [...profileDailyPlans.items].filter((plan) => plan.date?.toString()?.startsWith(new Date()?.toISOString().split('T')[0]) ); + }, [profileDailyPlans]); - const todayTasks = todayPlan - .map((plan) => { - return plan.tasks ? plan.tasks : []; - }) - .flat(); - - const futureTasks = - futurePlans && - futurePlans + const todayTasks = useMemo(() => { + return todayPlan .map((plan) => { return plan.tasks ? plan.tasks : []; }) .flat(); + }, [todayPlan]); - const outstandingPlans = - profileDailyPlans.items && - [...profileDailyPlans.items] - // Exclude today plans - .filter((plan) => !plan.date?.toString()?.startsWith(new Date()?.toISOString().split('T')[0])) - - // Exclude future plans - .filter((plan) => { - const planDate = new Date(plan.date); - const today = new Date(); - today.setHours(23, 59, 59, 0); // Set today time to exclude timestamps in comparization - return planDate.getTime() <= today.getTime(); + const futureTasks = useMemo(() => { + return futurePlans + .map((plan) => { + return plan.tasks ? plan.tasks : []; }) - .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()) - .map((plan) => ({ - ...plan, - // Include only no completed tasks - tasks: plan.tasks?.filter((task) => task.status !== 'completed') - })) - .map((plan) => ({ - ...plan, - // Include only tasks that are not added yet to the today plan or future plans - tasks: plan.tasks?.filter( - (_task) => ![...todayTasks, ...futureTasks].find((task) => task.id === _task.id) - ) - })) - .filter((plan) => plan.tasks?.length && plan.tasks.length > 0); - - const sortedPlans = - profileDailyPlans.items && - [...profileDailyPlans.items].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); + .flat(); + }, [futurePlans]); + + const outstandingPlans = useMemo(() => { + return ( + [...profileDailyPlans.items] + // Exclude today plans + .filter((plan) => !plan.date?.toString()?.startsWith(new Date()?.toISOString().split('T')[0])) + + // Exclude future plans + .filter((plan) => { + const planDate = new Date(plan.date); + const today = new Date(); + today.setHours(23, 59, 59, 0); // Set today time to exclude timestamps in comparization + return planDate.getTime() <= today.getTime(); + }) + .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()) + .map((plan) => ({ + ...plan, + // Include only no completed tasks + tasks: plan.tasks?.filter((task) => task.status !== 'completed') + })) + .map((plan) => ({ + ...plan, + // Include only tasks that are not added yet to the today plan or future plans + tasks: plan.tasks?.filter( + (_task) => ![...todayTasks, ...futureTasks].find((task) => task.id === _task.id) + ) + })) + .filter((plan) => plan.tasks?.length && plan.tasks.length > 0) + ); + }, [profileDailyPlans, todayTasks, futureTasks]); + + const sortedPlans = useMemo(() => { + return [...profileDailyPlans.items].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); + }, [profileDailyPlans]); useEffect(() => { if (firstLoad) { diff --git a/apps/web/app/hooks/features/useEmployee.ts b/apps/web/app/hooks/features/useEmployee.ts index 4ca1d9037..5cf037242 100644 --- a/apps/web/app/hooks/features/useEmployee.ts +++ b/apps/web/app/hooks/features/useEmployee.ts @@ -55,7 +55,7 @@ export const useEmployeeUpdate = () => { .catch((error) => { console.log(error); }); - }, []); + }, [employeeUpdateQuery]); return { updateEmployee, isLoading }; }; diff --git a/apps/web/app/hooks/features/useGetTasksStatsData.ts b/apps/web/app/hooks/features/useGetTasksStatsData.ts index 37e8548d9..f4d8a67ff 100644 --- a/apps/web/app/hooks/features/useGetTasksStatsData.ts +++ b/apps/web/app/hooks/features/useGetTasksStatsData.ts @@ -32,7 +32,7 @@ export function useGetTasksStatsData(employeeId: string | undefined, triggerWith if (entry?.isIntersecting && supported) { loadTaskStats(); } - }, [employeeId, triggerWithIObserver, entry]); + }, [employeeId, triggerWithIObserver, entry, getTasksStatsData]); return IObserverRef; } diff --git a/apps/web/app/hooks/features/useOrganizationTeamManagers.ts b/apps/web/app/hooks/features/useOrganizationTeamManagers.ts index edaab309e..b379bd566 100644 --- a/apps/web/app/hooks/features/useOrganizationTeamManagers.ts +++ b/apps/web/app/hooks/features/useOrganizationTeamManagers.ts @@ -2,18 +2,21 @@ import { useRecoilValue } from 'recoil'; import { useAuthenticateUser } from './useAuthenticateUser'; import { useOrganizationTeams } from './useOrganizationTeams'; import { filterValue } from '@app/stores/all-teams'; +import { useMemo } from 'react'; export function useOrganizationAndTeamManagers() { const { user } = useAuthenticateUser(); const { teams } = useOrganizationTeams(); const { value: filtered } = useRecoilValue(filterValue); - const userManagedTeams = teams.filter((team) => - team.members.some((member) => member.employee?.user?.id === user?.id && member.role?.name === 'MANAGER') - ); + const userManagedTeams = useMemo(() => { + return teams.filter((team) => + team.members.some((member) => member.employee?.user?.id === user?.id && member.role?.name === 'MANAGER') + ); + }, [teams, user]); - const filteredTeams = - filtered === 'all' + const filteredTeams = useMemo(() => { + return filtered === 'all' ? userManagedTeams : filtered === 'pause' ? userManagedTeams.map((team) => ({ @@ -36,6 +39,7 @@ export function useOrganizationAndTeamManagers() { members: team.members.filter((member) => member.employee.acceptDate) })) : userManagedTeams; + }, [filtered, userManagedTeams]); return { userManagedTeams, diff --git a/apps/web/app/hooks/features/usePagination.ts b/apps/web/app/hooks/features/usePagination.ts index 3b4630b7b..f1a19a96a 100644 --- a/apps/web/app/hooks/features/usePagination.ts +++ b/apps/web/app/hooks/features/usePagination.ts @@ -48,7 +48,7 @@ export function useScrollPagination({ setPage(1); setSlicedItems(items.slice(0, defaultItemsPerPage)); } - }, [enabled, items]); + }, [enabled, items, defaultItemsPerPage]); useEffect(() => { const container = $scrollableElement.current; @@ -68,6 +68,8 @@ export function useScrollPagination({ return () => { container.removeEventListener('scroll', handleScroll); }; + + // eslint-disable-next-line react-hooks/exhaustive-deps }, [$scrollableElement.current, enabled]); useEffect(() => { diff --git a/apps/web/app/hooks/features/useTaskInput.ts b/apps/web/app/hooks/features/useTaskInput.ts index 241ca8f18..bb204f8f6 100644 --- a/apps/web/app/hooks/features/useTaskInput.ts +++ b/apps/web/app/hooks/features/useTaskInput.ts @@ -170,13 +170,17 @@ export function useTaskInput({ [updateTask, userRef] ); - const closedTaskCount = filteredTasks2.filter((f_task) => { - return f_task.status === 'closed'; - }).length; - - const openTaskCount = filteredTasks2.filter((f_task) => { - return f_task.status !== 'closed'; - }).length; + const closedTaskCount = useMemo(() => { + return filteredTasks2.filter((f_task) => { + return f_task.status === 'closed'; + }).length; + }, [filteredTasks2]); + + const openTaskCount = useMemo(() => { + return filteredTasks2.filter((f_task) => { + return f_task.status !== 'closed'; + }).length; + }, [filteredTasks2]); useEffect(() => { setTaskIssue(''); diff --git a/apps/web/app/hooks/features/useTeamTasks.ts b/apps/web/app/hooks/features/useTeamTasks.ts index a60f7d6c4..f317fb5fd 100644 --- a/apps/web/app/hooks/features/useTeamTasks.ts +++ b/apps/web/app/hooks/features/useTeamTasks.ts @@ -115,7 +115,7 @@ export function useTeamTasks() { return res; }); }, - [getTasksByIdQueryCall, setDetailedTask] + [getTasksByIdQueryCall, setDetailedTask, tasksRef] ); const getTasksByEmployeeId = useCallback( @@ -285,8 +285,8 @@ export function useTeamTasks() { // TODO: Make it dynamic when we add Dropdown in Navbar ...(activeTeam?.projects && activeTeam?.projects.length > 0 ? { - projectId: activeTeam.projects[0].id - } + projectId: activeTeam.projects[0].id + } : {}), ...(description ? { description: `

${description}

` } : {}), ...(members ? { members } : {}), @@ -451,7 +451,17 @@ export function useTeamTasks() { } } }, - [setActiveTeamTask, setActiveUserTaskCookieCb, updateOrganizationTeamEmployeeActiveTask, activeTeam, authUser] + [ + setActiveTeamTask, + setActiveUserTaskCookieCb, + updateOrganizationTeamEmployeeActiveTask, + activeTeam, + authUser, + $memberActiveTaskId, + $user, + tasksRef, + updateTask + ] ); const deleteEmployeeFromTasks = useCallback( diff --git a/apps/web/app/hooks/features/useTimeLogs.ts b/apps/web/app/hooks/features/useTimeLogs.ts index bd18fa220..49e9b1f96 100644 --- a/apps/web/app/hooks/features/useTimeLogs.ts +++ b/apps/web/app/hooks/features/useTimeLogs.ts @@ -43,7 +43,6 @@ export function useTimeLogs() { profile.member?.employeeId, queryTimerLogsDailyReport, setTimerLogsDailyReport, - user?.employee.id, user?.employee.organizationId, user?.tenantId, ] diff --git a/apps/web/app/hooks/features/useTimer.ts b/apps/web/app/hooks/features/useTimer.ts index d94e77b27..a54cce2e3 100644 --- a/apps/web/app/hooks/features/useTimer.ts +++ b/apps/web/app/hooks/features/useTimer.ts @@ -104,7 +104,7 @@ function useLocalTimeCounter(timerStatus: ITimerStatus | null, activeTeamTask: I // THis is form constant update of the progress line timerSecondsRef.current = useMemo(() => { - // if (!firstLoad) return 0; + if (!firstLoad) return 0; if (seconds > timerSecondsRef.current) { return seconds; } diff --git a/apps/web/app/hooks/features/useUserProfilePage.ts b/apps/web/app/hooks/features/useUserProfilePage.ts index 90303976a..74d5cf3fe 100644 --- a/apps/web/app/hooks/features/useUserProfilePage.ts +++ b/apps/web/app/hooks/features/useUserProfilePage.ts @@ -23,11 +23,13 @@ export function useUserProfilePage() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [params, userMemberId]); - const members = activeTeam?.members || []; + const members = useMemo(() => activeTeam?.members || [], [activeTeam]); - const matchUser = members.find((m) => { - return m.employee.userId === memberId; - }); + const matchUser = useMemo(() => { + return members.find((m) => { + return m.employee.userId === memberId; + }); + }, [members, memberId]); const isAuthUser = auth?.employee?.userId === memberId; diff --git a/apps/web/app/hooks/useDateRange.ts b/apps/web/app/hooks/useDateRange.ts index 4c8cfd08e..146737a74 100644 --- a/apps/web/app/hooks/useDateRange.ts +++ b/apps/web/app/hooks/useDateRange.ts @@ -1,18 +1,24 @@ -import { dateRangeAllPlanState, dateRangeFuturePlanState, dateRangePastPlanState, getFirstAndLastDateState } from "@app/stores"; -import { useRecoilState, useRecoilValue } from "recoil"; +import { + dateRangeAllPlanState, + dateRangeFuturePlanState, + dateRangePastPlanState, + getFirstAndLastDateState +} from '@app/stores'; +import { useRecoilState, useRecoilValue } from 'recoil'; export const useDateRange = (tab: string | any) => { - const itemsDate = useRecoilValue(getFirstAndLastDateState); - const [dateFuture, setDateFuture] = useRecoilState(dateRangeFuturePlanState); - const [dateAllPlan, setDateAllPlan] = useRecoilState(dateRangeAllPlanState); - const [datePastPlan, setDatePastPlan] = useRecoilState(dateRangePastPlanState); - switch (tab) { - case 'Future Tasks': - return { date: dateFuture, setDate: setDateFuture, data: itemsDate }; - case 'Past Tasks': - return { date: datePastPlan, setDate: setDatePastPlan, data: itemsDate }; - case 'All Tasks': - default: - return { date: dateAllPlan, setDate: setDateAllPlan, data: itemsDate }; - } -} + const itemsDate = useRecoilValue(getFirstAndLastDateState); + const [dateFuture, setDateFuture] = useRecoilState(dateRangeFuturePlanState); + const [dateAllPlan, setDateAllPlan] = useRecoilState(dateRangeAllPlanState); + const [datePastPlan, setDatePastPlan] = useRecoilState(dateRangePastPlanState); + + switch (tab) { + case 'Future Tasks': + return { date: dateFuture, setDate: setDateFuture, data: itemsDate }; + case 'Past Tasks': + return { date: datePastPlan, setDate: setDatePastPlan, data: itemsDate }; + case 'All Tasks': + default: + return { date: dateAllPlan, setDate: setDateAllPlan, data: itemsDate }; + } +}; diff --git a/apps/web/app/stores/daily-plan.ts b/apps/web/app/stores/daily-plan.ts index af57cd9da..95f5c0e59 100644 --- a/apps/web/app/stores/daily-plan.ts +++ b/apps/web/app/stores/daily-plan.ts @@ -3,7 +3,6 @@ import { IDailyPlan, PaginationResponse } from '@app/interfaces'; import { DateRange } from 'react-day-picker'; import { isTestDateRange } from '@app/helpers'; - export const dailyPlanListState = atom>({ key: 'dailyPlanListState', default: { items: [], total: 0 } @@ -47,70 +46,81 @@ export const activeDailyPlanState = selector({ return dailyPlans.items.find((plan) => plan.id === activeId) || dailyPlans.items[0] || null; } }); -const createDailyPlanCountFilterAtom = (key: string | any) => atom( - { + +const createDailyPlanCountFilterAtom = (key: string | any) => + atom({ key, default: 0 - } -) + }); -const createDailyPlanAtom = (key: string | any) => atom({ - key, - default: [], -}); +const createDailyPlanAtom = (key: string | any) => + atom({ + key, + default: [] + }); -const createDateRangeAtom = (key: string | any) => atom({ - key, - default: { from: undefined, to: undefined } -}); +const createDateRangeAtom = (key: string | any) => + atom({ + key, + default: { from: undefined, to: undefined } + }); export const dataDailyPlanState = createDailyPlanAtom('originalPlanState'); -const getFirstAndLastDateSelector = (key: string | any) => selector({ - key, - get: ({ get }) => { - const itemsData = get(dataDailyPlanState); - if (!itemsData?.length) return { from: null, to: null }; - const sortedData = itemsData?.slice().sort((a, b) => new Date(a.date)?.getTime() - new Date(b?.date).getTime()); - return { from: new Date(sortedData[0]?.date), to: new Date(sortedData[sortedData.length - 1]?.date) }; - } -}); -export const dateRangeDailyPlanState = createDateRangeAtom('dateRangeDailyPlanState') - -const createFilteredDailyPlanDataSelector = (key: string | any, dateRangeState: RecoilState, originalDataState: RecoilState) => selector({ - key, - get: ({ get }) => { - const dateRange = get(dateRangeState); - const data = get(originalDataState); - if (!dateRange || !data.length) return data; - const { from, to } = dateRange; - if (!from && !to) { - return data +const getFirstAndLastDateSelector = (key: string | any) => + selector({ + key, + get: ({ get }) => { + const itemsData = get(dataDailyPlanState); + if (!itemsData?.length) return { from: null, to: null }; + const sortedData = itemsData + ?.slice() + .sort((a, b) => new Date(a.date)?.getTime() - new Date(b?.date).getTime()); + return { from: new Date(sortedData[0]?.date), to: new Date(sortedData[sortedData.length - 1]?.date) }; } - return data.filter((plan) => { - const itemDate = new Date(plan.date); - return isTestDateRange(itemDate, from, to); - }); - }, -}); + }); +export const dateRangeDailyPlanState = createDateRangeAtom('dateRangeDailyPlanState'); + +const createFilteredDailyPlanDataSelector = ( + key: string | any, + dateRangeState: RecoilState, + originalDataState: RecoilState +) => + selector({ + key, + get: ({ get }) => { + const dateRange = get(dateRangeState); + const data = get(originalDataState); + if (!dateRange || !data.length) return data; + const { from, to } = dateRange; + if (!from && !to) { + return data; + } + return data.filter((plan) => { + const itemDate = new Date(plan.date); + return isTestDateRange(itemDate, from, to); + }); + } + }); export const dataDailyPlanAllFilterState = createDailyPlanAtom('dataDailyPlanAllFilterState'); export const dateRangeAllPlanState = createDateRangeAtom('dateRangeAllPlanState'); -export const setCreateFilteredDailyPlanDataSelector = () => selector({ - key: 'dataDailyPlanAllFilter', - get: ({ get }) => { - const dateRange = get(dateRangeAllPlanState); - const data = get(dataDailyPlanAllFilterState); - if (!dateRange || !data.length) return data; - const { from, to } = dateRange; - if (!from && !to) { - return data +export const setCreateFilteredDailyPlanDataSelector = () => + selector({ + key: 'dataDailyPlanAllFilter', + get: ({ get }) => { + const dateRange = get(dateRangeAllPlanState); + const data = get(dataDailyPlanAllFilterState); + if (!dateRange || !data.length) return data; + const { from, to } = dateRange; + if (!from && !to) { + return data; + } + return data.filter((plan) => { + const itemDate = new Date(plan.date); + return isTestDateRange(itemDate, from, to); + }); } - return data.filter((plan) => { - const itemDate = new Date(plan.date); - return isTestDateRange(itemDate, from, to); - }); - }, -}); + }); export const dataDailyPlanCountFilterState = createDailyPlanCountFilterAtom('dataDailyPlanCountFilterState'); export const dateRangePastPlanState = createDateRangeAtom('dateRangePastPlanState'); diff --git a/apps/web/app/stores/employee.ts b/apps/web/app/stores/employee.ts index ecd867c97..7fbeca90b 100644 --- a/apps/web/app/stores/employee.ts +++ b/apps/web/app/stores/employee.ts @@ -14,5 +14,5 @@ export const workingEmployeesEmailState = atom({ export const employeeUpdateState = atom({ key: 'employeeUpdateState', - default: null!, + default: undefined, }) diff --git a/apps/web/components/layout/Meta.tsx b/apps/web/components/layout/Meta.tsx index c61bb0d65..5f3ecccfd 100644 --- a/apps/web/components/layout/Meta.tsx +++ b/apps/web/components/layout/Meta.tsx @@ -1,7 +1,7 @@ import Head from 'next/head'; import { MetaProps } from '../../app/interfaces/hooks'; -const Meta = ({ title, keywords, description }: MetaProps) => { +const Meta = ({ title = 'Gauzy Teams', keywords = '', description = '' }: Partial) => { return ( @@ -11,10 +11,4 @@ const Meta = ({ title, keywords, description }: MetaProps) => { ); }; -Meta.defaultProps = { - title: 'Gauzy Teams', - keywords: '', - description: '' -}; - export default Meta; diff --git a/apps/web/components/pages/kanban/sort-tasks-status-settings.tsx b/apps/web/components/pages/kanban/sort-tasks-status-settings.tsx index d6410efe6..57fc6376b 100644 --- a/apps/web/components/pages/kanban/sort-tasks-status-settings.tsx +++ b/apps/web/components/pages/kanban/sort-tasks-status-settings.tsx @@ -9,14 +9,15 @@ import { SixSquareGridIcon } from 'assets/svg'; import { useTranslations } from 'next-intl'; import React, { useState } from 'react'; import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd'; -import { useRecoilState } from 'recoil'; +import { useSetRecoilState } from 'recoil'; const SortTasksStatusSettings = ({ arr, onClose }: { arr: ITaskStatusItemList[]; onClose: () => void }) => { const [items, setItems] = useState(arr); const [saveLoader, setSaveLoader] = useState(false); const [saveCheck, setSaveCheck] = useState(false); const organizationId = getOrganizationIdCookie(); - const [_, setState] = useRecoilState(taskStatusListState); + const setState = useSetRecoilState(taskStatusListState); + const t = useTranslations(); const { reOrderQueryCall } = useTaskStatus(); const onDragEnd = (result: DropResult) => { diff --git a/apps/web/components/pages/task/details-section/blocks/task-secondary-info.tsx b/apps/web/components/pages/task/details-section/blocks/task-secondary-info.tsx index ffdff3dc9..338fe0edf 100644 --- a/apps/web/components/pages/task/details-section/blocks/task-secondary-info.tsx +++ b/apps/web/components/pages/task/details-section/blocks/task-secondary-info.tsx @@ -1,6 +1,6 @@ -import { useModal, useSyncRef, useTeamTasks } from '@app/hooks'; +import { useModal, useTeamTasks } from '@app/hooks'; import { ITaskVersionCreate, ITeamTask } from '@app/interfaces'; -import { detailedTaskState, taskVersionListState } from '@app/stores'; +import { detailedTaskState } from '@app/stores'; import { PlusIcon } from '@heroicons/react/20/solid'; import { Button, Card, Modal, Tooltip } from 'lib/components'; import { @@ -27,8 +27,6 @@ type StatusType = 'version' | 'epic' | 'status' | 'label' | 'size' | 'priority'; const TaskSecondaryInfo = () => { const task = useRecoilValue(detailedTaskState); - const taskVersion = useRecoilValue(taskVersionListState); - const $taskVersion = useSyncRef(taskVersion); const { updateTask } = useTeamTasks(); const { handleStatusUpdate } = useTeamTasks(); @@ -52,7 +50,7 @@ const TaskSecondaryInfo = () => { (version: ITaskVersionCreate) => { handleStatusUpdate(version.value || version.name, 'version', task?.taskStatusId, task); }, - [$taskVersion, task, handleStatusUpdate] + [task, handleStatusUpdate] ); const onTaskSelect = useCallback( diff --git a/apps/web/components/shared/invite/invite-modal.tsx b/apps/web/components/shared/invite/invite-modal.tsx index 21dc0c7b6..ec74bd0a7 100644 --- a/apps/web/components/shared/invite/invite-modal.tsx +++ b/apps/web/components/shared/invite/invite-modal.tsx @@ -54,7 +54,7 @@ const InviteModal = ({ isOpen, Fragment, closeModal }: IInviteProps) => { } inviteUser(formData.email, formData.name) - .then((data) => { + .then(() => { setFormData(initalValues); closeModal(); toast({ diff --git a/apps/web/components/ui/inputs/input.tsx b/apps/web/components/ui/inputs/input.tsx index b7428d03e..803496863 100644 --- a/apps/web/components/ui/inputs/input.tsx +++ b/apps/web/components/ui/inputs/input.tsx @@ -3,7 +3,7 @@ import { IInputProps } from '@app/interfaces/hooks'; const Input = ({ label, name, - type, + type = 'text', placeholder, required, onChange, @@ -40,8 +40,4 @@ const Input = ({ ); }; -Input.defaultProps = { - type: 'text' -}; - export default Input; diff --git a/apps/web/lib/components/custom-select/multi-select.tsx b/apps/web/lib/components/custom-select/multi-select.tsx index 6b87b8084..a88cb2e65 100644 --- a/apps/web/lib/components/custom-select/multi-select.tsx +++ b/apps/web/lib/components/custom-select/multi-select.tsx @@ -71,7 +71,7 @@ export function MultiSelect({ if (triggerRef.current) { setPopoverWidth(triggerRef.current.offsetWidth); } - }, [triggerRef.current]); + }, []); return (
diff --git a/apps/web/lib/components/inputs/auth-code-input.tsx b/apps/web/lib/components/inputs/auth-code-input.tsx index 7a8a2b4e2..1df14a9a2 100644 --- a/apps/web/lib/components/inputs/auth-code-input.tsx +++ b/apps/web/lib/components/inputs/auth-code-input.tsx @@ -4,6 +4,7 @@ import { clsxm } from '@app/utils'; import React, { MutableRefObject, forwardRef, useState, useEffect, useImperativeHandle, useRef } from 'react'; import { InputField } from './input'; import { useTranslations } from 'next-intl'; +import { useCallbackRef } from '@app/hooks'; const allowedCharactersValues = ['alpha', 'numeric', 'alphanumeric'] as const; @@ -95,6 +96,8 @@ export const AuthCodeInputField = forwardRef( } const [canSubmit, setCanSubmit] = useState(false); const reference = useRef([]); + const $submitCode = useCallbackRef(submitCode); + const inputsRef = inputReference || reference; const inputProps = propsMap[allowedCharacters]; const validDefaultValue = @@ -126,15 +129,8 @@ export const AuthCodeInputField = forwardRef( }, [autoFocus, inputsRef]); useEffect(() => { - if (autoComplete && autoComplete.length > 0) { - handleAutoComplete(autoComplete); - setCanSubmit(true); - } - }, [autoComplete, canSubmit]); - - useEffect(() => { - canSubmit && submitCode && submitCode(); - }, []); + canSubmit && $submitCode.current?.(); + }, [canSubmit, $submitCode]); const sendResult = () => { const res = inputsRef.current.map((input) => input.value).join(''); @@ -225,6 +221,14 @@ export const AuthCodeInputField = forwardRef( sendResult(); }; + useEffect(() => { + if (autoComplete && autoComplete.length > 0) { + handleAutoComplete(autoComplete); + setCanSubmit(true); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [autoComplete, canSubmit]); + const hintColor = { success: '#4BB543', error: '#FF9494', diff --git a/apps/web/lib/components/lazy-render.tsx b/apps/web/lib/components/lazy-render.tsx index e11e30427..2261578c0 100644 --- a/apps/web/lib/components/lazy-render.tsx +++ b/apps/web/lib/components/lazy-render.tsx @@ -53,7 +53,7 @@ export function LazyRender({ items, children, itemsPerPage = 1 return () => { window.cancelIdleCallback(cancelableIdlCallback); }; - }, [page, items, itemsRef]); + }, [page, items, itemsRef, itemsPerPage]); return ( <> diff --git a/apps/web/lib/components/time-picker/index.tsx b/apps/web/lib/components/time-picker/index.tsx index 210c1281d..17daf3663 100644 --- a/apps/web/lib/components/time-picker/index.tsx +++ b/apps/web/lib/components/time-picker/index.tsx @@ -31,7 +31,7 @@ export function TimePicker({ onChange, defaultValue }: IPopoverTimePicker) { const handleTimeChange = (newTime: any) => { setTime(newTime); - onChange!(newTime) + onChange && onChange(newTime); }; return ( diff --git a/apps/web/lib/features/daily-plan/daily-plan-compare-estimate-modal.tsx b/apps/web/lib/features/daily-plan/daily-plan-compare-estimate-modal.tsx index 7d4f56c7c..e762df8cf 100644 --- a/apps/web/lib/features/daily-plan/daily-plan-compare-estimate-modal.tsx +++ b/apps/web/lib/features/daily-plan/daily-plan-compare-estimate-modal.tsx @@ -38,7 +38,7 @@ export function DailyPlanCompareEstimatedModal({ const hour = dh.toString()?.padStart(2, '0'); const minute = dm.toString()?.padStart(2, '0'); const [times, setTimes] = useState({ - hours: (workTimePlanned! / 3600).toString(), + hours: workTimePlanned ? (workTimePlanned / 3600).toString() : '--', meridiem: 'PM', minute: '--' }); diff --git a/apps/web/lib/features/integrations/calendar/confirm-change-status.tsx b/apps/web/lib/features/integrations/calendar/confirm-change-status.tsx index 4f7b6bbc1..2fa91a4ce 100644 --- a/apps/web/lib/features/integrations/calendar/confirm-change-status.tsx +++ b/apps/web/lib/features/integrations/calendar/confirm-change-status.tsx @@ -24,30 +24,37 @@ export function ConfirmStatusChange({ closeModal, isOpen, newStatus, oldStatus } const oldStatusClass = getStatusClasses(oldStatus); return ( - -
- Time entry will be changed from - + <> + { + closeModal ? ( + +
+ Time entry will be changed from + - - -
-
+ + +
+
+ ) + : + <> + } + ) } - const StatusTransition = ({ previousStatus, currentStatus, currentStatusClass, previousStatusClass }: { previousStatus: string; currentStatus: string; currentStatusClass: string; previousStatusClass: string }) => (
{previousStatus} diff --git a/apps/web/lib/features/integrations/calendar/setup-full-calendar.tsx b/apps/web/lib/features/integrations/calendar/setup-full-calendar.tsx index 53029d319..d5ff98662 100644 --- a/apps/web/lib/features/integrations/calendar/setup-full-calendar.tsx +++ b/apps/web/lib/features/integrations/calendar/setup-full-calendar.tsx @@ -191,7 +191,7 @@ export const CardItemsMember = ({ imageUrl, name, time }: { imageUrl?: string, n return (
- +
{name}
@@ -208,7 +208,7 @@ export const CardItemsProjects = ({ logo, title, totalHours }: { logo?: string, return (
- logos + logos
{title} {totalHours} diff --git a/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx b/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx index e6c533f9d..f18ae4c5e 100644 --- a/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx +++ b/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx @@ -417,6 +417,7 @@ const TaskDetails = ({ description, name }: { description: string; name: string {name} +
{description}
); }; diff --git a/apps/web/lib/features/manual-time/add-manual-time-modal.tsx b/apps/web/lib/features/manual-time/add-manual-time-modal.tsx index faf7c9506..490d14ce3 100644 --- a/apps/web/lib/features/manual-time/add-manual-time-modal.tsx +++ b/apps/web/lib/features/manual-time/add-manual-time-modal.tsx @@ -29,8 +29,8 @@ import { Item, ManageOrMemberComponent, getNestedValue } from './manage-member-c */ interface IAddManualTimeModalProps { isOpen: boolean; - params: "AddManuelTime" | "AddTime"; - timeSheetStatus?: "ManagerTimesheet" | "TeamMemberTimesheet", + params: 'AddManuelTime' | 'AddTime'; + timeSheetStatus?: 'ManagerTimesheet' | 'TeamMemberTimesheet'; closeModal: () => void; } @@ -115,12 +115,13 @@ export function AddManualTimeModal(props: IAddManualTimeModalProps) { const timeString = [ hours > 0 ? `${String(hours).padStart(2, '0')}h` : '0h', minutes > 0 ? `${String(minutes).padStart(2, '0')}m` : '' - ].filter(Boolean).join(' '); + ] + .filter(Boolean) + .join(' '); setTimeDifference(timeString); }, [endTime, startTime]); - useEffect(() => { calculateTimeDifference(); }, [calculateTimeDifference, endTime, startTime]); @@ -142,16 +143,15 @@ export function AddManualTimeModal(props: IAddManualTimeModalProps) { } }, [addManualTimeLoading, closeModal, timeLog]); - const memberItemsLists = { - 'Project': activeTeam?.projects, - 'Employee': activeTeam?.members, - 'Task': tasks, + Project: activeTeam?.projects, + Employee: activeTeam?.members, + Task: tasks }; const selectedValues = { - 'Teams': null, - 'Members': null, - "Task": null + Teams: null, + Members: null, + Task: null }; const fields = [ { @@ -162,15 +162,18 @@ export function AddManualTimeModal(props: IAddManualTimeModalProps) { displayKey: 'name', element: 'Project' }, - ...(timeSheetStatus === 'ManagerTimesheet' ? - [{ - label: t('manualTime.EMPLOYEE'), - placeholder: 'Select an employee', - isRequired: true, - valueKey: 'id', - displayKey: 'employee.fullName', - element: 'Employee' - }] : []), + ...(timeSheetStatus === 'ManagerTimesheet' + ? [ + { + label: t('manualTime.EMPLOYEE'), + placeholder: 'Select an employee', + isRequired: true, + valueKey: 'id', + displayKey: 'employee.fullName', + element: 'Employee' + } + ] + : []), { label: t('manualTime.TASK'), placeholder: 'Select a Task', @@ -181,9 +184,6 @@ export function AddManualTimeModal(props: IAddManualTimeModalProps) { } ]; - - - const handleSelectedValuesChange = (values: { [key: string]: Item | null }) => { console.log(values); }; @@ -196,29 +196,33 @@ export function AddManualTimeModal(props: IAddManualTimeModalProps) {
} @@ -249,7 +253,8 @@ export function AddManualTimeModal(props: IAddManualTimeModalProps) {
- +
- +
{timeDifference}
+ {/*
+ + { + activeTeam ? + setTeam(team)} + itemId={(team) => (team ? team.id : '')} + itemToString={(team) => (team ? team.name : '')} + triggerClassName="border-gray-300 dark:border-slate-600" + /> + : + <> + } +
*/} + + {params === 'AddManuelTime' ? ( + <> + getNestedValue(item, displayKey) || ''} + itemToValue={(item, valueKey) => getNestedValue(item, valueKey) || ''} + /> +
+ +