expand sub tasks

This commit is contained in:
chamiakJ
2025-07-03 01:31:05 +05:30
parent 3bef18901a
commit ecd4d29a38
435 changed files with 13150 additions and 11087 deletions

View File

@@ -112,7 +112,7 @@ export const adminCenterApiService = {
async updateTeam(
team_id: string,
body: {name: string, teamMembers: IOrganizationUser[]}
body: { name: string; teamMembers: IOrganizationUser[] }
): Promise<IServerResponse<IOrganization>> {
const response = await apiClient.put<IServerResponse<IOrganization>>(
`${rootUrl}/organization/team/${team_id}`,
@@ -152,7 +152,6 @@ export const adminCenterApiService = {
return response.data;
},
// Billing - Configuration
async getCountries(): Promise<IServerResponse<IBillingConfigurationCountry[]>> {
const response = await apiClient.get<IServerResponse<IBillingConfigurationCountry[]>>(
@@ -168,7 +167,9 @@ export const adminCenterApiService = {
return response.data;
},
async updateBillingConfiguration(body: IBillingConfiguration): Promise<IServerResponse<IBillingConfiguration>> {
async updateBillingConfiguration(
body: IBillingConfiguration
): Promise<IServerResponse<IBillingConfiguration>> {
const response = await apiClient.put<IServerResponse<IBillingConfiguration>>(
`${rootUrl}/billing/configuration`,
body
@@ -178,42 +179,58 @@ export const adminCenterApiService = {
// Billing - Current Bill
async getCharges(): Promise<IServerResponse<IBillingChargesResponse>> {
const response = await apiClient.get<IServerResponse<IBillingChargesResponse>>(`${rootUrl}/billing/charges`);
const response = await apiClient.get<IServerResponse<IBillingChargesResponse>>(
`${rootUrl}/billing/charges`
);
return response.data;
},
async getTransactions(): Promise<IServerResponse<IBillingTransaction[]>> {
const response = await apiClient.get<IServerResponse<IBillingTransaction[]>>(`${rootUrl}/billing/transactions`);
const response = await apiClient.get<IServerResponse<IBillingTransaction[]>>(
`${rootUrl}/billing/transactions`
);
return response.data;
},
async getBillingAccountInfo(): Promise<IServerResponse<IBillingAccountInfo>> {
const response = await apiClient.get<IServerResponse<IBillingAccountInfo>>(`${rootUrl}/billing/info`);
const response = await apiClient.get<IServerResponse<IBillingAccountInfo>>(
`${rootUrl}/billing/info`
);
return response.data;
},
async getFreePlanSettings(): Promise<IServerResponse<IFreePlanSettings>> {
const response = await apiClient.get<IServerResponse<IFreePlanSettings>>(`${rootUrl}/billing/free-plan`);
const response = await apiClient.get<IServerResponse<IFreePlanSettings>>(
`${rootUrl}/billing/free-plan`
);
return response.data;
},
async upgradePlan(plan: string): Promise<IServerResponse<IUpgradeSubscriptionPlanResponse>> {
const response = await apiClient.get<IServerResponse<IUpgradeSubscriptionPlanResponse>>(`${rootUrl}/billing/upgrade-plan${toQueryString({plan})}`);
const response = await apiClient.get<IServerResponse<IUpgradeSubscriptionPlanResponse>>(
`${rootUrl}/billing/upgrade-plan${toQueryString({ plan })}`
);
return response.data;
},
async changePlan(plan: string): Promise<IServerResponse<IUpgradeSubscriptionPlanResponse>> {
const response = await apiClient.get<IServerResponse<IUpgradeSubscriptionPlanResponse>>(`${rootUrl}/billing/change-plan${toQueryString({plan})}`);
const response = await apiClient.get<IServerResponse<IUpgradeSubscriptionPlanResponse>>(
`${rootUrl}/billing/change-plan${toQueryString({ plan })}`
);
return response.data;
},
async getPlans(): Promise<IServerResponse<IPricingPlans>> {
const response = await apiClient.get<IServerResponse<IPricingPlans>>(`${rootUrl}/billing/plans`);
const response = await apiClient.get<IServerResponse<IPricingPlans>>(
`${rootUrl}/billing/plans`
);
return response.data;
},
async getStorageInfo(): Promise<IServerResponse<IStorageInfo>> {
const response = await apiClient.get<IServerResponse<IStorageInfo>>(`${rootUrl}/billing/storage`);
const response = await apiClient.get<IServerResponse<IStorageInfo>>(
`${rootUrl}/billing/storage`
);
return response.data;
},
@@ -225,7 +242,7 @@ export const adminCenterApiService = {
async resumeSubscription(): Promise<IServerResponse<any>> {
const response = await apiClient.get<IServerResponse<any>>(`${rootUrl}/billing/resume-plan`);
return response.data;
},
},
async cancelSubscription(): Promise<IServerResponse<any>> {
const response = await apiClient.get<IServerResponse<any>>(`${rootUrl}/billing/cancel-plan`);
@@ -233,26 +250,34 @@ export const adminCenterApiService = {
},
async addMoreSeats(totalSeats: number): Promise<IServerResponse<any>> {
const response = await apiClient.post<IServerResponse<any>>(`${rootUrl}/billing/purchase-more-seats`, {seatCount: totalSeats});
const response = await apiClient.post<IServerResponse<any>>(
`${rootUrl}/billing/purchase-more-seats`,
{ seatCount: totalSeats }
);
return response.data;
},
async redeemCode(code: string): Promise<IServerResponse<IUpgradeSubscriptionPlanResponse>> {
const response = await apiClient.post<IServerResponse<IUpgradeSubscriptionPlanResponse>>(`${rootUrl}/billing/redeem`, {
code,
});
const response = await apiClient.post<IServerResponse<IUpgradeSubscriptionPlanResponse>>(
`${rootUrl}/billing/redeem`,
{
code,
}
);
return response.data;
},
async getAccountStorage(): Promise<IServerResponse<IBillingAccountStorage>> {
const response = await apiClient.get<IServerResponse<IBillingAccountStorage>>(`${rootUrl}/billing/account-storage`);
const response = await apiClient.get<IServerResponse<IBillingAccountStorage>>(
`${rootUrl}/billing/account-storage`
);
return response.data;
},
async switchToFreePlan(teamId: string): Promise<IServerResponse<any>> {
const response = await apiClient.get<IServerResponse<any>>(`${rootUrl}/billing/switch-to-free-plan/${teamId}`);
const response = await apiClient.get<IServerResponse<any>>(
`${rootUrl}/billing/switch-to-free-plan/${teamId}`
);
return response.data;
},
};

View File

@@ -6,7 +6,10 @@ import { IUpgradeSubscriptionPlanResponse } from '@/types/admin-center/admin-cen
const rootUrl = `${API_BASE_URL}/billing`;
export const billingApiService = {
async upgradeToPaidPlan(plan: string, seatCount: number): Promise<IServerResponse<IUpgradeSubscriptionPlanResponse>> {
async upgradeToPaidPlan(
plan: string,
seatCount: number
): Promise<IServerResponse<IUpgradeSubscriptionPlanResponse>> {
const q = toQueryString({ plan, seatCount });
const response = await apiClient.get<IServerResponse<any>>(
`${rootUrl}/upgrade-to-paid-plan${q}`
@@ -14,7 +17,9 @@ export const billingApiService = {
return response.data;
},
async purchaseMoreSeats(seatCount: number): Promise<IServerResponse<IUpgradeSubscriptionPlanResponse>> {
async purchaseMoreSeats(
seatCount: number
): Promise<IServerResponse<IUpgradeSubscriptionPlanResponse>> {
const response = await apiClient.post<IServerResponse<IUpgradeSubscriptionPlanResponse>>(
`${rootUrl}/purchase-more-seats`,
{ seatCount }
@@ -27,9 +32,5 @@ export const billingApiService = {
`${rootUrl}/contact-us${toQueryString({ contactNo })}`
);
return response.data;
}
},
};

View File

@@ -16,16 +16,16 @@ export const refreshCsrfToken = async (): Promise<string | null> => {
try {
const tokenStart = performance.now();
console.log('[CSRF] Starting CSRF token refresh...');
// Make a GET request to the server to get a fresh CSRF token with timeout
const response = await axios.get(`${config.apiUrl}/csrf-token`, {
const response = await axios.get(`${config.apiUrl}/csrf-token`, {
withCredentials: true,
timeout: 10000 // 10 second timeout for CSRF token requests
timeout: 10000, // 10 second timeout for CSRF token requests
});
const tokenEnd = performance.now();
console.log(`[CSRF] CSRF token refresh completed in ${(tokenEnd - tokenStart).toFixed(2)}ms`);
if (response.data && response.data.token) {
csrfToken = response.data.token;
console.log('[CSRF] CSRF token successfully refreshed');
@@ -61,22 +61,22 @@ const apiClient = axios.create({
apiClient.interceptors.request.use(
async config => {
const requestStart = performance.now();
// Ensure we have a CSRF token before making requests
if (!csrfToken) {
const tokenStart = performance.now();
await refreshCsrfToken();
const tokenEnd = performance.now();
}
if (csrfToken) {
config.headers['X-CSRF-Token'] = csrfToken;
} else {
console.warn('No CSRF token available after refresh attempt');
}
const requestEnd = performance.now();
return config;
},
error => Promise.reject(error)
@@ -114,14 +114,17 @@ apiClient.interceptors.response.use(
const errorResponse = error.response;
// Handle CSRF token errors
if (errorResponse?.status === 403 &&
(typeof errorResponse.data === 'object' &&
errorResponse.data !== null &&
'message' in errorResponse.data &&
(errorResponse.data.message === 'invalid csrf token' || errorResponse.data.message === 'Invalid CSRF token') ||
(error as any).code === 'EBADCSRFTOKEN')) {
if (
errorResponse?.status === 403 &&
((typeof errorResponse.data === 'object' &&
errorResponse.data !== null &&
'message' in errorResponse.data &&
(errorResponse.data.message === 'invalid csrf token' ||
errorResponse.data.message === 'Invalid CSRF token')) ||
(error as any).code === 'EBADCSRFTOKEN')
) {
alertService.error('Security Error', 'Invalid security token. Refreshing your session...');
// Try to refresh the CSRF token and retry the request
const newToken = await refreshCsrfToken();
if (newToken && error.config) {

View File

@@ -1,25 +1,37 @@
import { IServerResponse } from "@/types/common.types";
import { IProjectAttachmentsViewModel } from "@/types/tasks/task-attachment-view-model";
import apiClient from "../api-client";
import { API_BASE_URL } from "@/shared/constants";
import { toQueryString } from "@/utils/toQueryString";
import { IServerResponse } from '@/types/common.types';
import { IProjectAttachmentsViewModel } from '@/types/tasks/task-attachment-view-model';
import apiClient from '../api-client';
import { API_BASE_URL } from '@/shared/constants';
import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/attachments`;
export const attachmentsApiService = {
getTaskAttachments: async (taskId: string): Promise<IServerResponse<IProjectAttachmentsViewModel>> => {
const response = await apiClient.get<IServerResponse<IProjectAttachmentsViewModel>>(`${rootUrl}/tasks/${taskId}`);
getTaskAttachments: async (
taskId: string
): Promise<IServerResponse<IProjectAttachmentsViewModel>> => {
const response = await apiClient.get<IServerResponse<IProjectAttachmentsViewModel>>(
`${rootUrl}/tasks/${taskId}`
);
return response.data;
},
getProjectAttachments: async (projectId: string, index: number, size: number): Promise<IServerResponse<IProjectAttachmentsViewModel>> => {
getProjectAttachments: async (
projectId: string,
index: number,
size: number
): Promise<IServerResponse<IProjectAttachmentsViewModel>> => {
const q = toQueryString({ index, size });
const response = await apiClient.get<IServerResponse<IProjectAttachmentsViewModel>>(`${rootUrl}/project/${projectId}${q}`);
const response = await apiClient.get<IServerResponse<IProjectAttachmentsViewModel>>(
`${rootUrl}/project/${projectId}${q}`
);
return response.data;
},
downloadAttachment: async (id: string, filename: string): Promise<IServerResponse<string>> => {
const response = await apiClient.get<IServerResponse<string>>(`${rootUrl}/download?id=${id}&file=${filename}`);
const response = await apiClient.get<IServerResponse<string>>(
`${rootUrl}/download?id=${id}&file=${filename}`
);
return response.data;
},
@@ -27,7 +39,4 @@ export const attachmentsApiService = {
const response = await apiClient.delete<IServerResponse<string>>(`${rootUrl}/tasks/${id}`);
return response.data;
},
};

View File

@@ -20,7 +20,7 @@ const api = createApi({
if (!token) {
token = await refreshCsrfToken();
}
if (token) {
headers.set('X-CSRF-Token', token);
}

View File

@@ -10,7 +10,7 @@ export const projectMembersApiService = {
createProjectMember: async (
body: IProjectMemberViewModel
): Promise<IServerResponse<IProjectMemberViewModel>> => {
const q = toQueryString({current_project_id: body.project_id});
const q = toQueryString({ current_project_id: body.project_id });
const response = await apiClient.post<IServerResponse<IProjectMemberViewModel>>(
`${rootUrl}${q}`,

View File

@@ -34,7 +34,9 @@ export const projectTemplatesApiService = {
return response.data;
},
createCustomTemplate: async (body: { template_id: string }): Promise<IServerResponse<IProjectTemplate>> => {
createCustomTemplate: async (body: {
template_id: string;
}): Promise<IServerResponse<IProjectTemplate>> => {
const response = await apiClient.post(`${rootUrl}/custom-template`, body);
return response.data;
},
@@ -44,15 +46,17 @@ export const projectTemplatesApiService = {
return response.data;
},
createFromWorklenzTemplate: async (body: { template_id: string }): Promise<IServerResponse<IProjectTemplate>> => {
createFromWorklenzTemplate: async (body: {
template_id: string;
}): Promise<IServerResponse<IProjectTemplate>> => {
const response = await apiClient.post(`${rootUrl}/import-template`, body);
return response.data;
},
createFromCustomTemplate: async (body: { template_id: string }): Promise<IServerResponse<IProjectTemplate>> => {
const response = await apiClient.post(`${rootUrl}/import-custom-template`, body);
return response.data;
},
createFromCustomTemplate: async (body: {
template_id: string;
}): Promise<IServerResponse<IProjectTemplate>> => {
const response = await apiClient.post(`${rootUrl}/import-custom-template`, body);
return response.data;
},
};

View File

@@ -101,7 +101,9 @@ export const projectsApiService = {
return response.data;
},
updateProject: async (payload: UpdateProjectPayload): Promise<IServerResponse<IProjectViewModel>> => {
updateProject: async (
payload: UpdateProjectPayload
): Promise<IServerResponse<IProjectViewModel>> => {
const { id, ...data } = payload;
const q = toQueryString({ current_project_id: id });
const url = `${API_BASE_URL}/projects/${id}${q}`;
@@ -127,7 +129,10 @@ export const projectsApiService = {
return response.data;
},
updateDefaultTab: async (body: { project_id: string; default_view: string }): Promise<IServerResponse<any>> => {
updateDefaultTab: async (body: {
project_id: string;
default_view: string;
}): Promise<IServerResponse<any>> => {
const url = `${rootUrl}/update-pinned-view`;
const response = await apiClient.put<IServerResponse<IProjectViewModel>>(`${url}`, body);
return response.data;
@@ -139,4 +144,3 @@ export const projectsApiService = {
return response.data;
},
};

View File

@@ -20,7 +20,7 @@ export const projectsApi = createApi({
if (!token) {
token = await refreshCsrfToken();
}
if (token) {
headers.set('X-CSRF-Token', token);
}

View File

@@ -1,5 +1,10 @@
import { IServerResponse } from '@/types/common.types';
import { IGetProjectsRequestBody, IRPTMembersViewModel, IRPTOverviewProjectMember, IRPTProjectsViewModel } from '@/types/reporting/reporting.types';
import {
IGetProjectsRequestBody,
IRPTMembersViewModel,
IRPTOverviewProjectMember,
IRPTProjectsViewModel,
} from '@/types/reporting/reporting.types';
import apiClient from '../api-client';
import { API_BASE_URL } from '@/shared/constants';
import { toQueryString } from '@/utils/toQueryString';
@@ -7,9 +12,7 @@ import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/reporting/members`;
export const reportingMembersApiService = {
getMembers: async (
body: any
): Promise<IServerResponse<IRPTMembersViewModel>> => {
getMembers: async (body: any): Promise<IServerResponse<IRPTMembersViewModel>> => {
const q = toQueryString(body);
const url = `${rootUrl}${q}`;
const response = await apiClient.get<IServerResponse<IRPTMembersViewModel>>(url);

View File

@@ -1,5 +1,10 @@
import { IServerResponse } from '@/types/common.types';
import { IGetProjectsRequestBody, IRPTOverviewProjectInfo, IRPTOverviewProjectMember, IRPTProjectsViewModel } from '@/types/reporting/reporting.types';
import {
IGetProjectsRequestBody,
IRPTOverviewProjectInfo,
IRPTOverviewProjectMember,
IRPTProjectsViewModel,
} from '@/types/reporting/reporting.types';
import apiClient from '../api-client';
import { API_BASE_URL } from '@/shared/constants';
import { toQueryString } from '@/utils/toQueryString';
@@ -33,8 +38,11 @@ export const reportingProjectsApiService = {
return response.data;
},
getTasks: async (projectId: string, groupBy: string): Promise<IServerResponse<ITaskListGroup[]>> => {
const q = toQueryString({group: groupBy})
getTasks: async (
projectId: string,
groupBy: string
): Promise<IServerResponse<ITaskListGroup[]>> => {
const q = toQueryString({ group: groupBy });
const url = `${API_BASE_URL}/reporting/overview/project/tasks/${projectId}${q}`;
const response = await apiClient.get<IServerResponse<ITaskListGroup[]>>(url);

View File

@@ -3,12 +3,20 @@ import { toQueryString } from '@/utils/toQueryString';
import apiClient from '../api-client';
import { IServerResponse } from '@/types/common.types';
import { IAllocationViewModel } from '@/types/reporting/reporting-allocation.types';
import { IProjectLogsBreakdown, IRPTTimeMember, IRPTTimeProject, ITimeLogBreakdownReq } from '@/types/reporting/reporting.types';
import {
IProjectLogsBreakdown,
IRPTTimeMember,
IRPTTimeProject,
ITimeLogBreakdownReq,
} from '@/types/reporting/reporting.types';
const rootUrl = `${API_BASE_URL}/reporting`;
export const reportingTimesheetApiService = {
getTimeSheetData: async (body = {}, archived = false): Promise<IServerResponse<IAllocationViewModel>> => {
getTimeSheetData: async (
body = {},
archived = false
): Promise<IServerResponse<IAllocationViewModel>> => {
const q = toQueryString({ archived });
const response = await apiClient.post(`${rootUrl}/allocation/${q}`, body);
return response.data;
@@ -19,24 +27,35 @@ export const reportingTimesheetApiService = {
return response.data;
},
getProjectTimeSheets: async (body = {}, archived = false): Promise<IServerResponse<IRPTTimeProject[]>> => {
getProjectTimeSheets: async (
body = {},
archived = false
): Promise<IServerResponse<IRPTTimeProject[]>> => {
const q = toQueryString({ archived });
const response = await apiClient.post(`${rootUrl}/time-reports/projects/${q}`, body);
return response.data;
},
getMemberTimeSheets: async (body = {}, archived = false): Promise<IServerResponse<IRPTTimeMember[]>> => {
getMemberTimeSheets: async (
body = {},
archived = false
): Promise<IServerResponse<IRPTTimeMember[]>> => {
const q = toQueryString({ archived });
const response = await apiClient.post(`${rootUrl}/time-reports/members/${q}`, body);
return response.data;
},
getProjectTimeLogs: async (body: ITimeLogBreakdownReq): Promise<IServerResponse<IProjectLogsBreakdown[]>> => {
getProjectTimeLogs: async (
body: ITimeLogBreakdownReq
): Promise<IServerResponse<IProjectLogsBreakdown[]>> => {
const response = await apiClient.post(`${rootUrl}/project-timelogs`, body);
return response.data;
},
getProjectEstimatedVsActual: async (body = {}, archived = false): Promise<IServerResponse<IRPTTimeProject[]>> => {
getProjectEstimatedVsActual: async (
body = {},
archived = false
): Promise<IServerResponse<IRPTTimeProject[]>> => {
const q = toQueryString({ archived });
const response = await apiClient.post(`${rootUrl}/time-reports/estimated-vs-actual${q}`, body);
return response.data;

View File

@@ -2,7 +2,13 @@ import { API_BASE_URL } from '@/shared/constants';
import apiClient from '../api-client';
import { IServerResponse } from '@/types/common.types';
import { ITeamMemberViewModel } from '@/types/teamMembers/teamMembersGetResponse.types';
import { DateList, Member, Project, ScheduleData, Settings } from '@/types/schedule/schedule-v2.types';
import {
DateList,
Member,
Project,
ScheduleData,
Settings,
} from '@/types/schedule/schedule-v2.types';
const rootUrl = `${API_BASE_URL}/schedule-gannt-v2`;
@@ -45,16 +51,18 @@ export const scheduleAPIService = {
},
fetchMemberProjects: async ({ id }: { id: string }): Promise<IServerResponse<Project>> => {
const response = await apiClient.get<IServerResponse<Project>>(`${rootUrl}/members/projects/${id}`);
const response = await apiClient.get<IServerResponse<Project>>(
`${rootUrl}/members/projects/${id}`
);
return response.data;
},
submitScheduleData: async ({
schedule
schedule,
}: {
schedule: ScheduleData
schedule: ScheduleData;
}): Promise<IServerResponse<any>> => {
const response = await apiClient.post<IServerResponse<any>>(`${rootUrl}/schedule`, schedule);
return response.data;
}
},
};

View File

@@ -52,8 +52,11 @@ export const profileSettingsApiService = {
return response.data;
},
updateTeamName: async (id: string, body: ITeam): Promise<IServerResponse<ITeam>> => {
const response = await apiClient.put<IServerResponse<ITeam>>(`${rootUrl}/team-name/${id}`, body);
updateTeamName: async (id: string, body: ITeam): Promise<IServerResponse<ITeam>> => {
const response = await apiClient.put<IServerResponse<ITeam>>(
`${rootUrl}/team-name/${id}`,
body
);
return response.data;
},

View File

@@ -21,12 +21,18 @@ export const taskTemplatesApiService = {
const response = await apiClient.get<IServerResponse<ITaskTemplateGetResponse>>(`${url}`);
return response.data;
},
createTemplate: async (body: { name: string, tasks: IProjectTask[] }): Promise<IServerResponse<ITask>> => {
createTemplate: async (body: {
name: string;
tasks: IProjectTask[];
}): Promise<IServerResponse<ITask>> => {
const url = `${rootUrl}`;
const response = await apiClient.post<IServerResponse<ITask>>(`${url}`, body);
return response.data;
},
updateTemplate: async (id: string, body: { name: string, tasks: IProjectTask[] }): Promise<IServerResponse<ITask>> => {
updateTemplate: async (
id: string,
body: { name: string; tasks: IProjectTask[] }
): Promise<IServerResponse<ITask>> => {
const url = `${rootUrl}/${id}`;
const response = await apiClient.put<IServerResponse<ITask>>(`${url}`, body);
return response.data;

View File

@@ -43,7 +43,7 @@ export const phasesApiService = {
return response.data;
},
updateNameOfPhase: async (phaseId: string, body: ITaskPhase, projectId: string,) => {
updateNameOfPhase: async (phaseId: string, body: ITaskPhase, projectId: string) => {
const q = toQueryString({ id: projectId, current_project_id: projectId });
const response = await apiClient.put<IServerResponse<ITaskPhase>>(
`${rootUrl}/${phaseId}${q}`,

View File

@@ -69,8 +69,16 @@ export const statusApiService = {
return response.data;
},
deleteStatus: async (statusId: string, projectId: string, replacingStatusId: string): Promise<IServerResponse<void>> => {
const q = toQueryString({ project: projectId, current_project_id: projectId, replace: replacingStatusId || null });
deleteStatus: async (
statusId: string,
projectId: string,
replacingStatusId: string
): Promise<IServerResponse<void>> => {
const q = toQueryString({
project: projectId,
current_project_id: projectId,
replace: replacingStatusId || null,
});
const response = await apiClient.delete<IServerResponse<void>>(`${rootUrl}/${statusId}${q}`);
return response.data;
},

View File

@@ -1,7 +1,7 @@
import { API_BASE_URL } from "@/shared/constants";
import apiClient from "../api-client";
import { IServerResponse } from "@/types/common.types";
import { ISubTask } from "@/types/tasks/subTask.types";
import { API_BASE_URL } from '@/shared/constants';
import apiClient from '../api-client';
import { IServerResponse } from '@/types/common.types';
import { ISubTask } from '@/types/tasks/subTask.types';
const root = `${API_BASE_URL}/sub-tasks`;
@@ -10,7 +10,4 @@ export const subTasksApiService = {
const response = await apiClient.get(`${root}/${parentTaskId}`);
return response.data;
},
};

View File

@@ -1,5 +1,9 @@
import { IServerResponse } from '@/types/common.types';
import { IProjectAttachmentsViewModel, ITaskAttachment, ITaskAttachmentViewModel } from '@/types/tasks/task-attachment-view-model';
import {
IProjectAttachmentsViewModel,
ITaskAttachment,
ITaskAttachmentViewModel,
} from '@/types/tasks/task-attachment-view-model';
import apiClient from '../api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IAvatarAttachment } from '@/types/avatarAttachment.types';
@@ -8,7 +12,6 @@ import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/attachments`;
const taskAttachmentsApiService = {
createTaskAttachment: async (
body: ITaskAttachment
): Promise<IServerResponse<ITaskAttachmentViewModel>> => {
@@ -16,18 +19,26 @@ const taskAttachmentsApiService = {
return response.data;
},
createAvatarAttachment: async (body: IAvatarAttachment): Promise<IServerResponse<{ url: string; }>> => {
createAvatarAttachment: async (
body: IAvatarAttachment
): Promise<IServerResponse<{ url: string }>> => {
const response = await apiClient.post(`${rootUrl}/avatar`, body);
return response.data;
},
getTaskAttachments: async (taskId: string): Promise<IServerResponse<ITaskAttachmentViewModel[]>> => {
getTaskAttachments: async (
taskId: string
): Promise<IServerResponse<ITaskAttachmentViewModel[]>> => {
const response = await apiClient.get(`${rootUrl}/tasks/${taskId}`);
return response.data;
},
getProjectAttachments: async (projectId: string, index: number, size: number ): Promise<IServerResponse<IProjectAttachmentsViewModel>> => {
const q = toQueryString({ index, size });
getProjectAttachments: async (
projectId: string,
index: number,
size: number
): Promise<IServerResponse<IProjectAttachmentsViewModel>> => {
const q = toQueryString({ index, size });
const response = await apiClient.get(`${rootUrl}/project/${projectId}${q}`);
return response.data;
},

View File

@@ -2,10 +2,16 @@ import apiClient from '@api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { toQueryString } from '@/utils/toQueryString';
import { ITaskComment, ITaskCommentsCreateRequest, ITaskCommentViewModel } from '@/types/tasks/task-comments.types';
import {
ITaskComment,
ITaskCommentsCreateRequest,
ITaskCommentViewModel,
} from '@/types/tasks/task-comments.types';
const taskCommentsApiService = {
create: async (data: ITaskCommentsCreateRequest): Promise<IServerResponse<ITaskCommentsCreateRequest>> => {
create: async (
data: ITaskCommentsCreateRequest
): Promise<IServerResponse<ITaskCommentsCreateRequest>> => {
const response = await apiClient.post(`${API_BASE_URL}/task-comments`, data);
return response.data;
},
@@ -21,12 +27,16 @@ const taskCommentsApiService = {
},
deleteAttachment: async (id: string, taskId: string): Promise<IServerResponse<ITaskComment>> => {
const response = await apiClient.delete(`${API_BASE_URL}/task-comments/attachment/${id}/${taskId}`);
const response = await apiClient.delete(
`${API_BASE_URL}/task-comments/attachment/${id}/${taskId}`
);
return response.data;
},
download: async (id: string, filename: string): Promise<IServerResponse<any>> => {
const response = await apiClient.get(`${API_BASE_URL}/task-comments/download?id=${id}&file=${filename}`);
const response = await apiClient.get(
`${API_BASE_URL}/task-comments/download?id=${id}&file=${filename}`
);
return response.data;
},
@@ -35,8 +45,13 @@ const taskCommentsApiService = {
return response.data;
},
updateReaction: async (id: string, body: {reaction_type: string, task_id: string}): Promise<IServerResponse<ITaskComment>> => {
const response = await apiClient.put(`${API_BASE_URL}/task-comments/reaction/${id}${toQueryString(body)}`);
updateReaction: async (
id: string,
body: { reaction_type: string; task_id: string }
): Promise<IServerResponse<ITaskComment>> => {
const response = await apiClient.put(
`${API_BASE_URL}/task-comments/reaction/${id}${toQueryString(body)}`
);
return response.data;
},
};

View File

@@ -1,7 +1,7 @@
import { API_BASE_URL } from "@/shared/constants";
import apiClient from "../api-client";
import { ITaskDependency } from "@/types/tasks/task-dependency.types";
import { IServerResponse } from "@/types/common.types";
import { API_BASE_URL } from '@/shared/constants';
import apiClient from '../api-client';
import { ITaskDependency } from '@/types/tasks/task-dependency.types';
import { IServerResponse } from '@/types/common.types';
const rootUrl = `${API_BASE_URL}/task-dependencies`;
@@ -10,7 +10,9 @@ export const taskDependenciesApiService = {
const response = await apiClient.get(`${rootUrl}/${taskId}`);
return response.data;
},
createTaskDependency: async (body: ITaskDependency): Promise<IServerResponse<ITaskDependency>> => {
createTaskDependency: async (
body: ITaskDependency
): Promise<IServerResponse<ITaskDependency>> => {
const response = await apiClient.post(`${rootUrl}`, body);
return response.data;
},
@@ -18,4 +20,4 @@ export const taskDependenciesApiService = {
const response = await apiClient.delete(`${rootUrl}/${dependencyId}`);
return response.data;
},
};
};

View File

@@ -1,16 +1,21 @@
import { API_BASE_URL } from "@/shared/constants";
import { IServerResponse } from "@/types/common.types";
import { ITaskRecurringSchedule } from "@/types/tasks/task-recurring-schedule";
import apiClient from "../api-client";
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { ITaskRecurringSchedule } from '@/types/tasks/task-recurring-schedule';
import apiClient from '../api-client';
const rootUrl = `${API_BASE_URL}/task-recurring`;
export const taskRecurringApiService = {
getTaskRecurringData: async (schedule_id: string): Promise<IServerResponse<ITaskRecurringSchedule>> => {
const response = await apiClient.get(`${rootUrl}/${schedule_id}`);
return response.data;
},
updateTaskRecurringData: async (schedule_id: string, body: any): Promise<IServerResponse<ITaskRecurringSchedule>> => {
return apiClient.put(`${rootUrl}/${schedule_id}`, body);
}
}
getTaskRecurringData: async (
schedule_id: string
): Promise<IServerResponse<ITaskRecurringSchedule>> => {
const response = await apiClient.get(`${rootUrl}/${schedule_id}`);
return response.data;
},
updateTaskRecurringData: async (
schedule_id: string,
body: any
): Promise<IServerResponse<ITaskRecurringSchedule>> => {
return apiClient.put(`${rootUrl}/${schedule_id}`, body);
},
};

View File

@@ -1,7 +1,7 @@
import { API_BASE_URL } from "@/shared/constants";
import apiClient from "../api-client";
import { IServerResponse } from "@/types/common.types";
import { ITaskLogViewModel } from "@/types/tasks/task-log-view.types";
import { API_BASE_URL } from '@/shared/constants';
import apiClient from '../api-client';
import { IServerResponse } from '@/types/common.types';
import { ITaskLogViewModel } from '@/types/tasks/task-log-view.types';
const rootUrl = `${API_BASE_URL}/task-time-log`;
@@ -16,12 +16,12 @@ export interface IRunningTimer {
}
export const taskTimeLogsApiService = {
getByTask: async (id: string) : Promise<IServerResponse<ITaskLogViewModel[]>> => {
getByTask: async (id: string): Promise<IServerResponse<ITaskLogViewModel[]>> => {
const response = await apiClient.get(`${rootUrl}/task/${id}`);
return response.data;
},
delete: async (id: string, taskId: string) : Promise<IServerResponse<void>> => {
delete: async (id: string, taskId: string): Promise<IServerResponse<void>> => {
const response = await apiClient.delete(`${rootUrl}/${id}?task=${taskId}`);
return response.data;
},

View File

@@ -1,23 +1,23 @@
import { ITaskListColumn } from "@/types/tasks/taskList.types";
import apiClient from "../api-client";
import { IServerResponse } from "@/types/common.types";
import { ITaskListColumn } from '@/types/tasks/taskList.types';
import apiClient from '../api-client';
import { IServerResponse } from '@/types/common.types';
export const tasksCustomColumnsService = {
getCustomColumns: async (projectId: string): Promise<IServerResponse<ITaskListColumn[]>> => {
const response = await apiClient.get(`/api/v1/custom-columns/project/${projectId}/columns`);
return response.data;
},
updateTaskCustomColumnValue: async (
taskId: string,
columnKey: string,
taskId: string,
columnKey: string,
value: string | number | boolean,
projectId: string
): Promise<IServerResponse<any>> => {
const response = await apiClient.put(`/api/v1/tasks/${taskId}/custom-column`, {
column_key: columnKey,
value: value,
project_id: projectId
project_id: projectId,
});
return response.data;
},
@@ -35,7 +35,7 @@ export const tasksCustomColumnsService = {
): Promise<IServerResponse<any>> => {
const response = await apiClient.post('/api/v1/custom-columns', {
project_id: projectId,
...columnData
...columnData,
});
return response.data;
},
@@ -63,7 +63,10 @@ export const tasksCustomColumnsService = {
projectId: string,
item: ITaskListColumn
): Promise<IServerResponse<ITaskListColumn>> => {
const response = await apiClient.put(`/api/v1/custom-columns/project/${projectId}/columns`, item);
const response = await apiClient.put(
`/api/v1/custom-columns/project/${projectId}/columns`,
item
);
return response.data;
}
},
};

View File

@@ -131,14 +131,19 @@ export const tasksApiService = {
return response.data;
},
getTaskDependencyStatus: async (taskId: string, statusId: string): Promise<IServerResponse<{ can_continue: boolean }>> => {
const q = toQueryString({taskId, statusId});
getTaskDependencyStatus: async (
taskId: string,
statusId: string
): Promise<IServerResponse<{ can_continue: boolean }>> => {
const q = toQueryString({ taskId, statusId });
const response = await apiClient.get(`${rootUrl}/dependency-status${q}`);
return response.data;
},
getTaskListV3: async (config: ITaskListConfigV2): Promise<IServerResponse<ITaskListV3Response>> => {
const q = toQueryString({ ...config, include_empty: "true" });
getTaskListV3: async (
config: ITaskListConfigV2
): Promise<IServerResponse<ITaskListV3Response>> => {
const q = toQueryString({ ...config, include_empty: 'true' });
const response = await apiClient.get(`${rootUrl}/list/v3/${config.id}${q}`);
return response.data;
},
@@ -148,20 +153,28 @@ export const tasksApiService = {
return response.data;
},
getTaskProgressStatus: async (projectId: string): Promise<IServerResponse<{
projectId: string;
totalTasks: number;
completedTasks: number;
avgProgress: number;
lastUpdated: string;
completionPercentage: number;
}>> => {
getTaskProgressStatus: async (
projectId: string
): Promise<
IServerResponse<{
projectId: string;
totalTasks: number;
completedTasks: number;
avgProgress: number;
lastUpdated: string;
completionPercentage: number;
}>
> => {
const response = await apiClient.get(`${rootUrl}/progress-status/${projectId}`);
return response.data;
},
// API method to reorder tasks
reorderTasks: async (params: { taskIds: string[]; newOrder: number[]; projectId: string }): Promise<IServerResponse<{ done: boolean }>> => {
reorderTasks: async (params: {
taskIds: string[];
newOrder: number[];
projectId: string;
}): Promise<IServerResponse<{ done: boolean }>> => {
const response = await apiClient.post(`${rootUrl}/reorder`, {
task_ids: params.taskIds,
new_order: params.newOrder,
@@ -171,7 +184,12 @@ export const tasksApiService = {
},
// API method to update task group (status, priority, phase)
updateTaskGroup: async (params: { taskId: string; groupType: 'status' | 'priority' | 'phase'; groupValue: string; projectId: string }): Promise<IServerResponse<{ done: boolean }>> => {
updateTaskGroup: async (params: {
taskId: string;
groupType: 'status' | 'priority' | 'phase';
groupValue: string;
projectId: string;
}): Promise<IServerResponse<{ done: boolean }>> => {
const response = await apiClient.put(`${rootUrl}/${params.taskId}/group`, {
group_type: params.groupType,
group_value: params.groupValue,

View File

@@ -44,7 +44,9 @@ export const teamMembersApiService = {
return response.data;
},
getAll: async (projectId: string | null = null): Promise<IServerResponse<ITeamMemberViewModel[]>> => {
getAll: async (
projectId: string | null = null
): Promise<IServerResponse<ITeamMemberViewModel[]>> => {
const params = new URLSearchParams(projectId ? { project: projectId } : {});
const response = await apiClient.get<IServerResponse<ITeamMemberViewModel[]>>(
`${rootUrl}/all${params.toString() ? '?' + params.toString() : ''}`

View File

@@ -14,11 +14,8 @@ const rootUrl = `${API_BASE_URL}/teams`;
export const teamsApiService = {
getTeams: async (): Promise<IServerResponse<ITeamGetResponse[]>> => {
const response = await apiClient.get<IServerResponse<ITeamGetResponse[]>>(
`${rootUrl}`
);
const response = await apiClient.get<IServerResponse<ITeamGetResponse[]>>(`${rootUrl}`);
return response.data;
},
setActiveTeam: async (teamId: string): Promise<IServerResponse<ITeamActivateResponse>> => {
@@ -29,23 +26,18 @@ export const teamsApiService = {
return response.data;
},
createTeam: async (team: IOrganizationTeam): Promise<IServerResponse<ITeam>> => {
const response = await apiClient.post<IServerResponse<ITeam>>(`${rootUrl}`, team);
return response.data;
},
getInvitations: async (): Promise<IServerResponse<ITeamInvites[]>> => {
const response = await apiClient.get<IServerResponse<ITeamInvites[]>>(
`${rootUrl}/invites`
);
const response = await apiClient.get<IServerResponse<ITeamInvites[]>>(`${rootUrl}/invites`);
return response.data;
},
acceptInvitation: async (body: IAcceptTeamInvite): Promise<IServerResponse<ITeamInvites>> => {
const response = await apiClient.put<IServerResponse<ITeamInvites>>(`${rootUrl}`, body);
return response.data;
}
},
};