This commit is contained in:
chamikaJ
2025-04-17 18:28:54 +05:30
parent f583291d8a
commit 8825b0410a
2837 changed files with 241385 additions and 127578 deletions

View File

@@ -0,0 +1,258 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '../api-client';
import { API_BASE_URL } from '@/shared/constants';
import {
IOrganization,
IOrganizationUser,
IOrganizationTeam,
IOrganizationUsersGetRequest,
IOrganizationTeamGetRequest,
IOrganizationProjectsGetResponse,
IBillingConfigurationCountry,
IBillingConfiguration,
IBillingAccountInfo,
IUpgradeSubscriptionPlanResponse,
IPricingPlans,
IBillingTransaction,
IBillingChargesResponse,
IStorageInfo,
IFreePlanSettings,
IBillingAccountStorage,
} from '@/types/admin-center/admin-center.types';
import { IClient } from '@/types/client.types';
import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/admin-center`;
export interface IOrganizationUserRequestParams {
page: number;
pageSize: number;
sort: string;
order: string;
searchTerm: string;
}
export interface IOrganizationTeamRequestParams {
index: number;
size: number;
field: string | null;
order: string | null;
search: string | null;
}
export const adminCenterApiService = {
async getOrganizationDetails(): Promise<IServerResponse<IOrganization>> {
const response = await apiClient.get<IServerResponse<IOrganization>>(`${rootUrl}/organization`);
return response.data;
},
async getOrganizationAdmins(): Promise<IServerResponse<IOrganizationUser[]>> {
const response = await apiClient.get<IServerResponse<IOrganizationUser[]>>(
`${rootUrl}/organization/admins`
);
return response.data;
},
async updateOrganizationName<T>(body: IClient): Promise<IServerResponse<IOrganization>> {
const response = await apiClient.put<IServerResponse<IOrganization>>(
`${rootUrl}/organization`,
body
);
return response.data;
},
async updateOwnerContactNumber<T>(body: {
contact_number: string;
}): Promise<IServerResponse<IOrganization>> {
const response = await apiClient.put<IServerResponse<IOrganization>>(
`${rootUrl}/organization/owner/contact-number`,
body
);
return response.data;
},
async getOrganizationUsers(
requestParams: IOrganizationUserRequestParams
): Promise<IServerResponse<IOrganizationUsersGetRequest>> {
const params = new URLSearchParams({
index: requestParams.page.toString(),
size: requestParams.pageSize.toString(),
...(requestParams.sort && { field: requestParams.sort }),
...(requestParams.order && { order: requestParams.order }),
...(requestParams.searchTerm && { search: requestParams.searchTerm }),
});
const response = await apiClient.get<IServerResponse<IOrganizationUsersGetRequest>>(
`${rootUrl}/organization/users?${params}`
);
return response.data;
},
async getOrganizationTeams(
requestParams: IOrganizationTeamRequestParams
): Promise<IServerResponse<IOrganizationTeamGetRequest>> {
const params = new URLSearchParams({
index: requestParams.index.toString(),
size: requestParams.size.toString(),
...(requestParams.field && { field: requestParams.field }),
...(requestParams.order && { order: requestParams.order }),
...(requestParams.search && { search: requestParams.search }),
});
const response = await apiClient.get<IServerResponse<IOrganizationTeamGetRequest>>(
`${rootUrl}/organization/teams?${params}`
);
return response.data;
},
async getOrganizationTeam(team_id: string): Promise<IServerResponse<IOrganizationTeam>> {
const response = await apiClient.get<IServerResponse<IOrganizationTeam>>(
`${rootUrl}/organization/team/${team_id}`
);
return response.data;
},
async updateTeam(
team_id: string,
team_members: IOrganizationUser[]
): Promise<IServerResponse<IOrganization>> {
const response = await apiClient.put<IServerResponse<IOrganization>>(
`${rootUrl}/organization/team/${team_id}`,
team_members
);
return response.data;
},
async deleteTeam(id: string): Promise<IServerResponse<any>> {
const response = await apiClient.delete<IServerResponse<any>>(
`${rootUrl}/organization/team/${id}`
);
return response.data;
},
async removeTeamMember(team_member_id: string, team_id: string): Promise<IServerResponse<any>> {
const response = await apiClient.put<IServerResponse<any>>(
`${rootUrl}/organization/team-member/${team_member_id}`,
{ teamId: team_id }
);
return response.data;
},
async getOrganizationProjects(
requestParams: IOrganizationTeamRequestParams
): Promise<IServerResponse<IOrganizationProjectsGetResponse>> {
const params = new URLSearchParams({
index: requestParams.index.toString(),
size: requestParams.size.toString(),
...(requestParams.field && { field: requestParams.field }),
...(requestParams.order && { order: requestParams.order }),
...(requestParams.search && { search: requestParams.search }),
});
const response = await apiClient.get<IServerResponse<IOrganizationProjectsGetResponse>>(
`${rootUrl}/organization/projects?${params}`
);
return response.data;
},
// Billing - Configuration
async getCountries(): Promise<IServerResponse<IBillingConfigurationCountry[]>> {
const response = await apiClient.get<IServerResponse<IBillingConfigurationCountry[]>>(
`${rootUrl}/billing/countries`
);
return response.data;
},
async getBillingConfiguration(): Promise<IServerResponse<IBillingConfiguration>> {
const response = await apiClient.get<IServerResponse<IBillingConfiguration>>(
`${rootUrl}/billing/configuration`
);
return response.data;
},
async updateBillingConfiguration(body: IBillingConfiguration): Promise<IServerResponse<IBillingConfiguration>> {
const response = await apiClient.put<IServerResponse<IBillingConfiguration>>(
`${rootUrl}/billing/configuration`,
body
);
return response.data;
},
// Billing - Current Bill
async getCharges(): Promise<IServerResponse<IBillingChargesResponse>> {
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`);
return response.data;
},
async getBillingAccountInfo(): Promise<IServerResponse<IBillingAccountInfo>> {
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`);
return response.data;
},
async upgradePlan(plan: string): Promise<IServerResponse<IUpgradeSubscriptionPlanResponse>> {
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})}`);
return response.data;
},
async getPlans(): Promise<IServerResponse<IPricingPlans>> {
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`);
return response.data;
},
async pauseSubscription(): Promise<IServerResponse<any>> {
const response = await apiClient.get<IServerResponse<any>>(`${rootUrl}/billing/pause-plan`);
return response.data;
},
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`);
return response.data;
},
async addMoreSeats(totalSeats: number): Promise<IServerResponse<any>> {
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,
});
return response.data;
},
async getAccountStorage(): Promise<IServerResponse<IBillingAccountStorage>> {
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}`);
return response.data;
},
};

View File

@@ -0,0 +1,35 @@
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import apiClient from '../api-client';
import { toQueryString } from '@/utils/toQueryString';
import { IUpgradeSubscriptionPlanResponse } from '@/types/admin-center/admin-center.types';
const rootUrl = `${API_BASE_URL}/billing`;
export const billingApiService = {
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}`
);
return response.data;
},
async purchaseMoreSeats(seatCount: number): Promise<IServerResponse<IUpgradeSubscriptionPlanResponse>> {
const response = await apiClient.post<IServerResponse<IUpgradeSubscriptionPlanResponse>>(
`${rootUrl}/purchase-more-seats`,
{ seatCount }
);
return response.data;
},
async contactUs(contactNo: string): Promise<IServerResponse<any>> {
const response = await apiClient.get<IServerResponse<any>>(
`${rootUrl}/contact-us${toQueryString({ contactNo })}`
);
return response.data;
}
};

View File

@@ -0,0 +1,134 @@
import axios, { AxiosError } from 'axios';
import alertService from '@/services/alerts/alertService';
import logger from '@/utils/errorLogger';
export const getCsrfToken = (): string | null => {
const match = document.cookie.split('; ').find(cookie => cookie.startsWith('XSRF-TOKEN='));
if (!match) {
return null;
}
return decodeURIComponent(match.split('=')[1]);
};
// Function to refresh CSRF token if needed
export const refreshCsrfToken = async (): Promise<string | null> => {
try {
// Make a GET request to the server to get a fresh CSRF token
await axios.get(`${import.meta.env.VITE_API_URL}/csrf-token`, { withCredentials: true });
return getCsrfToken();
} catch (error) {
console.error('Failed to refresh CSRF token:', error);
return null;
}
};
const apiClient = axios.create({
baseURL: import.meta.env.VITE_API_URL,
withCredentials: true,
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
});
// Request interceptor
apiClient.interceptors.request.use(
config => {
const token = getCsrfToken();
if (token) {
config.headers['X-CSRF-Token'] = token;
} else {
console.warn('No CSRF token found');
}
return config;
},
error => Promise.reject(error)
);
// Response interceptor with notification handling based on done flag
apiClient.interceptors.response.use(
response => {
// Handle 302 redirect
if (response.status === 302) {
const redirectUrl = response.headers.location;
if (redirectUrl) {
window.location.href = redirectUrl;
return response;
}
}
if (response.data) {
const { title, message, auth_error, done } = response.data;
if (message && message.charAt(0) !== '$') {
if (done) {
alertService.success(title || '', message);
} else {
alertService.error(title || '', message);
}
} else if (auth_error) {
alertService.error(title || 'Authentication Error', auth_error);
}
}
return response;
},
async (error: AxiosError) => {
const { message, code, name } = error || {};
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' ||
(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) {
// Update the token in the failed request
error.config.headers['X-CSRF-Token'] = newToken;
// Retry the original request with the new token
return axios(error.config);
} else {
// If token refresh failed, redirect to login
window.location.href = '/auth/login';
return Promise.reject(error);
}
}
// Add 401 unauthorized handling
if (error.response?.status === 401) {
alertService.error('Session Expired', 'Please log in again');
// Redirect to login page or trigger re-authentication
window.location.href = '/auth/login'; // Adjust this path as needed
return Promise.reject(error);
}
const errorMessage = message || 'An unexpected error occurred';
const errorTitle = 'Error';
if (error.code !== 'ERR_NETWORK') {
alertService.error(errorTitle, errorMessage);
}
// Development logging
if (import.meta.env.VITE_APP_ENV === 'development') {
logger.error('API Error:', {
code,
name,
message,
headers: error.config?.headers,
cookies: document.cookie,
});
}
return Promise.reject(error);
}
);
export default apiClient;

View File

@@ -0,0 +1,33 @@
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}`);
return response.data;
},
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}`);
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}`);
return response.data;
},
deleteAttachment: async (id: string): Promise<IServerResponse<string>> => {
const response = await apiClient.delete<IServerResponse<string>>(`${rootUrl}/tasks/${id}`);
return response.data;
},
};

View File

@@ -0,0 +1,59 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '../api-client';
import {
IUserLoginRequest,
IUserLoginResponse,
IAuthorizeResponse,
} from '@/types/auth/login.types';
import { AUTH_API_BASE_URL } from '@/shared/constants';
const rootUrl = `${AUTH_API_BASE_URL}`;
export const authApiService = {
async login(credentials: IUserLoginRequest): Promise<IAuthorizeResponse> {
const response = await apiClient.post<IAuthorizeResponse>(`${rootUrl}/login`, credentials);
return response.data;
},
async logout(): Promise<IServerResponse<void>> {
const response = await apiClient.get<IServerResponse<void>>(`${rootUrl}/logout`);
return response.data;
},
async verify(): Promise<IAuthorizeResponse> {
const response = await apiClient.get<IAuthorizeResponse>(`${rootUrl}/verify`);
return response.data;
},
async signUp(body: any): Promise<IServerResponse<void>> {
const response = await apiClient.post<IServerResponse<void>>(`${rootUrl}/signup`, body);
return response.data;
},
async signUpCheck(body: any): Promise<IServerResponse<void>> {
const response = await apiClient.post<IServerResponse<void>>(`${rootUrl}/signup/check`, body);
return response.data;
},
async resetPassword(email: string): Promise<IServerResponse<string>> {
const response = await apiClient.post<IServerResponse<string>>(`${rootUrl}/reset-password`, {
email,
});
return response.data;
},
async updatePassword(values: any): Promise<IServerResponse<string>> {
const response = await apiClient.post<IServerResponse<string>>(
`${rootUrl}/update-password`,
values
);
return response.data;
},
async verifyRecaptchaToken(token: string): Promise<IServerResponse<string>> {
const response = await apiClient.post<IServerResponse<string>>(`${rootUrl}/verify-captcha`, {
token,
});
return response.data;
},
};

View File

@@ -0,0 +1,49 @@
import { IClient, IClientsViewModel } from '@/types/client.types';
import apiClient from '@api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/clients`;
export const clientsApiService = {
// Get all clients
async getClients(
index: number,
size: number,
field: string | null,
order: string | null,
search?: string | null
): Promise<IServerResponse<IClientsViewModel>> {
const s = encodeURIComponent(search || '');
const queryString = toQueryString({ index, size, field, order, search: s });
const response = await apiClient.get<IServerResponse<IClientsViewModel>>(
`${rootUrl}${queryString}`
);
return response.data;
},
// Get single client by ID
async getClientById(id: string): Promise<IServerResponse<IClient>> {
const response = await apiClient.get<IServerResponse<IClient>>(`${rootUrl}/${id}`);
return response.data;
},
// Create new client
async createClient(body: IClient): Promise<IServerResponse<IClient>> {
const response = await apiClient.post<IServerResponse<IClient>>(rootUrl, body);
return response.data;
},
// Update existing client
async updateClient(id: string, body: IClient): Promise<IServerResponse<IClient>> {
const response = await apiClient.put<IServerResponse<IClient>>(`${rootUrl}/${id}`, body);
return response.data;
},
// Delete client
async deleteClient(id: string): Promise<IServerResponse<void>> {
const response = await apiClient.delete<IServerResponse<void>>(`${rootUrl}/${id}`);
return response.data;
},
};

View File

@@ -0,0 +1,72 @@
import { BaseQueryFn, createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { toQueryString } from '@/utils/toQueryString';
import { IHomeTasksModel, IHomeTasksConfig } from '@/types/home/home-page.types';
import { IMyTask } from '@/types/home/my-tasks.types';
import { IProject } from '@/types/project/project.types';
import { getCsrfToken } from '../api-client';
const rootUrl = '/home';
const api = createApi({
reducerPath: 'homePageApi',
baseQuery: fetchBaseQuery({
baseUrl: `${import.meta.env.VITE_API_URL}${API_BASE_URL}`,
prepareHeaders: headers => {
headers.set('X-CSRF-Token', getCsrfToken() || '');
headers.set('Content-Type', 'application/json');
},
credentials: 'include',
}),
tagTypes: ['personalTasks', 'projects', 'teamProjects'],
endpoints: builder => ({
getPersonalTasks: builder.query<IServerResponse<IMyTask[]>, void>({
query: () => `${rootUrl}/personal-tasks`,
}),
createPersonalTask: builder.mutation<IServerResponse<any>, IMyTask>({
query: body => ({
url: `${rootUrl}/personal-task`,
method: 'POST',
body,
}),
}),
markPersonalTaskAsDone: builder.mutation<IServerResponse<any>, string>({
query: taskId => ({
url: `${rootUrl}/update-personal-task`,
method: 'PUT',
body: { id: taskId },
}),
}),
getMyTasks: builder.query<IServerResponse<IHomeTasksModel>, IHomeTasksConfig>({
query: config => {
const { tasks_group_by, current_tab, is_calendar_view, selected_date, time_zone } = config;
const url = `${rootUrl}/tasks${toQueryString({
group_by: tasks_group_by,
current_tab,
is_calendar_view,
selected_date: selected_date?.toISOString().split('T')[0],
time_zone,
})}`;
return url;
},
}),
getProjects: builder.query<IServerResponse<IProject[]>, { view: number }>({
query: ({ view }) => `${rootUrl}/projects?view=${view}`,
}),
getProjectsByTeam: builder.query<IServerResponse<IProject[]>, void>({
query: () => `${rootUrl}/team-projects`,
}),
}),
});
export const {
useCreatePersonalTaskMutation,
useGetMyTasksQuery,
useGetPersonalTasksQuery,
useGetProjectsQuery,
useGetProjectsByTeamQuery,
useMarkPersonalTaskAsDoneMutation,
} = api;
export default api;

View File

@@ -0,0 +1,34 @@
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 { IMyTask } from '@/types/home/my-tasks.types';
import { IWorklenzNotification } from '@/types/notifications/notifications.types';
const rootUrl = `${API_BASE_URL}/notifications`;
export const notificationsApiService = {
getNotifications: async (filter: string): Promise<IServerResponse<IWorklenzNotification[]>> => {
const q = toQueryString({ filter });
const response = await apiClient.get<IServerResponse<IWorklenzNotification[]>>(
`${rootUrl}${q}`
);
return response.data;
},
updateNotification: async (id: string): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(`${rootUrl}/${id}`);
return response.data;
},
readAllNotifications: async (): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(`${rootUrl}/read-all`);
return response.data;
},
getUnreadCount: async (): Promise<IServerResponse<number>> => {
const response = await apiClient.get<IServerResponse<number>>(`${rootUrl}/unread-count`);
return response.data;
},
};

View File

@@ -0,0 +1,52 @@
import { IProjectMemberViewModel } from '@/types/projectMember.types';
import apiClient from '../api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/project-members`;
export const projectMembersApiService = {
createProjectMember: async (
body: IProjectMemberViewModel
): Promise<IServerResponse<IProjectMemberViewModel>> => {
const q = toQueryString({current_project_id: body.project_id});
const response = await apiClient.post<IServerResponse<IProjectMemberViewModel>>(
`${rootUrl}${q}`,
body
);
return response.data;
},
createByEmail: async (body: {
project_id: string;
email: string;
}): Promise<IServerResponse<IProjectMemberViewModel>> => {
const response = await apiClient.post<IServerResponse<IProjectMemberViewModel>>(
`${rootUrl}/invite`,
body
);
return response.data;
},
getByProjectId: async (
projectId: string
): Promise<IServerResponse<IProjectMemberViewModel[]>> => {
const response = await apiClient.get<IServerResponse<IProjectMemberViewModel[]>>(
`${rootUrl}/${projectId}`
);
return response.data;
},
deleteProjectMember: async (
id: string,
currentProjectId: string
): Promise<IServerResponse<IProjectMemberViewModel>> => {
const q = toQueryString({ current_project_id: currentProjectId });
const response = await apiClient.delete<IServerResponse<IProjectMemberViewModel>>(
`${rootUrl}/${id}${q}`
);
return response.data;
},
};

View File

@@ -0,0 +1,58 @@
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import {
IAccountSetupRequest,
IAccountSetupResponse,
IProjectTemplate,
IWorklenzTemplate,
} from '@/types/project-templates/project-templates.types';
import apiClient from '../api-client';
import { ICustomProjectTemplateCreateRequest } from '@/types/project/projectTemplate.types';
const rootUrl = `${API_BASE_URL}/project-templates`;
export const projectTemplatesApiService = {
getWorklenzTemplates: async (): Promise<IServerResponse<IWorklenzTemplate[]>> => {
const response = await apiClient.get(`${rootUrl}/worklenz-templates`);
return response.data;
},
getByTemplateId: async (templateId: string): Promise<IServerResponse<IProjectTemplate>> => {
const response = await apiClient.get(`${rootUrl}/worklenz-templates/${templateId}`);
return response.data;
},
getCustomTemplates: async (): Promise<IServerResponse<IWorklenzTemplate[]>> => {
const response = await apiClient.get(`${rootUrl}/custom-templates`);
return response.data;
},
setupAccount: async (
model: IAccountSetupRequest
): Promise<IServerResponse<IAccountSetupResponse>> => {
const response = await apiClient.post(`${rootUrl}/setup`, model);
return response.data;
},
createCustomTemplate: async (body: { template_id: string }): Promise<IServerResponse<IProjectTemplate>> => {
const response = await apiClient.post(`${rootUrl}/custom-template`, body);
return response.data;
},
deleteCustomTemplate: async (id: string): Promise<IServerResponse<void>> => {
const response = await apiClient.delete(`${rootUrl}/${id}`);
return response.data;
},
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;
},
};

View File

@@ -0,0 +1,63 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '@/api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import {
IMentionMemberSelectOption,
IMentionMemberViewModel,
IProjectCommentsCreateRequest,
} from '@/types/project/projectComments.types';
import { toQueryString } from '@/utils/toQueryString';
import { IProjectUpdateCommentViewModel } from '@/types/project/project.types';
const rootUrl = `${API_BASE_URL}/project-comments`;
export const projectCommentsApiService = {
createProjectComment: async (
body: IProjectCommentsCreateRequest
): Promise<IServerResponse<IProjectCommentsCreateRequest>> => {
const url = `${rootUrl}`;
const response = await apiClient.post<IServerResponse<IProjectCommentsCreateRequest>>(
`${url}`,
body
);
return response.data;
},
getMentionMembers: async (
projectId: string,
index: number,
size: number,
field: string | null,
order: string | null,
search: string | null
): Promise<IServerResponse<IMentionMemberViewModel[]>> => {
const s = encodeURIComponent(search || '');
const url = `${rootUrl}/project-members/${projectId}${toQueryString({ index, size, field, order, search: s })}`;
const response = await apiClient.get<IServerResponse<IMentionMemberViewModel[]>>(`${url}`);
return response.data;
},
getCountByProjectId: async (projectId: string): Promise<IServerResponse<number>> => {
const url = `${rootUrl}/${projectId}/comments/count`;
const response = await apiClient.get<IServerResponse<number>>(`${url}`);
return response.data;
},
getByProjectId: async (
projectId: string,
isLimit: boolean = false
): Promise<IServerResponse<IProjectUpdateCommentViewModel[]>> => {
const url = `${rootUrl}/project-comments/${projectId}${toQueryString({ latest: isLimit })}`;
const response = await apiClient.get<IServerResponse<IProjectUpdateCommentViewModel[]>>(
`${url}`
);
return response.data;
},
deleteComment: async (commentId: string): Promise<IServerResponse<string>> => {
const url = `${rootUrl}/delete/${commentId}`;
const response = await apiClient.delete<IServerResponse<string>>(`${url}`);
return response.data;
},
};

View File

@@ -0,0 +1,125 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '@/api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import { toQueryString } from '@/utils/toQueryString';
import { IProjectViewModel } from '@/types/project/projectViewModel.types';
import { IDeadlineTaskStats } from '@/types/project/projectInsights.types';
import {
IInsightTasks,
IProjectInsightsGetRequest,
IProjectLogs,
IProjectMemberStats,
} from '@/types/project/projectInsights.types';
import { ITaskStatusCounts } from '@/types/project/project-insights.types';
const rootUrl = `${API_BASE_URL}/project-insights`;
export const projectInsightsApiService = {
getProjectInsights: async (id: string): Promise<IServerResponse<IProjectViewModel>> => {
const url = `${rootUrl}/${id}/insights`;
const response = await apiClient.get<IServerResponse<IProjectViewModel>>(`${url}`);
return response.data;
},
getProjectOverviewData: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<IProjectInsightsGetRequest>> => {
const url = `${rootUrl}/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<IProjectInsightsGetRequest>>(url);
return response.data;
},
getLastUpdatedTasks: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<IInsightTasks[]>> => {
const url = `${rootUrl}/last-updated/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<IInsightTasks[]>>(url);
return response.data;
},
getProjectLogs: async (id: string): Promise<IServerResponse<IProjectLogs[]>> => {
const url = `${rootUrl}/logs/${id}`;
const response = await apiClient.get<IServerResponse<IProjectLogs[]>>(url);
return response.data;
},
getTaskStatusCounts: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<ITaskStatusCounts[]>> => {
const url = `${rootUrl}/status-overview/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<ITaskStatusCounts[]>>(url);
return response.data;
},
getPriorityOverview: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<ITaskStatusCounts[]>> => {
const url = `${rootUrl}/priority-overview/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<ITaskStatusCounts[]>>(url);
return response.data;
},
getOverdueTasks: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<IInsightTasks[]>> => {
const url = `${rootUrl}/overdue-tasks/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<IInsightTasks[]>>(url);
return response.data;
},
getTasksCompletedEarly: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<IInsightTasks[]>> => {
const url = `${rootUrl}/early-tasks/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<IInsightTasks[]>>(url);
return response.data;
},
getTasksCompletedLate: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<IInsightTasks[]>> => {
const url = `${rootUrl}/late-tasks/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<IInsightTasks[]>>(url);
return response.data;
},
getMemberInsightAStats: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<IProjectMemberStats>> => {
const url = `${rootUrl}/members/stats/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<IProjectMemberStats>>(url);
return response.data;
},
getMemberTasks: async (body: any): Promise<IServerResponse<IInsightTasks[]>> => {
const url = `${rootUrl}/members/tasks`;
const response = await apiClient.post<IServerResponse<IInsightTasks[]>>(url, body);
return response.data;
},
getProjectDeadlineStats: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<IDeadlineTaskStats>> => {
const url = `${rootUrl}/deadline/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<IDeadlineTaskStats>>(url);
return response.data;
},
getOverloggedTasks: async (
id: string,
include_archived: boolean
): Promise<IServerResponse<IInsightTasks[]>> => {
const url = `${rootUrl}/overlogged-tasks/${id}?archived=${include_archived}`;
const response = await apiClient.get<IServerResponse<IInsightTasks[]>>(url);
return response.data;
},
};

View File

@@ -0,0 +1,13 @@
import { IServerResponse } from '@/types/common.types';
import { API_BASE_URL } from '@/shared/constants';
import { IProjectHealth } from '@/types/project/projectHealth.types';
import apiClient from '@api/api-client';
const rootUrl = `${API_BASE_URL}/project-healths`;
export const projectHealthApiService = {
getHealthOptions: async (): Promise<IServerResponse<IProjectHealth[]>> => {
const response = await apiClient.get<IServerResponse<IProjectHealth[]>>(rootUrl);
return response.data;
},
};

View File

@@ -0,0 +1,13 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '../../api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IProjectStatus } from '@/types/project/projectStatus.types';
const rootUrl = `${API_BASE_URL}/project-statuses`;
export const projectStatusesApiService = {
getStatuses: async (): Promise<IServerResponse<IProjectStatus[]>> => {
const response = await apiClient.get<IServerResponse<IProjectStatus[]>>(rootUrl);
return response.data;
},
};

View File

@@ -0,0 +1,121 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '../api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IProjectOverviewStats, IProjectsViewModel } from '@/types/project/projectsViewModel.types';
import { toQueryString } from '@/utils/toQueryString';
import { IProjectViewModel } from '@/types/project/projectViewModel.types';
import { ITeamMemberOverviewGetResponse } from '@/types/project/project-insights.types';
import { IProjectMembersViewModel } from '@/types/projectMember.types';
import { IProjectManager } from '@/types/project/projectManager.types';
const rootUrl = `${API_BASE_URL}/projects`;
export const projectsApiService = {
getProjects: async (
index: number,
size: number,
field: string | null,
order: string | null,
search: string | null,
filter: number | null = null,
statuses: string | null = null,
categories: string | null = null
): Promise<IServerResponse<IProjectsViewModel>> => {
const s = encodeURIComponent(search || '');
const url = `${rootUrl}${toQueryString({ index, size, field, order, search: s, filter, statuses, categories })}`;
const response = await apiClient.get<IServerResponse<IProjectsViewModel>>(`${url}`);
return response.data;
},
getProject: async (id: string): Promise<IServerResponse<IProjectViewModel>> => {
const url = `${rootUrl}/${id}`;
const response = await apiClient.get<IServerResponse<IProjectViewModel>>(`${url}`);
return response.data;
},
toggleFavoriteProject: async (id: string): Promise<IServerResponse<IProjectsViewModel>> => {
const url = `${rootUrl}/favorite/${id}`;
const response = await apiClient.get<IServerResponse<IProjectsViewModel>>(`${url}`);
return response.data;
},
getOverViewById: async (id: string): Promise<IServerResponse<IProjectOverviewStats>> => {
const url = `${rootUrl}/overview/${id}`;
const response = await apiClient.get<IServerResponse<IProjectOverviewStats>>(`${url}`);
return response.data;
},
getOverViewMembersById: async (
id: string,
archived = false
): Promise<IServerResponse<ITeamMemberOverviewGetResponse[]>> => {
const url = `${rootUrl}/overview-members/${id}?archived=${archived}`;
const response = await apiClient.get<IServerResponse<ITeamMemberOverviewGetResponse[]>>(
`${url}`
);
return response.data;
},
getMembers: async (
id: string,
index: number,
size: number,
field: string | null,
order: string | null,
search: string | null
): Promise<IServerResponse<IProjectMembersViewModel>> => {
const s = encodeURIComponent(search || '');
const url = `${rootUrl}/members/${id}${toQueryString({ index, size, field, order, search: s })}`;
const response = await apiClient.get<IServerResponse<IProjectMembersViewModel>>(`${url}`);
return response.data;
},
createProject: async (
project: IProjectViewModel
): Promise<IServerResponse<IProjectViewModel>> => {
const url = `${rootUrl}`;
const response = await apiClient.post<IServerResponse<IProjectViewModel>>(`${url}`, project);
return response.data;
},
updateProject: async (
id: string,
project: IProjectViewModel
): Promise<IServerResponse<IProjectViewModel>> => {
const q = toQueryString({ current_project_id: id });
const url = `${rootUrl}/${id}${q}`;
const response = await apiClient.put<IServerResponse<IProjectViewModel>>(`${url}`, project);
return response.data;
},
deleteProject: async (id: string): Promise<IServerResponse<IProjectViewModel>> => {
const url = `${rootUrl}/${id}`;
const response = await apiClient.delete<IServerResponse<IProjectViewModel>>(`${url}`);
return response.data;
},
toggleArchiveProject: async (id: string): Promise<IServerResponse<any>> => {
const url = `${rootUrl}/archive/${id}`;
const response = await apiClient.get<IServerResponse<IProjectViewModel>>(`${url}`);
return response.data;
},
toggleArchiveProjectForAll: async (id: string): Promise<IServerResponse<any>> => {
const url = `${rootUrl}/archive-all/${id}`;
const response = await apiClient.get<IServerResponse<IProjectViewModel>>(`${url}`);
return response.data;
},
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;
},
getProjectManagers: async (): Promise<IServerResponse<IProjectManager[]>> => {
const url = `${API_BASE_URL}/project-managers`;
const response = await apiClient.get<IServerResponse<IProjectManager[]>>(`${url}`);
return response.data;
},
};

View File

@@ -0,0 +1,153 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { API_BASE_URL } from '@/shared/constants';
import { IProjectViewModel } from '@/types/project/projectViewModel.types';
import { IProjectCategory } from '@/types/project/projectCategory.types';
import { IProjectsViewModel } from '@/types/project/projectsViewModel.types';
import { IServerResponse } from '@/types/common.types';
import { IProjectMembersViewModel } from '@/types/projectMember.types';
import { getCsrfToken } from '../api-client';
const rootUrl = '/projects';
export const projectsApi = createApi({
reducerPath: 'projectsApi',
baseQuery: fetchBaseQuery({
baseUrl: `${import.meta.env.VITE_API_URL}${API_BASE_URL}`,
prepareHeaders: headers => {
headers.set('X-CSRF-Token', getCsrfToken() || '');
headers.set('Content-Type', 'application/json');
},
credentials: 'include',
}),
tagTypes: ['Projects', 'ProjectCategories', 'ProjectMembers'],
endpoints: builder => ({
getProjects: builder.query<
IServerResponse<IProjectsViewModel>,
{
index: number;
size: number;
field: string | null;
order: string | null;
search: string | null;
filter: number | null;
statuses: string | null;
categories: string | null;
}
>({
query: ({ index, size, field, order, search, filter, statuses, categories }) => {
const params = new URLSearchParams({
index: index.toString(),
size: size.toString(),
field: field || '',
order: order || '',
search: search || '',
filter: filter?.toString() || '',
statuses: statuses || '',
categories: categories || '',
});
return `${rootUrl}?${params.toString()}`;
},
providesTags: result => [{ type: 'Projects', id: 'LIST' }],
}),
getProject: builder.query<IServerResponse<IProjectViewModel>, string>({
query: id => `${rootUrl}/${id}`,
providesTags: (result, error, id) => [{ type: 'Projects', id }],
}),
createProject: builder.mutation<IServerResponse<IProjectViewModel>, IProjectViewModel>({
query: project => ({
url: rootUrl,
method: 'POST',
body: project,
}),
invalidatesTags: [{ type: 'Projects', id: 'LIST' }],
}),
updateProject: builder.mutation<
IServerResponse<IProjectViewModel>,
{ id: string; project: IProjectViewModel }
>({
query: ({ id, project }) => ({
url: `${rootUrl}/${id}`,
method: 'PUT',
body: project,
}),
invalidatesTags: (result, error, { id }) => [{ type: 'Projects', id }],
}),
deleteProject: builder.mutation<IServerResponse<IProjectViewModel>, string>({
query: id => ({
url: `${rootUrl}/${id}`,
method: 'DELETE',
}),
invalidatesTags: [{ type: 'Projects', id: 'LIST' }],
}),
toggleFavoriteProject: builder.mutation<IServerResponse<IProjectsViewModel>, string>({
query: id => ({
url: `${rootUrl}/favorite/${id}`,
method: 'GET',
}),
invalidatesTags: (result, error, id) => [{ type: 'Projects', id }],
}),
toggleArchiveProject: builder.mutation<IServerResponse<any>, string>({
query: id => ({
url: `${rootUrl}/archive/${id}`,
method: 'GET',
}),
invalidatesTags: [{ type: 'Projects', id: 'LIST' }],
}),
toggleArchiveProjectForAll: builder.mutation<IServerResponse<any>, string>({
query: id => ({
url: `${rootUrl}/archive-all/${id}`,
method: 'GET',
}),
invalidatesTags: [{ type: 'Projects', id: 'LIST' }],
}),
getProjectCategories: builder.query<IProjectCategory[], void>({
query: () => `${rootUrl}/categories`,
providesTags: ['ProjectCategories'],
}),
getProjectMembers: builder.query<
IServerResponse<IProjectMembersViewModel>,
{
id: string;
index: number;
size: number;
field: string | null;
order: string | null;
search: string | null;
}
>({
query: ({ id, index, size, field, order, search }) => {
const params = new URLSearchParams({
index: index.toString(),
size: size.toString(),
field: field || '',
order: order || '',
search: search || '',
});
return `${rootUrl}/members/${id}?${params.toString()}`;
},
providesTags: (result, error, { id }) => [{ type: 'ProjectMembers', id }],
}),
}),
});
export const {
useGetProjectsQuery,
useGetProjectQuery,
useCreateProjectMutation,
useUpdateProjectMutation,
useDeleteProjectMutation,
useToggleFavoriteProjectMutation,
useToggleArchiveProjectMutation,
useToggleArchiveProjectForAllMutation,
useGetProjectCategoriesQuery,
useGetProjectMembersQuery,
} = projectsApi;

View File

@@ -0,0 +1,175 @@
import { toQueryString } from '@/utils/toQueryString';
import { API_BASE_URL } from '@/shared/constants';
import { ITimeLogBreakdownReq } from '@/types/reporting/reporting.types';
const rootUrl = `${import.meta.env.VITE_API_URL}${API_BASE_URL}/reporting-export`;
export const reportingExportApiService = {
exportOverviewProjectsByTeam(teamId: string, teamName: string) {
const params = toQueryString({
team_id: teamId,
team_name: teamName,
});
window.location.href = `${rootUrl}/overview/projects${params}`;
},
exportOverviewMembersByTeam(teamId: string, teamName: string) {
const params = toQueryString({
team_id: teamId,
team_name: teamName,
});
window.location.href = `${rootUrl}/overview/members${params}`;
},
exportAllocation(
archived: boolean,
teams: string[],
projects: string[],
duration: string | undefined,
date_range: string[],
billable = true,
nonBillable = true
) {
const teamsString = teams?.join(',');
const projectsString = projects.join(',');
window.location.href = `${rootUrl}/allocation/export${toQueryString({
teams: teamsString,
projects: projectsString,
duration: duration,
date_range: date_range,
include_archived: archived,
billable,
nonBillable,
})}`;
},
exportProjects(teamName: string | undefined) {
const params = toQueryString({
team_name: teamName,
});
window.location.href = `${rootUrl}/projects/export${params}`;
},
exportMembers(
teamName: string | undefined,
duration: string | null | undefined,
date_range: string[] | null,
archived: boolean
) {
const params = toQueryString({
team_name: teamName,
duration: duration,
date_range: date_range,
archived: archived,
});
window.location.href = `${rootUrl}/members/export${params}`;
},
exportProjectMembers(
projectId: string,
projectName: string,
teamName: string | null | undefined
) {
const params = toQueryString({
project_id: projectId,
project_name: projectName,
team_name: teamName ? teamName : null,
});
window.location.href = `${rootUrl}/project-members/export${params}`;
},
exportProjectTasks(projectId: string, projectName: string, teamName: string | null | undefined) {
const params = toQueryString({
project_id: projectId,
project_name: projectName,
team_name: teamName ? teamName : null,
});
window.location.href = `${rootUrl}/project-tasks/export${params}`;
},
exportMemberProjects(
memberId: string,
teamId: string | null,
memberName: string,
teamName: string | null | undefined,
archived: boolean
) {
const params = toQueryString({
team_member_id: memberId,
team_id: teamId,
team_member_name: memberName,
team_name: teamName ? teamName : null,
archived: archived,
});
window.location.href = `${rootUrl}/member-projects/export${params}`;
},
exportMemberTasks(
memberId: string,
memberName: string,
teamName: string | null | undefined,
body: any | null
) {
const params = toQueryString({
team_member_id: memberId,
team_member_name: memberName,
team_name: teamName ? teamName : null,
duration: body.duration,
date_range: body.date_range,
only_single_member: body.only_single_member ? body.only_single_member : false,
archived: body.archived ? body.archived : false,
});
window.location.href = `${rootUrl}/member-tasks/export${params}`;
},
exportFlatTasks(
memberId: string,
memberName: string,
projectId: string | null,
projectName: string | null
) {
const params = toQueryString({
team_member_id: memberId,
team_member_name: memberName,
project_id: projectId,
project_name: projectName,
});
window.location.href = `${rootUrl}/flat-tasks/export${params}`;
},
exportProjectTimeLogs(body: ITimeLogBreakdownReq, projectName: string) {
const params = toQueryString({
id: body.id,
duration: body.duration,
date_range: body.date_range,
project_name: projectName,
});
window.location.href = `${rootUrl}/projects-time-log-breakdown/export${params}`;
},
exportMemberTimeLogs(body: any | null) {
const params = toQueryString({
team_member_id: body.team_member_id,
team_id: body.team_id,
duration: body.duration,
date_range: body.date_range,
member_name: body.member_name,
team_name: body.team_name,
archived: body.archived ? body.archived : false,
});
window.location.href = `${rootUrl}/member-time-log-breakdown/export${params}`;
},
exportMemberActivityLogs(body: any | null) {
const params = toQueryString({
team_member_id: body.team_member_id,
team_id: body.team_id,
duration: body.duration,
date_range: body.date_range,
member_name: body.member_name,
team_name: body.team_name,
archived: body.archived ? body.archived : false,
});
window.location.href = `${rootUrl}/member-activity-log-breakdown/export${params}`;
},
};

View File

@@ -0,0 +1,18 @@
import { IServerResponse } from '@/types/common.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';
const rootUrl = `${API_BASE_URL}/reporting/members`;
export const reportingMembersApiService = {
getMembers: async (
body: any
): Promise<IServerResponse<IRPTMembersViewModel>> => {
const q = toQueryString(body);
const url = `${rootUrl}${q}`;
const response = await apiClient.get<IServerResponse<IRPTMembersViewModel>>(url);
return response.data;
},
};

View File

@@ -0,0 +1,43 @@
import { IServerResponse } from '@/types/common.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';
import { ITaskListGroup } from '@/types/tasks/taskList.types';
const rootUrl = `${API_BASE_URL}/reporting/projects`;
export const reportingProjectsApiService = {
getProjects: async (
body: IGetProjectsRequestBody
): Promise<IServerResponse<IRPTProjectsViewModel>> => {
const q = toQueryString(body);
const url = `${rootUrl}${q}`;
const response = await apiClient.get<IServerResponse<IRPTProjectsViewModel>>(url);
return response.data;
},
getProjectOverview: async (
projectId: string
): Promise<IServerResponse<IRPTOverviewProjectInfo>> => {
const url = `${API_BASE_URL}/reporting/overview/project/info/${projectId}`;
const response = await apiClient.get<IServerResponse<IRPTOverviewProjectInfo>>(url);
return response.data;
},
getProjectMembers: async (
projectId: string
): Promise<IServerResponse<IRPTOverviewProjectMember[]>> => {
const url = `${API_BASE_URL}/reporting/overview/project/members/${projectId}`;
const response = await apiClient.get<IServerResponse<IRPTOverviewProjectMember[]>>(url);
return response.data;
},
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);
return response.data;
},
};

View File

@@ -0,0 +1,301 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '../api-client';
import { API_BASE_URL } from '@/shared/constants';
import { toQueryString } from '@/utils/toQueryString';
import { IProjectViewModel } from '@/types/project/projectViewModel.types';
import {
IProjectLogsBreakdown,
IRPTMember,
IRPTOverviewMemberInfo,
IRPTOverviewProjectInfo,
IRPTOverviewProjectMember,
IRPTOverviewStatistics,
IRPTOverviewTeamInfo,
IRPTProject,
IRPTProjectsViewModel,
IRPTReportingMemberTask,
IRPTTeam,
ITimeLogBreakdownReq,
} from '@/types/reporting/reporting.types';
import { IReportingInfo } from '@/types/reporting/reporting.types';
import {
IMemberProjectsResonse,
IMemberTaskStatGroupResonse,
IRPTMemberProject,
IRPTMemberResponse,
IRPTTimeMember,
IRPTTimeProject,
ISingleMemberActivityLogs,
ISingleMemberLogs,
} from '@/types/reporting/reporting.types';
import { ITaskListGroup } from '@/types/tasks/taskList.types';
import {
ISelectableCategory,
ISelectableProject,
} from '../../types/reporting/reporting-filters.types';
import { IAllocationViewModel } from '@/types/reporting/reporting-allocation.types';
const rootUrl = `${API_BASE_URL}/reporting`;
export const reportingApiService = {
getProject: async (id: string): Promise<IServerResponse<IProjectViewModel>> => {
const url = `${rootUrl}/${id}`;
const response = await apiClient.get<IServerResponse<IProjectViewModel>>(`${url}`);
return response.data;
},
getInfo: async (): Promise<IServerResponse<IReportingInfo>> => {
const url = `${rootUrl}/info`;
const response = await apiClient.get<IServerResponse<IReportingInfo>>(url);
return response.data;
},
getOverviewStatistics: async (
includeArchived = false
): Promise<IServerResponse<IRPTOverviewStatistics>> => {
const q = toQueryString({ archived: includeArchived });
const url = `${rootUrl}/overview/statistics${q}`;
const response = await apiClient.get<IServerResponse<IRPTOverviewStatistics>>(url);
return response.data;
},
getOverviewTeams: async (includeArchived = true): Promise<IServerResponse<IRPTTeam[]>> => {
const q = toQueryString({ archived: includeArchived });
const url = `${rootUrl}/overview/teams${q}`;
const response = await apiClient.get<IServerResponse<IRPTTeam[]>>(url);
return response.data;
},
getOverviewProjects: async (
body: any | null = null
): Promise<IServerResponse<IRPTProjectsViewModel>> => {
const q = toQueryString(body);
const url = `${rootUrl}/overview/projects${q}`;
const response = await apiClient.get<IServerResponse<IRPTProjectsViewModel>>(url);
return response.data;
},
getOverviewProjectsByTeam: async (
teamId: string,
teamMemberId?: string
): Promise<IServerResponse<IRPTProject[]>> => {
const q = toQueryString({ member: teamMemberId || null });
const url = `${rootUrl}/overview/projects/${teamId}${q}`;
const response = await apiClient.get<IServerResponse<IRPTProject[]>>(url);
return response.data;
},
getOverviewMembersByTeam: async (
teamId: string,
archived: boolean
): Promise<IServerResponse<IRPTMember[]>> => {
const q = toQueryString({ archived });
const url = `${rootUrl}/overview/members/${teamId}${q}`;
const response = await apiClient.get<IServerResponse<IRPTMember[]>>(url);
return response.data;
},
getTeamInfo: async (
teamId: string,
archived = false
): Promise<IServerResponse<IRPTOverviewTeamInfo>> => {
const q = toQueryString({ archived });
const url = `${rootUrl}/overview/team/info/${teamId}${q}`;
const response = await apiClient.get<IServerResponse<IRPTOverviewTeamInfo>>(url);
return response.data;
},
getProjectInfo: async (projectId: string): Promise<IServerResponse<IRPTOverviewProjectInfo>> => {
const url = `${rootUrl}/overview/project/info/${projectId}`;
const response = await apiClient.get<IServerResponse<IRPTOverviewProjectInfo>>(url);
return response.data;
},
getMemberInfo: async (
body: any | null = null
): Promise<IServerResponse<IRPTOverviewMemberInfo>> => {
const q = toQueryString(body);
const url = `${rootUrl}/overview/member/info/${q}`;
const response = await apiClient.get<IServerResponse<IRPTOverviewMemberInfo>>(url);
return response.data;
},
getTeamMemberInfo: async (
body: any | null = null
): Promise<IServerResponse<IRPTOverviewMemberInfo>> => {
const q = toQueryString(body);
const url = `${rootUrl}/overview/team-member/info/${q}`;
const response = await apiClient.get<IServerResponse<IRPTOverviewMemberInfo>>(url);
return response.data;
},
getProjectMembers: async (
projectId: string
): Promise<IServerResponse<IRPTOverviewProjectMember[]>> => {
const url = `${rootUrl}/overview/project/members/${projectId}`;
const response = await apiClient.get<IServerResponse<IRPTOverviewProjectMember[]>>(url);
return response.data;
},
getTasks: async (
projectId: string,
groupBy: string
): Promise<IServerResponse<ITaskListGroup[]>> => {
const q = toQueryString({ group: groupBy });
const url = `${rootUrl}/overview/project/tasks/${projectId}${q}`;
const response = await apiClient.get<IServerResponse<ITaskListGroup[]>>(url);
return response.data;
},
getTasksByMember: async (
teamMemberId: string,
projectId: string | null = null,
isMultiple: boolean,
teamId: string | null = null,
additionalBody: any | null = null
): Promise<IServerResponse<IRPTReportingMemberTask[]>> => {
const q = toQueryString({
project: projectId || null,
is_multiple: isMultiple,
teamId,
only_single_member: additionalBody.only_single_member,
duration: additionalBody.duration,
date_range: additionalBody.date_range,
archived: additionalBody.archived,
});
const url = `${rootUrl}/overview/member/tasks/${teamMemberId}${q}`;
const response = await apiClient.get<IServerResponse<IRPTReportingMemberTask[]>>(url);
return response.data;
},
getProjects: async (body: any | null = null): Promise<IServerResponse<IRPTProjectsViewModel>> => {
const q = toQueryString(body);
const url = `${rootUrl}/projects${q}`;
const response = await apiClient.get<IServerResponse<IRPTProjectsViewModel>>(url);
return response.data;
},
getProjectTimeLogs: async (
body: ITimeLogBreakdownReq
): Promise<IServerResponse<IProjectLogsBreakdown[]>> => {
const url = `${rootUrl}/project-timelogs`;
const response = await apiClient.post<IServerResponse<IProjectLogsBreakdown[]>>(url, body);
return response.data;
},
getCategories: async (
selectedTeams: string[]
): Promise<IServerResponse<ISelectableCategory[]>> => {
const url = `${rootUrl}/allocation/categories`;
const response = await apiClient.post<IServerResponse<ISelectableCategory[]>>(
url,
selectedTeams
);
return response.data;
},
getAllocationProjects: async (
selectedTeams: string[],
categories: string[],
isNoCategory: boolean
): Promise<IServerResponse<ISelectableProject[]>> => {
const body = {
selectedTeams: selectedTeams,
selectedCategories: categories,
noCategoryIncluded: isNoCategory,
};
const url = `${rootUrl}/allocation/projects`;
const response = await apiClient.post<IServerResponse<ISelectableProject[]>>(url, body);
return response.data;
},
getAllocationData: async (
body = {},
archived = false
): Promise<IServerResponse<IAllocationViewModel>> => {
const q = toQueryString({ archived });
const url = `${rootUrl}/allocation${q}`;
const response = await apiClient.post<IServerResponse<IAllocationViewModel>>(url, body);
return response.data;
},
getMembers: async (body: any | null = null): Promise<IServerResponse<IRPTMemberResponse>> => {
const q = toQueryString(body);
const url = `${rootUrl}/members${q}`;
const response = await apiClient.get<IServerResponse<IRPTMemberResponse>>(url);
return response.data;
},
getMemberProjects: async (
body: any | null = null
): Promise<IServerResponse<IRPTMemberProject[]>> => {
const q = toQueryString(body);
const url = `${rootUrl}/member-projects${q}`;
const response = await apiClient.get<IServerResponse<IRPTMemberProject[]>>(url);
return response.data;
},
getProjectTimeSheets: async (
body = {},
archived = false
): Promise<IServerResponse<IRPTTimeProject[]>> => {
const q = toQueryString({ archived });
const url = `${rootUrl}/time-reports/projects${q}`;
const response = await apiClient.post<IServerResponse<IRPTTimeProject[]>>(url, body);
return response.data;
},
getProjectEstimatedVsActual: async (
body = {},
archived = false
): Promise<IServerResponse<IRPTTimeProject[]>> => {
const q = toQueryString({ archived });
const url = `${rootUrl}/time-reports/estimated-vs-actual${q}`;
const response = await apiClient.post<IServerResponse<IRPTTimeProject[]>>(url, body);
return response.data;
},
getMemberTimeSheets: async (
body = {},
archived = false
): Promise<IServerResponse<IRPTTimeMember[]>> => {
const q = toQueryString({ archived });
const url = `${rootUrl}/time-reports/members${q}`;
const response = await apiClient.post<IServerResponse<IRPTTimeMember[]>>(url, body);
return response.data;
},
getSingleMemberActivities: async (
body: any | null = null
): Promise<IServerResponse<ISingleMemberActivityLogs[]>> => {
const url = `${rootUrl}/members/single-member-activities`;
const response = await apiClient.post<IServerResponse<ISingleMemberActivityLogs[]>>(url, body);
return response.data;
},
getSingleMemberTimeLogs: async (
body: any | null = null
): Promise<IServerResponse<ISingleMemberLogs[]>> => {
const url = `${rootUrl}/members/single-member-timelogs`;
const response = await apiClient.post<IServerResponse<ISingleMemberLogs[]>>(url, body);
return response.data;
},
getMemberTasksStats: async (
body: any | null = null
): Promise<IServerResponse<IMemberTaskStatGroupResonse>> => {
const q = toQueryString(body);
const url = `${rootUrl}/members/single-member-task-stats${q}`;
const response = await apiClient.get<IServerResponse<IMemberTaskStatGroupResonse>>(url);
return response.data;
},
getSingleMemberProjects: async (
body: any | null = null
): Promise<IServerResponse<IMemberProjectsResonse>> => {
const q = toQueryString(body);
const url = `${rootUrl}/members/single-member-projects${q}`;
const response = await apiClient.get<IServerResponse<IMemberProjectsResonse>>(url);
return response.data;
},
};

View File

@@ -0,0 +1,44 @@
import { API_BASE_URL } from '@/shared/constants';
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';
const rootUrl = `${API_BASE_URL}/reporting`;
export const reportingTimesheetApiService = {
getTimeSheetData: async (body = {}, archived = false): Promise<IServerResponse<IAllocationViewModel>> => {
const q = toQueryString({ archived });
const response = await apiClient.post(`${rootUrl}/allocation/${q}`, body);
return response.data;
},
getAllocationProjects: async (body = {}) => {
const response = await apiClient.post(`${rootUrl}/allocation/allocation-projects`, { body });
return response.data;
},
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[]>> => {
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[]>> => {
const response = await apiClient.post(`${rootUrl}/project-timelogs`, body);
return response.data;
},
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

@@ -0,0 +1,60 @@
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';
const rootUrl = `${API_BASE_URL}/schedule-gannt-v2`;
export const scheduleAPIService = {
fetchScheduleSettings: async (): Promise<IServerResponse<Settings>> => {
const response = await apiClient.get<IServerResponse<Settings>>(`${rootUrl}/settings`);
return response.data;
},
updateScheduleSettings: async ({
workingDays,
workingHours,
}: {
workingDays: string[];
workingHours: number;
}): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(`${rootUrl}/settings`, {
workingDays,
workingHours,
});
return response.data;
},
fetchScheduleDates: async ({
type,
date,
}: {
type: string;
date: string;
}): Promise<IServerResponse<DateList>> => {
const response = await apiClient.get<IServerResponse<DateList>>(
`${rootUrl}/dates/${date}/${type}`
);
return response.data;
},
fetchScheduleMembers: async (): Promise<IServerResponse<Member[]>> => {
const response = await apiClient.get<IServerResponse<Member[]>>(`${rootUrl}/members`);
return response.data;
},
fetchMemberProjects: async ({ id }: { id: string }): Promise<IServerResponse<Project>> => {
const response = await apiClient.get<IServerResponse<Project>>(`${rootUrl}/members/projects/${id}`);
return response.data;
},
submitScheduleData: async ({
schedule
}: {
schedule: ScheduleData
}): Promise<IServerResponse<any>> => {
const response = await apiClient.post<IServerResponse<any>>(`${rootUrl}/schedule`, schedule);
return response.data;
}
};

View File

@@ -0,0 +1,54 @@
import { IServerResponse } from '@/types/common.types';
import { API_BASE_URL } from '@/shared/constants';
import { IProjectCategory, IProjectCategoryViewModel } from '@/types/project/projectCategory.types';
import apiClient from '@api/api-client';
const rootUrl = `${API_BASE_URL}/project-categories`;
export const categoriesApiService = {
getCategories: async (): Promise<IServerResponse<IProjectCategoryViewModel[]>> => {
const response = await apiClient.get<IServerResponse<IProjectCategoryViewModel[]>>(rootUrl);
return response.data;
},
getCategoriesByTeam: async (
id: string
): Promise<IServerResponse<IProjectCategoryViewModel[]>> => {
const response = await apiClient.get<IServerResponse<IProjectCategoryViewModel[]>>(
`${rootUrl}/${id}`
);
return response.data;
},
getCategoriesByOrganization: async (): Promise<IServerResponse<IProjectCategoryViewModel[]>> => {
const response = await apiClient.get<IServerResponse<IProjectCategoryViewModel[]>>(
`${rootUrl}/org-categories`
);
return response.data;
},
createCategory: async (
category: Partial<IProjectCategory>
): Promise<IServerResponse<IProjectCategoryViewModel>> => {
const response = await apiClient.post<IServerResponse<IProjectCategoryViewModel>>(
rootUrl,
category
);
return response.data;
},
updateCategory: async (
category: IProjectCategoryViewModel
): Promise<IServerResponse<IProjectCategoryViewModel>> => {
const response = await apiClient.put<IServerResponse<IProjectCategoryViewModel>>(
`${rootUrl}/${category.id}`,
category
);
return response.data;
},
deleteCategory: async (id: string): Promise<IServerResponse<string>> => {
const response = await apiClient.delete<IServerResponse<string>>(`${rootUrl}/${id}`);
return response.data;
},
};

View File

@@ -0,0 +1,44 @@
import apiClient from '@api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { IJobTitle, IJobTitlesViewModel } from '@/types/job.types';
import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/job-titles`;
export const jobTitlesApiService = {
async getJobTitles(
index: number,
size: number,
field: string | null,
order: string | null,
search?: string | null
): Promise<IServerResponse<IJobTitlesViewModel>> {
const s = encodeURIComponent(search || '');
const queryString = toQueryString({ index, size, field, order, search: s });
const response = await apiClient.get<IServerResponse<IJobTitlesViewModel>>(
`${rootUrl}${queryString}`
);
return response.data;
},
async getJobTitleById(id: string): Promise<IServerResponse<IJobTitle>> {
const response = await apiClient.get<IServerResponse<IJobTitle>>(`${rootUrl}/${id}`);
return response.data;
},
async createJobTitle(body: IJobTitle): Promise<IServerResponse<IJobTitle>> {
const response = await apiClient.post<IServerResponse<IJobTitle>>(rootUrl, body);
return response.data;
},
async updateJobTitle(id: string, body: IJobTitle): Promise<IServerResponse<IJobTitle>> {
const response = await apiClient.put<IServerResponse<IJobTitle>>(`${rootUrl}/${id}`, body);
return response.data;
},
async deleteJobTitle(id: string): Promise<IServerResponse<void>> {
const response = await apiClient.delete<IServerResponse<void>>(`${rootUrl}/${id}`);
return response.data;
},
};

View File

@@ -0,0 +1,39 @@
import apiClient from '@api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { ITaskLabel } from '@/types/label.type';
import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/labels`;
export const labelsApiService = {
getLabels: async (projectId: string | null = null): Promise<IServerResponse<ITaskLabel>> => {
const q = toQueryString({ project: projectId });
const response = await apiClient.get<IServerResponse<ITaskLabel>>(`${rootUrl}${q}`);
return response.data;
},
getLabelsByTaskId: async (taskId: string): Promise<IServerResponse<ITaskLabel>> => {
const response = await apiClient.get<IServerResponse<ITaskLabel>>(`${rootUrl}/tasks/${taskId}`);
return response.data;
},
getByProjectId: async (projectId: string): Promise<IServerResponse<ITaskLabel>> => {
const response = await apiClient.get<IServerResponse<ITaskLabel>>(
`${rootUrl}/project/${projectId}`
);
return response.data;
},
updateColor: async (id: string, color: string): Promise<IServerResponse<ITaskLabel>> => {
const response = await apiClient.put<IServerResponse<ITaskLabel>>(`${rootUrl}/tasks/${id}`, {
color,
});
return response.data;
},
deleteLabel: async (id: string): Promise<IServerResponse<void>> => {
const response = await apiClient.delete<IServerResponse<void>>(`${rootUrl}/${id}`);
return response.data;
},
};

View File

@@ -0,0 +1,18 @@
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { ITimezone } from '@/types/settings/timezone.types';
import apiClient from '@api/api-client';
const rootUrl = `${API_BASE_URL}/timezones`;
export const timezonesApiService = {
update: async <T>(body: any): Promise<IServerResponse<ITimezone[]>> => {
const response = await apiClient.put<IServerResponse<ITimezone[]>>(rootUrl, body);
return response.data;
},
get: async <T>(): Promise<IServerResponse<ITimezone[]>> => {
const response = await apiClient.get<IServerResponse<ITimezone[]>>(rootUrl);
return response.data;
},
};

View File

@@ -0,0 +1,71 @@
import apiClient from '@api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { IProfileSettings } from '@/types/settings/profile.types';
import { INotificationSettings } from '@/types/settings/notifications.types';
import {
IAccountSetupRequest,
IAccountSetupResponse,
} from '@/types/project-templates/project-templates.types';
import { ITeam } from '@/types/teams/team.type';
const rootUrl = `${API_BASE_URL}/settings`;
export const profileSettingsApiService = {
getProfile: async (): Promise<IServerResponse<IProfileSettings>> => {
const response = await apiClient.get<IServerResponse<IProfileSettings>>(`${rootUrl}/profile`);
return response.data;
},
updateProfile: async (body: IProfileSettings): Promise<IServerResponse<IProfileSettings>> => {
const response = await apiClient.put<IServerResponse<IProfileSettings>>(
`${rootUrl}/profile`,
body
);
return response.data;
},
getNotificationSettings: async (): Promise<IServerResponse<INotificationSettings>> => {
const response = await apiClient.get<IServerResponse<INotificationSettings>>(
`${rootUrl}/notifications`
);
return response.data;
},
updateNotificationSettings: async (
body: INotificationSettings
): Promise<IServerResponse<INotificationSettings>> => {
const response = await apiClient.put<IServerResponse<INotificationSettings>>(
`${rootUrl}/notifications`,
body
);
return response.data;
},
setupAccount: async (
body: IAccountSetupRequest
): Promise<IServerResponse<IAccountSetupResponse>> => {
const response = await apiClient.post<IServerResponse<IAccountSetupResponse>>(
`${rootUrl}/setup`,
body
);
return response.data;
},
updateTeamName: async (id: string, body: ITeam): Promise<IServerResponse<ITeam>> => {
const response = await apiClient.put<IServerResponse<ITeam>>(`${rootUrl}/team-name/${id}`, body);
return response.data;
},
changePassword: async (body: {
new_password: string;
confirm_password: string;
password: string;
}): Promise<IServerResponse<any>> => {
const response = await apiClient.post<IServerResponse<any>>(
`${API_BASE_URL}/change-password`,
body
);
return response.data;
},
};

View File

@@ -0,0 +1,44 @@
import { API_BASE_URL } from '@/shared/constants';
import apiClient from '../api-client';
import { IServerResponse } from '@/types/common.types';
import {
ITaskTemplateGetResponse,
ITaskTemplatesGetResponse,
} from '@/types/settings/task-templates.types';
import { ITask } from '@/types/tasks/task.types';
import { IProjectTask } from '@/types/project/projectTasksViewModel.types';
const rootUrl = `${API_BASE_URL}/task-templates`;
export const taskTemplatesApiService = {
getTemplates: async (): Promise<IServerResponse<ITaskTemplatesGetResponse[]>> => {
const url = `${rootUrl}`;
const response = await apiClient.get<IServerResponse<ITaskTemplatesGetResponse[]>>(`${url}`);
return response.data;
},
getTemplate: async (id: string): Promise<IServerResponse<ITaskTemplateGetResponse>> => {
const url = `${rootUrl}/${id}`;
const response = await apiClient.get<IServerResponse<ITaskTemplateGetResponse>>(`${url}`);
return response.data;
},
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>> => {
const url = `${rootUrl}/${id}`;
const response = await apiClient.put<IServerResponse<ITask>>(`${url}`, body);
return response.data;
},
deleteTemplate: async (id: string): Promise<IServerResponse<ITask>> => {
const url = `${rootUrl}/${id}`;
const response = await apiClient.delete<IServerResponse<ITask>>(`${url}`);
return response.data;
},
importTemplate: async (id: string, body: IProjectTask[]): Promise<IServerResponse<ITask>> => {
const url = `${rootUrl}/import/${id}`;
const response = await apiClient.post<IServerResponse<ITask>>(`${url}`, body);
return response.data;
},
};

View File

@@ -0,0 +1,40 @@
import { IServerResponse } from '@/types/common.types';
import { API_BASE_URL } from '@/shared/constants';
import apiClient from '@api/api-client';
import { ITaskLabel } from '@/types/tasks/taskLabel.types';
const rootUrl = `${API_BASE_URL}/labels`;
export const labelsApiService = {
getLabels: async (): Promise<IServerResponse<ITaskLabel[]>> => {
const response = await apiClient.get<IServerResponse<ITaskLabel[]>>(`${rootUrl}`);
return response.data;
},
getPriorityByTask: async (taskId: string): Promise<IServerResponse<ITaskLabel[]>> => {
const response = await apiClient.get<IServerResponse<ITaskLabel[]>>(
`${rootUrl}/tasks/${taskId}`
);
return response.data;
},
getPriorityByProject: async (projectId: string): Promise<IServerResponse<ITaskLabel[]>> => {
const response = await apiClient.get<IServerResponse<ITaskLabel[]>>(
`${rootUrl}/project/${projectId}`
);
return response.data;
},
updateColor: async (labelId: string, color: string): Promise<IServerResponse<ITaskLabel>> => {
const response = await apiClient.put<IServerResponse<ITaskLabel>>(
`${rootUrl}/tasks/${labelId}/color`,
{ color }
);
return response.data;
},
deleteById: async (labelId: string): Promise<IServerResponse<void>> => {
const response = await apiClient.delete<IServerResponse<void>>(`${rootUrl}/team/${labelId}`);
return response.data;
},
};

View File

@@ -0,0 +1,72 @@
import apiClient from '@/api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { ITaskPhase } from '@/types/tasks/taskPhase.types';
import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/task-phases`;
interface UpdateSortOrderBody {
from_index: number;
to_index: number;
phases: ITaskPhase[];
project_id: string;
}
export const phasesApiService = {
addPhaseOption: async (projectId: string) => {
const q = toQueryString({ id: projectId, current_project_id: projectId });
const response = await apiClient.post<IServerResponse<ITaskPhase>>(`${rootUrl}${q}`);
return response.data;
},
getPhasesByProjectId: async (projectId: string) => {
const q = toQueryString({ id: projectId });
const response = await apiClient.get<IServerResponse<ITaskPhase[]>>(`${rootUrl}${q}`);
return response.data;
},
deletePhaseOption: async (phaseOptionId: string, projectId: string) => {
const q = toQueryString({ id: projectId, current_project_id: projectId });
const response = await apiClient.delete<IServerResponse<ITaskPhase>>(
`${rootUrl}/${phaseOptionId}${q}`
);
return response.data;
},
updatePhaseColor: async (projectId: string, body: ITaskPhase) => {
const q = toQueryString({ id: projectId, current_project_id: projectId });
const response = await apiClient.put<IServerResponse<ITaskPhase>>(
`${rootUrl}/change-color/${body.id}${q}`,
body
);
return response.data;
},
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}`,
body
);
return response.data;
},
updatePhaseOrder: async (projectId: string, body: UpdateSortOrderBody) => {
const q = toQueryString({ id: projectId, current_project_id: projectId });
const response = await apiClient.put<IServerResponse<ITaskPhase[]>>(
`${rootUrl}/update-sort-order${q}`,
body
);
return response.data;
},
updateProjectPhaseLabel: async (projectId: string, phaseLabel: string) => {
const q = toQueryString({ id: projectId, current_project_id: projectId });
const response = await apiClient.put<IServerResponse<ITaskPhase>>(
`${rootUrl}/label/${projectId}${q}`,
{ name: phaseLabel }
);
return response.data;
},
};

View File

@@ -0,0 +1,22 @@
import { IServerResponse } from '@/types/common.types';
import { API_BASE_URL } from '@/shared/constants';
import { ITaskPrioritiesGetResponse, ITaskPriority } from '@/types/tasks/taskPriority.types';
import apiClient from '@api/api-client';
const rootUrl = `${API_BASE_URL}/task-priorities`;
export const priorityApiService = {
getPriorities: async (): Promise<IServerResponse<ITaskPrioritiesGetResponse[]>> => {
const response = await apiClient.get<IServerResponse<ITaskPrioritiesGetResponse[]>>(
`${rootUrl}`
);
return response.data;
},
getPriorityById: async (priorityId: string): Promise<IServerResponse<ITaskPriority>> => {
const response = await apiClient.get<IServerResponse<ITaskPriority>>(
`${rootUrl}/${priorityId}`
);
return response.data;
},
};

View File

@@ -0,0 +1,77 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '@api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import { ITaskStatus, ITaskStatusCategory } from '@/types/status.types';
import { ITaskStatusCreateRequest } from '@/types/tasks/task-status-create-request';
import { toQueryString } from '@/utils/toQueryString';
import { ITaskStatusUpdateModel } from '@/types/tasks/task-status-update-model.types';
const rootUrl = `${API_BASE_URL}/statuses`;
export const statusApiService = {
getStatuses: async (projectId: string): Promise<IServerResponse<ITaskStatus[]>> => {
const response = await apiClient.get<IServerResponse<ITaskStatus[]>>(
`${rootUrl}?project=${projectId}`
);
return response.data;
},
getStatusCategories: async (): Promise<IServerResponse<ITaskStatusCategory[]>> => {
const response = await apiClient.get<IServerResponse<ITaskStatusCategory[]>>(
`${rootUrl}/categories`
);
return response.data;
},
createStatus: async (
body: ITaskStatusCreateRequest,
currentProjectId: string
): Promise<IServerResponse<ITaskStatus>> => {
const q = toQueryString({ current_project_id: currentProjectId });
const response = await apiClient.post<IServerResponse<ITaskStatus>>(`${rootUrl}${q}`, body);
return response.data;
},
updateStatus: async (
statusId: string,
body: ITaskStatusUpdateModel,
currentProjectId: string
): Promise<IServerResponse<ITaskStatus>> => {
const q = toQueryString({ current_project_id: currentProjectId });
const response = await apiClient.put<IServerResponse<ITaskStatus>>(
`${rootUrl}/${statusId}${q}`,
body
);
return response.data;
},
updateNameOfStatus: async (
id: string,
body: ITaskStatusUpdateModel,
currentProjectId: string
): Promise<IServerResponse<ITaskStatus>> => {
const q = toQueryString({ current_project_id: currentProjectId });
const response = await apiClient.put<IServerResponse<ITaskStatus>>(
`${rootUrl}/name/${id}${q}`,
body
);
return response.data;
},
updateStatusOrder: async (
body: ITaskStatusCreateRequest,
currentProjectId: string
): Promise<IServerResponse<ITaskStatus>> => {
const q = toQueryString({ current_project_id: currentProjectId });
const response = await apiClient.put<IServerResponse<ITaskStatus>>(`${rootUrl}/order`, body);
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 });
const response = await apiClient.delete<IServerResponse<void>>(`${rootUrl}/${statusId}${q}`);
return response.data;
},
};

View File

@@ -0,0 +1,16 @@
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`;
export const subTasksApiService = {
getSubTasks: async (parentTaskId: string): Promise<IServerResponse<ISubTask[]>> => {
const response = await apiClient.get(`${root}/${parentTaskId}`);
return response.data;
},
};

View File

@@ -0,0 +1,15 @@
import { API_BASE_URL } from '@/shared/constants';
import apiClient from '../api-client';
import { IServerResponse } from '@/types/common.types';
import { IActivityLogsResponse } from '@/types/tasks/task-activity-logs-get-request';
const rootUrl = `${API_BASE_URL}/activity-logs`;
export const taskActivityLogsApiService = {
getActivityLogsByTaskId: async (
taskId: string
): Promise<IServerResponse<IActivityLogsResponse>> => {
const response = await apiClient.get(`${rootUrl}/${taskId}`);
return response.data;
},
};

View File

@@ -0,0 +1,46 @@
import { IServerResponse } from '@/types/common.types';
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';
import { toQueryString } from '@/utils/toQueryString';
const rootUrl = `${API_BASE_URL}/attachments`;
const taskAttachmentsApiService = {
createTaskAttachment: async (
body: ITaskAttachment
): Promise<IServerResponse<ITaskAttachmentViewModel>> => {
const response = await apiClient.post(`${rootUrl}/tasks`, body);
return response.data;
},
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[]>> => {
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 });
const response = await apiClient.get(`${rootUrl}/project/${projectId}${q}`);
return response.data;
},
deleteTaskAttachment: async (attachmentId: string): Promise<IServerResponse<void>> => {
const response = await apiClient.delete(`${rootUrl}/tasks/${attachmentId}`);
return response.data;
},
downloadTaskAttachment: async (id: string, filename: string): Promise<IServerResponse<any>> => {
const response = await apiClient.get(`${rootUrl}/download?id=${id}&file=${filename}`);
return response.data;
},
};
export default taskAttachmentsApiService;

View File

@@ -0,0 +1,44 @@
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';
const taskCommentsApiService = {
create: async (data: ITaskCommentsCreateRequest): Promise<IServerResponse<ITaskCommentsCreateRequest>> => {
const response = await apiClient.post(`${API_BASE_URL}/task-comments`, data);
return response.data;
},
getByTaskId: async (id: string): Promise<IServerResponse<ITaskCommentViewModel[]>> => {
const response = await apiClient.get(`${API_BASE_URL}/task-comments/${id}`);
return response.data;
},
update: async (id: string, body: ITaskComment): Promise<IServerResponse<ITaskComment>> => {
const response = await apiClient.put(`${API_BASE_URL}/task-comments/${id}`, body);
return response.data;
},
deleteAttachment: async (id: string, taskId: string): Promise<IServerResponse<ITaskComment>> => {
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}`);
return response.data;
},
delete: async (id: string, taskId: string): Promise<IServerResponse<ITaskComment>> => {
const response = await apiClient.delete(`${API_BASE_URL}/task-comments/${id}/${taskId}`);
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)}`);
return response.data;
},
};
export default taskCommentsApiService;

View File

@@ -0,0 +1,21 @@
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`;
export const taskDependenciesApiService = {
getTaskDependencies: async (taskId: string): Promise<IServerResponse<ITaskDependency[]>> => {
const response = await apiClient.get(`${rootUrl}/${taskId}`);
return response.data;
},
createTaskDependency: async (body: ITaskDependency): Promise<IServerResponse<ITaskDependency>> => {
const response = await apiClient.post(`${rootUrl}`, body);
return response.data;
},
deleteTaskDependency: async (dependencyId: string): Promise<IServerResponse<void>> => {
const response = await apiClient.delete(`${rootUrl}/${dependencyId}`);
return response.data;
},
};

View File

@@ -0,0 +1,77 @@
import apiClient from '@api/api-client';
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import { ITask } from '@/types/tasks/task.types';
import {
IBulkAssignMembersRequest,
IBulkAssignRequest,
IBulkTasksArchiveRequest,
IBulkTasksDeleteRequest,
IBulkTasksLabelsRequest,
IBulkTasksPhaseChangeRequest,
IBulkTasksPriorityChangeRequest,
IBulkTasksStatusChangeRequest,
} from '@/types/tasks/bulk-action-bar.types';
import { ITaskAssigneesUpdateResponse } from '@/types/tasks/task-assignee-update-response';
const rootUrl = `${API_BASE_URL}/tasks/bulk`;
export const taskListBulkActionsApiService = {
changeStatus: async (
body: IBulkTasksStatusChangeRequest,
projectId: string
): Promise<IServerResponse<{ failed_tasks: string[] }>> => {
const response = await apiClient.put(`${rootUrl}/status?project=${projectId}`, body);
return response.data;
},
changePriority: async (
body: IBulkTasksPriorityChangeRequest,
projectId: string
): Promise<IServerResponse<ITask>> => {
const response = await apiClient.put(`${rootUrl}/priority?project=${projectId}`, body);
return response.data;
},
changePhase: async (
body: IBulkTasksPhaseChangeRequest,
projectId: string
): Promise<IServerResponse<ITask>> => {
const response = await apiClient.put(`${rootUrl}/phase?project=${projectId}`, body);
return response.data;
},
deleteTasks: async (
body: IBulkTasksDeleteRequest,
projectId: string
): Promise<IServerResponse<ITask>> => {
const response = await apiClient.put(`${rootUrl}/delete?project=${projectId}`, body);
return response.data;
},
archiveTasks: async (
body: IBulkTasksArchiveRequest,
unarchive = false
): Promise<IServerResponse<ITask>> => {
const response = await apiClient.put(
`${rootUrl}/archive?type=${unarchive ? 'unarchive' : 'archive'}&project=${body.project_id}`,
body
);
return response.data;
},
assignTasks: async (
body: IBulkAssignMembersRequest
): Promise<IServerResponse<ITaskAssigneesUpdateResponse>> => {
const response = await apiClient.put(`${rootUrl}/members?project=${body.project_id}`, body);
return response.data;
},
assignToMe: async (
body: IBulkAssignRequest
): Promise<IServerResponse<ITaskAssigneesUpdateResponse>> => {
const response = await apiClient.put(`${rootUrl}/assign-me?project=${body.project_id}`, body);
return response.data;
},
assignLabels: async (
body: IBulkTasksLabelsRequest,
projectId: string
): Promise<IServerResponse<ITask>> => {
const response = await apiClient.put(`${rootUrl}/label?project=${projectId}`, body);
return response.data;
},
};

View File

@@ -0,0 +1,32 @@
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`;
export const taskTimeLogsApiService = {
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>> => {
const response = await apiClient.delete(`${rootUrl}/${id}?task=${taskId}`);
return response.data;
},
create: async (body: {}): Promise<IServerResponse<ITaskLogViewModel>> => {
const response = await apiClient.post(`${rootUrl}`, body);
return response.data;
},
update: async (id: string, body: {}): Promise<IServerResponse<ITaskLogViewModel>> => {
const response = await apiClient.put(`${rootUrl}/${id}`, body);
return response.data;
},
exportToExcel(taskId: string) {
window.location.href = `${import.meta.env.VITE_API_URL}${API_BASE_URL}/task-time-log/export/${taskId}`;
},
};

View File

@@ -0,0 +1,69 @@
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,
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
});
return response.data;
},
createCustomColumn: async (
projectId: string,
columnData: {
name: string;
key: string;
field_type: string;
width: number;
is_visible: boolean;
configuration: any;
}
): Promise<IServerResponse<any>> => {
const response = await apiClient.post('/api/v1/custom-columns', {
project_id: projectId,
...columnData
});
return response.data;
},
updateCustomColumn: async (
columnId: string,
columnData: {
name: string;
field_type: string;
width: number;
is_visible: boolean;
configuration: any;
}
): Promise<IServerResponse<any>> => {
const response = await apiClient.put(`/api/v1/custom-columns/${columnId}`, columnData);
return response.data;
},
deleteCustomColumn: async (columnId: string): Promise<IServerResponse<any>> => {
const response = await apiClient.delete(`/api/v1/custom-columns/${columnId}`);
return response.data;
},
updateCustomColumnVisibility: async (
projectId: string,
item: ITaskListColumn
): Promise<IServerResponse<ITaskListColumn>> => {
const response = await apiClient.put(`/api/v1/custom-columns/project/${projectId}/columns`, item);
return response.data;
}
};

View File

@@ -0,0 +1,122 @@
import {
ITaskListColumn,
ITaskListGroup,
ITaskListMemberFilter,
} from '@/types/tasks/taskList.types';
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 { ITeamMemberViewModel } from '@/types/teamMembers/teamMembersGetResponse.types';
import { ITaskFormViewModel, ITaskViewModel } from '@/types/tasks/task.types';
import { InlineMember } from '@/types/teamMembers/inlineMember.types';
const rootUrl = `${API_BASE_URL}/tasks`;
export interface ITaskListConfigV2 {
id: string;
field: string | null;
order: string | null;
search: string | null;
statuses: string | null;
members: string | null;
projects: string | null;
labels?: string | null;
priorities?: string | null;
archived?: boolean;
count?: boolean;
parent_task?: string;
group?: string;
isSubtasksInclude: boolean;
}
export const tasksApiService = {
getTaskList: async (config: ITaskListConfigV2): Promise<IServerResponse<ITaskListGroup[]>> => {
const q = toQueryString(config);
const response = await apiClient.get(`${rootUrl}/list/v2/${config.id}${q}`);
return response.data;
},
fetchTaskAssignees: async (
projectId: string
): Promise<IServerResponse<ITeamMemberViewModel[]>> => {
const response = await apiClient.get(`${rootUrl}/assignees/${projectId}`);
return response.data;
},
fetchTaskListColumns: async (projectId: string): Promise<IServerResponse<ITaskListColumn[]>> => {
const response = await apiClient.get(`${rootUrl}/list/columns/${projectId}`);
return response.data;
},
getFormViewModel: async (
taskId: string | null,
projectId: string | null
): Promise<IServerResponse<ITaskFormViewModel>> => {
const params = [];
if (taskId) params.push(`task_id=${taskId}`);
if (projectId) params.push(`project_id=${projectId}`);
const q = params.length ? `?${params.join('&')}` : '';
const response = await apiClient.get(`${rootUrl}/info${q}`);
return response.data;
},
deleteTask: async (taskId: string): Promise<IServerResponse<void>> => {
const response = await apiClient.delete(`${rootUrl}/${taskId}`);
return response.data;
},
toggleColumnVisibility: async (
projectId: string,
item: ITaskListColumn
): Promise<IServerResponse<ITaskListColumn>> => {
const response = await apiClient.put(`${rootUrl}/list/columns/${projectId}`, item);
return response.data;
},
getSubscribers: async (taskId: string): Promise<IServerResponse<InlineMember[]>> => {
const response = await apiClient.get(`${rootUrl}/subscribers/${taskId}`);
return response.data;
},
convertToSubtask: async (
taskId: string,
projectId: string,
parentTaskId: string,
groupBy: string,
toGroupId: string
): Promise<IServerResponse<void>> => {
const response = await apiClient.post(`${rootUrl}/convert-to-subtask`, {
id: taskId,
project_id: projectId,
parent_task_id: parentTaskId,
group_by: groupBy,
to_group_id: toGroupId,
});
return response.data;
},
convertToTask: async (taskId: string, projectId: string): Promise<IServerResponse<void>> => {
const response = await apiClient.post(`${rootUrl}/convert`, {
id: taskId,
project_id: projectId,
});
return response.data;
},
searchTask: async (
taskId: string,
projectId: string,
searchQuery: string
): Promise<IServerResponse<{ label: string; value: string }[]>> => {
const q = toQueryString({ taskId, projectId, searchQuery });
const response = await apiClient.get(`${rootUrl}/search${q}`);
return response.data;
},
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;
},
};

View File

@@ -0,0 +1,99 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '../api-client';
import { API_BASE_URL } from '@/shared/constants';
import { ITeamMemberCreateRequest } from '@/types/teamMembers/team-member-create-request';
import { ITeamMemberViewModel } from '@/types/teamMembers/teamMembersGetResponse.types';
import { ITeamMembersViewModel } from '@/types/teamMembers/teamMembersViewModel.types';
import { ITeamMember } from '@/types/teamMembers/teamMember.types';
const rootUrl = `${API_BASE_URL}/team-members`;
export const teamMembersApiService = {
createTeamMember: async (
body: ITeamMemberCreateRequest
): Promise<IServerResponse<ITeamMember>> => {
const response = await apiClient.post<IServerResponse<ITeamMember>>(`${rootUrl}`, body);
return response.data;
},
get: async (
index: number,
size: number,
field: string | null,
order: string | null,
search: string | null,
all = false
): Promise<IServerResponse<ITeamMembersViewModel>> => {
const s = encodeURIComponent(search || '');
const params = new URLSearchParams({
index: index.toString(),
size: size.toString(),
...(field && { field }),
...(order && { order }),
...(s && { search: s }),
...(all && { all: all.toString() }),
});
const response = await apiClient.get<IServerResponse<ITeamMembersViewModel>>(
`${rootUrl}?${params}`
);
return response.data;
},
getById: async (id: string): Promise<IServerResponse<ITeamMemberViewModel>> => {
const response = await apiClient.get<IServerResponse<ITeamMemberViewModel>>(`${rootUrl}/${id}`);
return response.data;
},
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() : ''}`
);
return response.data;
},
update: async (id: string, body: ITeamMemberCreateRequest): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(`${rootUrl}/${id}`, body);
return response.data;
},
delete: async (id: string): Promise<IServerResponse<any>> => {
const response = await apiClient.delete<IServerResponse<any>>(`${rootUrl}/${id}`);
return response.data;
},
getTeamMembersByProjectId: async (projectId: string): Promise<IServerResponse<any[]>> => {
const response = await apiClient.get<IServerResponse<any[]>>(`${rootUrl}/project/${projectId}`);
return response.data;
},
resendInvitation: async (id: string): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(`${rootUrl}/resend-invitation`, {
id,
});
return response.data;
},
toggleMemberActiveStatus: async (
id: string,
active: boolean,
email: string
): Promise<IServerResponse<any>> => {
const params = new URLSearchParams({
active: active.toString(),
email,
});
const response = await apiClient.get<IServerResponse<any>>(
`${rootUrl}/deactivate/${id}?${params}`
);
return response.data;
},
addTeamMember: async (
id: string,
body: ITeamMemberCreateRequest
): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(`${rootUrl}/add-member/${id}`, body);
return response.data;
},
};

View File

@@ -0,0 +1,51 @@
import { IServerResponse } from '@/types/common.types';
import apiClient from '../api-client';
import {
IAcceptTeamInvite,
ITeam,
ITeamActivateResponse,
ITeamGetResponse,
ITeamInvites,
} from '@/types/teams/team.type';
import { API_BASE_URL } from '@/shared/constants';
import { IOrganizationTeam } from '@/types/admin-center/admin-center.types';
const rootUrl = `${API_BASE_URL}/teams`;
export const teamsApiService = {
getTeams: async (): Promise<IServerResponse<ITeamGetResponse[]>> => {
const response = await apiClient.get<IServerResponse<ITeamGetResponse[]>>(
`${rootUrl}`
);
return response.data;
},
setActiveTeam: async (teamId: string): Promise<IServerResponse<ITeamActivateResponse>> => {
const response = await apiClient.put<IServerResponse<ITeamActivateResponse>>(
`${rootUrl}/activate`,
{ id: teamId }
);
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`
);
return response.data;
},
acceptInvitation: async (body: IAcceptTeamInvite): Promise<IServerResponse<ITeamInvites>> => {
const response = await apiClient.put<IServerResponse<ITeamInvites>>(`${rootUrl}`, body);
return response.data;
}
};