Skip to content

Commit

Permalink
Merge pull request #2483 from ever-co/develop
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
evereq authored May 3, 2024
2 parents 61c4b9a + d102cb0 commit f6702a7
Show file tree
Hide file tree
Showing 87 changed files with 1,334 additions and 214 deletions.
6 changes: 5 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,11 @@
"Northflank",
"prebuild",
"dataToDisplay",
"GlobalSkeleton"
"GlobalSkeleton",
"dailyplan",
"tomorow",
"comparization",
"plan"
],
"useGitignore": true,
"ignorePaths": [
Expand Down
14 changes: 9 additions & 5 deletions apps/web/app/[locale]/auth/passcode/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ function PasscodeScreen({ form, className }: { form: TAuthenticationPasscode } &
const t = useTranslations();
const inputsRef = useRef<Array<HTMLInputElement>>([]);

const formatTime = (seconds: number) => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`;
};

const [timer, setTimer] = useState(60);
const [disabled, setDisabled] = useState(true);

Expand Down Expand Up @@ -229,14 +235,12 @@ function PasscodeScreen({ form, className }: { form: TAuthenticationPasscode } &
>
{!disabled ? (
<span className="text-primary dark:text-primary-light">
{'Re'}
{t('pages.auth.SEND_CODE')}
{t('pages.auth.RESEND_CODE')}
</span>
) : (
<span className=" dark:text-primary-light">
{'Re'}
{t('pages.auth.SEND_CODE')} {' in 00:'}
{timer}
{t('pages.auth.RESEND_CODE_IN')} {' '}
{formatTime(timer)}
</span>
)}
</button>
Expand Down
7 changes: 6 additions & 1 deletion apps/web/app/[locale]/profile/[memberId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/* eslint-disable no-mixed-spaces-and-tabs */
import { imgTitle } from '@app/helpers';
import { useAuthenticateUser, useOrganizationTeams, useTimer, useUserProfilePage } from '@app/hooks';
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';
Expand All @@ -29,6 +29,7 @@ const Profile = React.memo(function ProfilePage({ params }: { params: { memberId
const profile = useUserProfilePage();
const { user } = useAuthenticateUser();
const { isTrackingEnabled, activeTeam, activeTeamManagers } = useOrganizationTeams();
const { getEmployeeDayPlans } = useDailyPlan();
const fullWidth = useRecoilValue(fullWidthState);
const [activityFilter, setActivityFilter] = useState<FilterTab>('Tasks');
const setActivityTypeFilter = useSetRecoilState(activityTypeState);
Expand Down Expand Up @@ -68,6 +69,10 @@ const Profile = React.memo(function ProfilePage({ params }: { params: { memberId
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [profile.member]);

React.useEffect(() => {
getEmployeeDayPlans(params.memberId);
}, [getEmployeeDayPlans, params.memberId]);

// Example usage

return (
Expand Down
24 changes: 24 additions & 0 deletions apps/web/app/api/daily-plan/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { NextResponse } from 'next/server';
import { authenticatedGuard } from '@app/services/server/guards/authenticated-guard-app';
import { getDayPlansByEmployee } from '@app/services/server/requests';
import { INextParams } from '@app/interfaces';

export async function GET(req: Request, { params }: INextParams) {
const res = new NextResponse();
const { id } = params;
if (!id) {
return;
}

const { $res, user, tenantId, organizationId, access_token } = await authenticatedGuard(req, res);
if (!user) return $res('Unauthorized');

const response = await getDayPlansByEmployee({
bearer_token: access_token,
employeeId: id,
organizationId,
tenantId
});

return $res(response.data);
}
32 changes: 32 additions & 0 deletions apps/web/app/api/daily-plan/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ICreateDailyPlan } from '@app/interfaces';
import { authenticatedGuard } from '@app/services/server/guards/authenticated-guard-app';
import { createPlanRequest, getAllDayPlans } from '@app/services/server/requests';
import { NextResponse } from 'next/server';

export async function POST(req: Request) {
const res = new NextResponse();
const { $res, user, access_token: bearer_token, tenantId } = await authenticatedGuard(req, res);

if (!user) return $res('Unauthorized');

const body = (await req.json()) as unknown as ICreateDailyPlan;

const response = await createPlanRequest({ data: body, bearer_token, tenantId });

return $res(response.data);
}

export async function GET(req: Request) {
const res = new NextResponse();

const { $res, user, tenantId, organizationId, access_token } = await authenticatedGuard(req, res);
if (!user) return $res('Unauthorized');

const response = await getAllDayPlans({
bearer_token: access_token,
organizationId,
tenantId
});

return $res(response.data);
}
15 changes: 15 additions & 0 deletions apps/web/app/helpers/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,18 @@ export const calculateRemainingDays = (startDate: string, endDate: string): numb

return moment(endDate).diff(startDate, 'days');
};

export const tomorrowDate = moment().add(1, 'days').toDate();

export const formatDayPlanDate = (dateString: string | Date, format?: string) => {
if (dateString.toString().length > 10) {
dateString = dateString.toString().split('T')[0];
}
const date = moment(dateString, 'YYYY-MM-DD');

if (date.isSame(moment(), 'day')) return 'Today';
if (date.isSame(moment().add(1, 'day'), 'day')) return 'Tomorrow';
if (date.isSame(moment().subtract(1, 'day'), 'day')) return 'Yesterday';
if (format === 'DD MMM YYYY') return formatDateString(dateString.toString());
return date.format('dddd, MMMM DD, YYYY');
};
1 change: 1 addition & 0 deletions apps/web/app/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from './regex';
export * from './validations';
export * from './colors';
export * from './strings';
export * from './plan-day-badge';
25 changes: 25 additions & 0 deletions apps/web/app/helpers/plan-day-badge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { IDailyPlan, ITeamTask } from '@app/interfaces';
import { formatDayPlanDate } from './date';

export const planBadgeContent = (plans: IDailyPlan[], taskId: ITeamTask['id']): string | null => {
// Search a plan that contains a given task
const plan = plans.find((plan) => plan.tasks?.some((task) => task.id === taskId));

// If at least one plan have this task
if (plan) {
// Check if the task appears in other plans
const otherPlansWithTask = plans.filter(
(pl) => pl.id !== plan.id && pl.tasks?.some((tsk) => tsk.id === taskId)
);

// If the task exists in other plans, the its planned many days
if (otherPlansWithTask.length > 0) {
return 'Planned';
} else {
return `Planned ${formatDayPlanDate(plan.date, 'DD MMM YYYY')}`;
}
// The task does not exist in any plan
} else {
return null;
}
};
2 changes: 1 addition & 1 deletion apps/web/app/helpers/validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const authFormValidate = (keys: (keyof IRegisterDataAPI)[], values: IRegi
}
break;
case 'recaptcha':
if (RECAPTCHA_SITE_KEY) {
if (RECAPTCHA_SITE_KEY.value) {
if (!values['recaptcha'] || values['recaptcha'].trim().length < 2) {
err['recaptcha'] = 'Please check the ReCaptcha checkbox before continue';
}
Expand Down
19 changes: 6 additions & 13 deletions apps/web/app/hooks/auth/useAuthenticationPasscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ type AuthCodeRef = {
export function useAuthenticationPasscode() {
const pathname = usePathname();
const query = useSearchParams();
const queryTeamId = useMemo(() => {
return query?.get('teamId');
}, [query]);

const queryTeamId = query?.get('teamId');

const queryEmail = useMemo(() => {
const emailQuery = query?.get('email') || '';
Expand Down Expand Up @@ -110,6 +109,7 @@ export function useAuthenticationPasscode() {

signInToWorkspaceRequest({
email: email,
code: code,
token: currentWorkspace?.token as string,
selectedTeam: queryTeamId as string
});
Expand Down Expand Up @@ -156,16 +156,8 @@ export function useAuthenticationPasscode() {
[queryCall]
);

const signInToWorkspaceRequest = ({
email,
token,
selectedTeam
}: {
email: string;
token: string;
selectedTeam: string;
}) => {
signInWorkspaceQueryCall(email, token, selectedTeam)
const signInToWorkspaceRequest = (params: { email: string; token: string; selectedTeam: string; code: string }) => {
signInWorkspaceQueryCall(params)
.then(() => {
setAuthenticated(true);
router.push('/');
Expand Down Expand Up @@ -227,6 +219,7 @@ export function useAuthenticationPasscode() {

signInToWorkspaceRequest({
email: formValues.email,
code: formValues.code,
token,
selectedTeam
});
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/hooks/auth/useAuthenticationPassword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export function useAuthenticationPassword() {
token: string;
selectedTeam: string;
}) => {
signInWorkspaceQueryCall(email, token, selectedTeam)
signInWorkspaceQueryCall({ email, token, selectedTeam, code: '' })
.then(() => {
setAuthenticated(true);
router.push('/');
Expand Down
1 change: 1 addition & 0 deletions apps/web/app/hooks/auth/useAuthenticationTeam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export function useAuthenticationTeam() {
const { errors, valid } = authFormValidate(validationFields, formValues);

if (!valid) {
console.log({ errors });
setErrors(errors as any);
return;
}
Expand Down
11 changes: 9 additions & 2 deletions apps/web/app/hooks/features/useAuthTeamTasks.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { IUser } from '@app/interfaces';
import { tasksByTeamState } from '@app/stores';
import { dailyPlanListState, tasksByTeamState } from '@app/stores';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { useOrganizationTeams } from './useOrganizationTeams';

export function useAuthTeamTasks(user: IUser | undefined) {
const tasks = useRecoilValue(tasksByTeamState);
const plans = useRecoilValue(dailyPlanListState);

const { activeTeam } = useOrganizationTeams();
const currentMember = activeTeam?.members?.find((member) => member.employee?.userId === user?.id);
Expand All @@ -24,6 +25,11 @@ export function useAuthTeamTasks(user: IUser | undefined) {
});
}, [tasks, user]);

const dailyplan = useMemo(() => {
if (!user) return [];
return plans.items;
}, [plans, user]);

const totalTodayTasks = useMemo(
() =>
currentMember?.totalTodayTasks && currentMember?.totalTodayTasks.length
Expand All @@ -41,6 +47,7 @@ export function useAuthTeamTasks(user: IUser | undefined) {
return {
assignedTasks,
unassignedTasks,
workedTasks
workedTasks,
dailyplan
};
}
74 changes: 74 additions & 0 deletions apps/web/app/hooks/features/useDailyPlan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
'use client';

import { useRecoilState } from 'recoil';
import { useCallback, useEffect } from 'react';
import { useQuery } from '../useQuery';
import { dailyPlanFetchingState, dailyPlanListState, userState } from '@app/stores';
import { createDailyPlanAPI, getAllDayPlansAPI, getDayPlansByEmployeeAPI } from '@app/services/client/api';
import { ICreateDailyPlan } from '@app/interfaces';
import { useFirstLoad } from '../useFirstLoad';

export function useDailyPlan() {
const [user] = useRecoilState(userState);

const { loading, queryCall } = useQuery(getDayPlansByEmployeeAPI);
const { loading: getAllDayPlansLoading, queryCall: getAllQueryCall } = useQuery(getAllDayPlansAPI);
const { loading: createDailyPlanLoading, queryCall: createQueryCall } = useQuery(createDailyPlanAPI);

const [dailyPlan, setDailyPlan] = useRecoilState(dailyPlanListState);
const [dailyPlanFetching, setDailyPlanFetching] = useRecoilState(dailyPlanFetchingState);
const { firstLoadData: firstLoadDailyPlanData, firstLoad } = useFirstLoad();

useEffect(() => {
if (firstLoad) {
setDailyPlanFetching(loading);
}
}, [loading, firstLoad, setDailyPlanFetching]);

const getAllDayPlans = useCallback(() => {
getAllQueryCall().then((response) => {
if (response.data.items.length) {
const { items, total } = response.data;
setDailyPlan({ items, total });
}
});
}, [getAllQueryCall, setDailyPlan]);

const getEmployeeDayPlans = useCallback(
(employeeId: string) => {
queryCall(employeeId).then((response) => {
if (response.data.items.length) {
const { items, total } = response.data;
setDailyPlan({ items, total });
}
});
},
[queryCall, setDailyPlan]
);

const createDailyPlan = useCallback(
async (data: ICreateDailyPlan) => {
if (user?.tenantId) {
const res = await createQueryCall(data, user?.tenantId || '');
return res;
}
},
[createQueryCall, user]
);

return {
dailyPlan,
setDailyPlan,
dailyPlanFetching,
firstLoadDailyPlanData,

getAllDayPlans,
getAllDayPlansLoading,

getEmployeeDayPlans,
loading,

createDailyPlan,
createDailyPlanLoading
};
}
6 changes: 2 additions & 4 deletions apps/web/app/hooks/features/useTaskVersion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ import { useRecoilState, useRecoilValue } from 'recoil';
import { useFirstLoad } from '../useFirstLoad';
import { useQuery } from '../useQuery';
import isEqual from 'lodash/isEqual';
import { useCallbackRef } from '../useCallbackRef';
import { getActiveTeamIdCookie } from '@app/helpers';

export function useTaskVersion(onVersionCreated?: (version: ITaskVersionCreate) => void) {
export function useTaskVersion() {
const [user] = useRecoilState(userState);
const activeTeamId = useRecoilValue(activeTeamIdState);

Expand All @@ -27,7 +26,6 @@ export function useTaskVersion(onVersionCreated?: (version: ITaskVersionCreate)
const { loading: editTaskVersionLoading, queryCall: editQueryCall } = useQuery(editTaskVersionAPI);

const [taskVersion, setTaskVersion] = useRecoilState(taskVersionListState);
const $onVersionCreated = useCallbackRef(onVersionCreated);

const [taskVersionFetching, setTaskVersionFetching] = useRecoilState(taskVersionFetchingState);
const { firstLoadData: firstLoadTaskVersionData, firstLoad } = useFirstLoad();
Expand Down Expand Up @@ -68,7 +66,7 @@ export function useTaskVersion(onVersionCreated?: (version: ITaskVersionCreate)
}
},

[$onVersionCreated, createQueryCall, createTaskVersionLoading, deleteTaskVersionLoading, activeTeamId]
[createQueryCall, createTaskVersionLoading, deleteTaskVersionLoading, activeTeamId]
);

const deleteTaskVersion = useCallback(
Expand Down
Loading

0 comments on commit f6702a7

Please sign in to comment.