Skip to content

Commit

Permalink
Merge pull request #2510 from ever-co/stage
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
evereq authored May 9, 2024
2 parents aeeabfa + b3711a0 commit bb0a904
Show file tree
Hide file tree
Showing 49 changed files with 714 additions and 7,830 deletions.
5 changes: 3 additions & 2 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,9 @@
"dailyplan",
"tomorow",
"comparization",
"plan"
"plan",
"setwork",
"Clik"
],
"useGitignore": true,
"ignorePaths": [
Expand Down Expand Up @@ -377,7 +379,6 @@
"Chatwoot",
"CHATWOOT",
"apps/web/messages/*.json",
"apps/web/public/locales/**",
"apps/web/lib/i18n/*.ts",
"apps/web/lib/settings/timezones.js",
"apps/mobile/app/screens/DemoShowroomScreen/demos/**",
Expand Down
5 changes: 3 additions & 2 deletions apps/web/app/[locale]/profile/[memberId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ const Profile = React.memo(function ProfilePage({ params }: { params: { memberId
}, [profile.member]);

React.useEffect(() => {
getEmployeeDayPlans(params.memberId);
}, [getEmployeeDayPlans, params.memberId]);
console.log(profile.member?.employeeId);
getEmployeeDayPlans(profile.member?.employeeId ?? '');
}, [getEmployeeDayPlans, profile.member?.employeeId]);

// Example usage

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

export async function PUT(req: Request, { params }: INextParams) {
const res = new NextResponse();

const { planId } = params;
if (!planId) {
return;
}

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

const body = (await req.json()) as unknown as { employeeId: IEmployee['id']; taskId: ITeamTask['id'] };

const response = await addTaskToDailyPlanRequest({
bearer_token: access_token,
data: body,
organizationId,
planId,
tenantId
});

return $res(response.data);
}
4 changes: 2 additions & 2 deletions apps/web/app/hooks/features/useAuthTeamTasks.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { IUser } from '@app/interfaces';
import { dailyPlanListState, tasksByTeamState } from '@app/stores';
import { profileDailyPlanListState, 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 plans = useRecoilValue(profileDailyPlanListState);

const { activeTeam } = useOrganizationTeams();
const currentMember = activeTeam?.members?.find((member) => member.employee?.userId === user?.id);
Expand Down
45 changes: 35 additions & 10 deletions apps/web/app/hooks/features/useDailyPlan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@
import { useRecoilState } from 'recoil';
import { useCallback, useEffect } from 'react';
import { useQuery } from '../useQuery';
import { dailyPlanFetchingState, dailyPlanListState, taskPlans, userState } from '@app/stores';
import {
dailyPlanFetchingState,
dailyPlanListState,
profileDailyPlanListState,
taskPlans,
userState
} from '@app/stores';
import {
addTaskToPlanAPI,
createDailyPlanAPI,
getAllDayPlansAPI,
getDayPlansByEmployeeAPI,
getPlansByTaskAPI,
updateDailyPlanAPI
} from '@app/services/client/api';
import { ICreateDailyPlan } from '@app/interfaces';
import { ICreateDailyPlan, IDailyPlan, IEmployee, ITeamTask } from '@app/interfaces';
import { useFirstLoad } from '../useFirstLoad';

export function useDailyPlan() {
Expand All @@ -22,8 +29,10 @@ export function useDailyPlan() {
const { loading: createDailyPlanLoading, queryCall: createQueryCall } = useQuery(createDailyPlanAPI);
const { loading: updateDailyPlanLoading, queryCall: updateQueryCall } = useQuery(updateDailyPlanAPI);
const { loading: getPlansByTaskLoading, queryCall: getPlansByTaskQueryCall } = useQuery(getPlansByTaskAPI);
const { loading: addTaskToPlanLoading, queryCall: addTaskToPlanQueryCall } = useQuery(addTaskToPlanAPI);

const [dailyPlan, setDailyPlan] = useRecoilState(dailyPlanListState);
const [profileDailyPlans, setProfileDailyPlans] = useRecoilState(profileDailyPlanListState);
const [taskPlanList, setTaskPlans] = useRecoilState(taskPlans);
const [dailyPlanFetching, setDailyPlanFetching] = useRecoilState(dailyPlanFetchingState);
const { firstLoadData: firstLoadDailyPlanData, firstLoad } = useFirstLoad();
Expand All @@ -46,13 +55,11 @@ export function useDailyPlan() {
const getEmployeeDayPlans = useCallback(
(employeeId: string) => {
queryCall(employeeId).then((response) => {
if (response.data?.items?.length) {
const { items, total } = response.data;
setDailyPlan({ items, total });
}
const { items, total } = response.data;
setProfileDailyPlans({ items, total });
});
},
[queryCall, setDailyPlan]
[queryCall, setProfileDailyPlans]
);

const getPlansByTask = useCallback(
Expand All @@ -68,14 +75,18 @@ export function useDailyPlan() {
async (data: ICreateDailyPlan) => {
if (user?.tenantId) {
const res = await createQueryCall(data, user?.tenantId || '');
setProfileDailyPlans({
total: profileDailyPlans.total + 1,
items: [...profileDailyPlans.items, res.data]
});
return res;
}
},
[createQueryCall, user]
[createQueryCall, profileDailyPlans.items, profileDailyPlans.total, setProfileDailyPlans, user?.tenantId]
);

const updateDailyPlan = useCallback(
async (data: Partial<ICreateDailyPlan>, planId: string) => {
async (data: Partial<ICreateDailyPlan>, planId: IDailyPlan['id']) => {
const updated = dailyPlan.items.filter((plan) => plan.id != planId);
const res = await updateQueryCall(data, planId);
setDailyPlan({ total: dailyPlan.total, items: [...updated, res.data] });
Expand All @@ -84,8 +95,19 @@ export function useDailyPlan() {
[dailyPlan.items, dailyPlan.total, setDailyPlan, updateQueryCall]
);

const addTaskToPlan = useCallback(
async (data: { employeeId: IEmployee['id']; taskId: ITeamTask['id'] }, planId: IDailyPlan['id']) => {
const updated = profileDailyPlans.items.filter((plan) => plan.id != planId);
const res = await addTaskToPlanQueryCall(data, planId);
setProfileDailyPlans({ total: profileDailyPlans.total, items: [...updated, res.data] });
return res;
},
[addTaskToPlanQueryCall, profileDailyPlans.items, profileDailyPlans.total, setProfileDailyPlans]
);

return {
dailyPlan,
profileDailyPlans,
setDailyPlan,
dailyPlanFetching,

Expand All @@ -106,6 +128,9 @@ export function useDailyPlan() {
createDailyPlanLoading,

updateDailyPlan,
updateDailyPlanLoading
updateDailyPlanLoading,

addTaskToPlan,
addTaskToPlanLoading
};
}
6 changes: 2 additions & 4 deletions apps/web/app/hooks/useLanguage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
import { currentLanguageState } from '@app/stores';
import { useRouter } from 'next/navigation';
import { useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useRecoilState } from 'recoil';

export function useLanguage() {
const { i18n } = useTranslation();
const router = useRouter();
const [currentLanguage, setCurrentLanguage] = useRecoilState(currentLanguageState);

Expand All @@ -30,7 +28,7 @@ export function useLanguage() {
}
// router.refresh();
},
[router, i18n]
[router]
);
return { currentLanguage, changeLanguage, i18n };
return { currentLanguage, changeLanguage,};
}
17 changes: 15 additions & 2 deletions apps/web/app/services/client/api/daily-plan.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import qs from 'qs';
import { get, post, put } from '../axios';
import { ICreateDailyPlan, IDailyPlan, PaginationResponse } from '@app/interfaces';
import { ICreateDailyPlan, IDailyPlan, IEmployee, ITeamTask, PaginationResponse } from '@app/interfaces';
import { getOrganizationIdCookie, getTenantIdCookie } from '@app/helpers';

export function getAllDayPlansAPI() {
Expand Down Expand Up @@ -56,11 +56,24 @@ export function getPlansByTaskAPI(taskId?: string) {
}

export function createDailyPlanAPI(data: ICreateDailyPlan, tenantId?: string) {
return post<ICreateDailyPlan>('/daily-plan', data, {
return post<IDailyPlan>('/daily-plan', data, {
tenantId
});
}

export function updateDailyPlanAPI(data: Partial<ICreateDailyPlan>, planId: string) {
return put<IDailyPlan>(`/daily-plan/${planId}`, data, {});
}

export function addTaskToPlanAPI(data: { employeeId: IEmployee['id']; taskId: ITeamTask['id'] }, planId: string) {
const organizationId = getOrganizationIdCookie();
const tenantId = getTenantIdCookie();

const obj = {
'where[organizationId]': organizationId
} as Record<string, string>;

const query = qs.stringify(obj);

return put<IDailyPlan>(`/daily-plan/add-task/${planId}?${query}`, data, { tenantId });
}
29 changes: 29 additions & 0 deletions apps/web/app/services/server/requests/daily-plan.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import qs from 'qs';
import { ICreateDailyPlan, IDailyPlan } from '@app/interfaces/IDailyPlan';
import { serverFetch } from '../fetch';
import { IEmployee, ITeamTask } from '@app/interfaces';

export function getAllDayPlans({
organizationId,
Expand Down Expand Up @@ -124,3 +125,31 @@ export function updatePlanRequest({
tenantId
});
}

export function addTaskToDailyPlanRequest({
planId,
data,
bearer_token,
tenantId,
organizationId
}: {
planId: string;
data: { employeeId: IEmployee['id']; taskId: ITeamTask['id'] };
bearer_token?: string;
tenantId: any;
organizationId: string;
}) {
const obj = {
'where[organizationId]': organizationId
} as Record<string, string>;

const query = qs.stringify(obj);

return serverFetch<IDailyPlan>({
method: 'PUT',
path: `/daily-plan/add-task/${planId}?${query}`,
body: data,
bearer_token,
tenantId
});
}
5 changes: 5 additions & 0 deletions apps/web/app/stores/daily-plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ export const dailyPlanListState = atom<PaginationResponse<IDailyPlan>>({
default: { items: [], total: 0 }
});

export const profileDailyPlanListState = atom<PaginationResponse<IDailyPlan>>({
key: 'profileDailyPlanListState',
default: { items: [], total: 0 }
});

export const taskPlans = atom<IDailyPlan[]>({
key: 'taskPlansList',
default: []
Expand Down
17 changes: 16 additions & 1 deletion apps/web/components/pages/kanban/menu-kanban-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { useTeamMemberCard } from '@app/hooks';
import { activeTeamTaskId } from '@app/stores';
import { Popover, PopoverContent, PopoverTrigger } from '@components/ui/popover';
import { ThreeCircleOutlineVerticalIcon } from 'assets/svg';
import { SpinnerLoader } from 'lib/components';
import { HorizontalSeparator, SpinnerLoader } from 'lib/components';
import { PlanTask } from 'lib/features/task/task-card';
import { useTranslations } from 'next-intl';
import { useState } from 'react';
import { useSetRecoilState } from 'recoil';
Expand Down Expand Up @@ -80,6 +81,20 @@ export default function MenuKanbanCard({ member, item }: { item: any; member: an
);
})}
</ul>
<HorizontalSeparator />
<div className="mt-3 text-xs p-2">
<ul className="list-none">
<li className="mb-2">
<PlanTask planMode="today" taskId={item.id} chooseMember={true} />
</li>
<li className="mb-2">
<PlanTask planMode="tomorow" taskId={item.id} chooseMember={true} />
</li>
<li className="mb-2">
<PlanTask planMode="custom" taskId={item.id} chooseMember={true} />
</li>
</ul>
</div>
</PopoverContent>
</Popover>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,46 @@ export function TaskPlans() {
getPlansByTask(task?.id);
}, [getPlansByTask, task?.id]);

const groupedByEmployee: { [key: string]: any[] } = {};

if (taskPlanList?.length > 0)
for (const currentItem of taskPlanList) {
const employeeName = currentItem?.employee?.fullName;

if (typeof employeeName === 'string') {
if (!groupedByEmployee[employeeName]) {
groupedByEmployee[employeeName] = [];
}
groupedByEmployee[employeeName].push(currentItem);
}
}

return (
<section className="flex flex-col gap-4 px-[0.9375rem] pb-[0.9375rem]">
<div className="flex justify-between h-[1.25rem] items-center">
<div className="not-italic font-medium text-sm leading-[140%] tracking-[-0.02em] text-[#282048] dark:text-white">
Daily Plans
</div>
</div>

<div className="flex flex-col gap-4 pb-[0.9375rem]">
{taskPlanList?.length > 0 ? (
taskPlanList?.map((plan) => (
<TaskRow
key={plan.id}
labelIconPath="/assets/svg/profile.svg"
labelTitle={plan.employee?.fullName}
>
<span className="text-xs font-semibold">{formatDayPlanDate(plan.date)}</span>
</TaskRow>
Object.entries(groupedByEmployee).map(([employeeName, employeePlans]) => (
<div key={employeeName}>
<TaskRow
wrapperClassName="items-start"
labelIconPath="/assets/svg/profile.svg"
labelTitle={employeeName}
>
<div className="flex flex-col gap-3 pb-[0.9375rem]">
{employeePlans?.map((plan) => (
<span key={plan.id} className="text-xs font-semibold text-slate-600">
{formatDayPlanDate(plan.date)}
</span>
))}
</div>
</TaskRow>
</div>
))
) : (
<div className="text-center text-xs font-normal">Task not planned</div>
Expand Down
Loading

0 comments on commit bb0a904

Please sign in to comment.