first commit
This commit is contained in:
73
frontend/app/utils/api/apiRequests/baseApiRequest.ts
Normal file
73
frontend/app/utils/api/apiRequests/baseApiRequest.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
"use server";
|
||||
|
||||
import { getValidAccessToken } from "ikoncomponents";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export interface ExtraOptionsProps {
|
||||
isAccessTokenRequird?: boolean;
|
||||
revalidatePaths?: string[];
|
||||
isReturnErrorResult?: boolean;
|
||||
}
|
||||
|
||||
export const baseApiRequest = async (
|
||||
url: string,
|
||||
init: RequestInit,
|
||||
extraOptions?: ExtraOptionsProps,
|
||||
) => {
|
||||
const headers = new Headers(init.headers);
|
||||
|
||||
if (!headers.get("Content-Type")) {
|
||||
headers.set("Content-Type", "application/json");
|
||||
}
|
||||
|
||||
if (extraOptions?.isAccessTokenRequird !== false) {
|
||||
const accessToken = await getValidAccessToken(
|
||||
process.env.NEXT_PUBLIC_IKON_API_URL || "",
|
||||
);
|
||||
|
||||
if (!accessToken?.trim()) {
|
||||
redirect("/login.html");
|
||||
}
|
||||
|
||||
headers.set("Authorization", `Bearer ${accessToken.trim()}`);
|
||||
}
|
||||
|
||||
const response = await fetch(url, {
|
||||
...init,
|
||||
headers,
|
||||
});
|
||||
|
||||
const contentType = response.headers.get("Content-Type");
|
||||
|
||||
if (!response.ok) {
|
||||
let body = "";
|
||||
try {
|
||||
body = contentType?.includes("application/json")
|
||||
? await response.json()
|
||||
: await response.text();
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
const message =
|
||||
typeof body === "string"
|
||||
? body
|
||||
: (() => {
|
||||
try {
|
||||
return JSON.stringify(body);
|
||||
} catch {
|
||||
return String(body);
|
||||
}
|
||||
})();
|
||||
console.error(
|
||||
`API Request Failed - ${init.method} ${url}: HTTP ${response.status} ${message}`,
|
||||
);
|
||||
if (extraOptions?.isReturnErrorResult) {
|
||||
return body;
|
||||
}
|
||||
throw new Error(`HTTP ${response.status}: ${message}`);
|
||||
}
|
||||
|
||||
return contentType?.includes("application/json")
|
||||
? await response.json()
|
||||
: await response.text();
|
||||
};
|
||||
36
frontend/app/utils/api/companyData/gradeApi.ts/index.ts
Normal file
36
frontend/app/utils/api/companyData/gradeApi.ts/index.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { baseApiRequest } from "../../apiRequests/baseApiRequest";
|
||||
import { GradeResponse, GradeResponseDto } from "./type";
|
||||
|
||||
const PROJECT_MANAGEMENT_BASE_URL = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1`;
|
||||
|
||||
export const getAllGrade = async (): Promise<GradeResponse> => {
|
||||
return await baseApiRequest(
|
||||
`${PROJECT_MANAGEMENT_BASE_URL}/grades`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: ["/grades"],
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const getGradeById = async (id: string): Promise<GradeResponseDto> => {
|
||||
return await baseApiRequest(
|
||||
`${PROJECT_MANAGEMENT_BASE_URL}/grades/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: [`/grades/${id}`],
|
||||
},
|
||||
);
|
||||
};
|
||||
34
frontend/app/utils/api/companyData/gradeApi.ts/type.ts
Normal file
34
frontend/app/utils/api/companyData/gradeApi.ts/type.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
export interface GradeResponseDto {
|
||||
id: string;
|
||||
accountId: string;
|
||||
grade: string;
|
||||
}
|
||||
|
||||
export interface SortInfo {
|
||||
empty: boolean;
|
||||
sorted: boolean;
|
||||
unsorted: boolean;
|
||||
}
|
||||
|
||||
export interface PageableInfo {
|
||||
pageNumber: number;
|
||||
pageSize: number;
|
||||
sort: SortInfo;
|
||||
offset: number;
|
||||
paged: boolean;
|
||||
unpaged: boolean;
|
||||
}
|
||||
|
||||
export interface GradeResponse {
|
||||
content: GradeResponseDto[];
|
||||
pageable: PageableInfo;
|
||||
last: boolean;
|
||||
totalPages: number;
|
||||
totalElements: number;
|
||||
sort: SortInfo;
|
||||
first: boolean;
|
||||
number: number;
|
||||
size: number;
|
||||
numberOfElements: number;
|
||||
empty: boolean;
|
||||
}
|
||||
36
frontend/app/utils/api/companyData/roleApi.ts/index.ts
Normal file
36
frontend/app/utils/api/companyData/roleApi.ts/index.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { baseApiRequest } from "../../apiRequests/baseApiRequest";
|
||||
import { RoleResponse, RoleResponseDto } from "./type";
|
||||
|
||||
const PROJECT_MANAGEMENT_BASE_URL = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1`;
|
||||
|
||||
export const getAllRoles = async (): Promise<RoleResponse> => {
|
||||
return await baseApiRequest(
|
||||
`${PROJECT_MANAGEMENT_BASE_URL}/roles`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: ["/roles"],
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const getRoleById = async (id: string): Promise<RoleResponseDto> => {
|
||||
return await baseApiRequest(
|
||||
`${PROJECT_MANAGEMENT_BASE_URL}/roles/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: [`/roles/${id}`],
|
||||
},
|
||||
);
|
||||
};
|
||||
34
frontend/app/utils/api/companyData/roleApi.ts/type.ts
Normal file
34
frontend/app/utils/api/companyData/roleApi.ts/type.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
export interface RoleResponseDto {
|
||||
id: string;
|
||||
accountId: string;
|
||||
role: string;
|
||||
}
|
||||
|
||||
export interface SortInfo {
|
||||
empty: boolean;
|
||||
sorted: boolean;
|
||||
unsorted: boolean;
|
||||
}
|
||||
|
||||
export interface PageableInfo {
|
||||
pageNumber: number;
|
||||
pageSize: number;
|
||||
sort: SortInfo;
|
||||
offset: number;
|
||||
paged: boolean;
|
||||
unpaged: boolean;
|
||||
}
|
||||
|
||||
export interface RoleResponse {
|
||||
content: RoleResponseDto[];
|
||||
pageable: PageableInfo;
|
||||
last: boolean;
|
||||
totalPages: number;
|
||||
totalElements: number;
|
||||
sort: SortInfo;
|
||||
first: boolean;
|
||||
number: number;
|
||||
size: number;
|
||||
numberOfElements: number;
|
||||
empty: boolean;
|
||||
}
|
||||
43
frontend/app/utils/api/employeeDetails/index.tsx
Normal file
43
frontend/app/utils/api/employeeDetails/index.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
|
||||
const PROJECT_API = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1`;
|
||||
// const USER_API =
|
||||
// "https://ikoncloud-dev.keross.com/ikon-api/platform/user/current";
|
||||
|
||||
// READ
|
||||
export const getGrades = async () => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/grades`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
export const getRoles = async () => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/roles`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
export const getEmployees = async () => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/employees`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: ["/roles"],
|
||||
},
|
||||
);
|
||||
};
|
||||
109
frontend/app/utils/api/fxRate/index.tsx
Normal file
109
frontend/app/utils/api/fxRate/index.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
import { FxRateResponse } from "./type";
|
||||
|
||||
// interface FxRateApiResponse {
|
||||
// id: string;
|
||||
// year: string;
|
||||
// currency: string;
|
||||
// rate: string;
|
||||
// }
|
||||
|
||||
// interface PaginatedResponse<T> {
|
||||
// content: T[];
|
||||
// }
|
||||
|
||||
const PROJECT_MANAGEMENT_BASE_URL = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1`;
|
||||
|
||||
export const getAllFXRate = async (): Promise<FxRateResponse> => {
|
||||
return await baseApiRequest(
|
||||
`${PROJECT_MANAGEMENT_BASE_URL}/fx-rate`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: ["/fx-rate"],
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const getFxRateByYear = async (
|
||||
year: string,
|
||||
): Promise<FxRateResponse> => {
|
||||
return await baseApiRequest(
|
||||
`${PROJECT_MANAGEMENT_BASE_URL}/fx-rate/year=${year}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: [`/fx-rate/year=${year}`],
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
// export type FxRateMap = Map<string, Map<string, number>>;
|
||||
|
||||
// export async function createFxRateMap(): Promise<FxRateMap> {
|
||||
// const fxRateMap: FxRateMap = new Map();
|
||||
|
||||
// try {
|
||||
// console.log("Fetching FX Rates for map...");
|
||||
|
||||
// const response = await baseApiRequest(
|
||||
// "${process.env.SALES_CRM_API_URL}/fxrate",
|
||||
// {
|
||||
// method: "GET",
|
||||
// credentials: "include",
|
||||
// },
|
||||
// );
|
||||
|
||||
// const paginatedData = response as PaginatedResponse<FxRateApiResponse>;
|
||||
|
||||
// if (!paginatedData || !Array.isArray(paginatedData.content)) {
|
||||
// console.error(
|
||||
// "Invalid response structure received from FX Rate API:",
|
||||
// paginatedData,
|
||||
// );
|
||||
// throw new Error("Failed to fetch FX Rates: Invalid data format.");
|
||||
// }
|
||||
|
||||
// const rates: FxRateApiResponse[] = paginatedData.content;
|
||||
// console.log(`Processing ${rates.length} FX rates...`);
|
||||
|
||||
// rates.forEach((rateData) => {
|
||||
// const year = rateData.year;
|
||||
// const currency = rateData.currency.toUpperCase();
|
||||
// const rateValue = parseFloat(rateData.rate);
|
||||
|
||||
// if (!year || !currency || isNaN(rateValue)) {
|
||||
// console.warn("Skipping invalid rate data:", rateData);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (!fxRateMap.has(year)) {
|
||||
// fxRateMap.set(year, new Map<string, number>());
|
||||
// }
|
||||
// const yearMap = fxRateMap.get(year)!;
|
||||
// yearMap.set(currency, rateValue);
|
||||
// });
|
||||
|
||||
// console.log("FX Rate Map created successfully:", fxRateMap);
|
||||
// return fxRateMap;
|
||||
// } catch (error) {
|
||||
// console.error("Error creating FX Rate Map:", error);
|
||||
// let errorMessage = "An unknown error occurred";
|
||||
// if (error instanceof Error) {
|
||||
// errorMessage = error.message;
|
||||
// } else if (typeof error === "string") {
|
||||
// errorMessage = error;
|
||||
// }
|
||||
// throw new Error(`Failed to create FX Rate Map: ${errorMessage}`);
|
||||
// }
|
||||
// }
|
||||
65
frontend/app/utils/api/fxRate/type.ts
Normal file
65
frontend/app/utils/api/fxRate/type.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
export interface FxRateDetail {
|
||||
id: string;
|
||||
currency: string;
|
||||
fxRate: number;
|
||||
activeStatus: boolean;
|
||||
year: string;
|
||||
}
|
||||
|
||||
export interface FxRateYearGroup {
|
||||
[year: string]: {
|
||||
[key: string]: FxRateDetail;
|
||||
};
|
||||
}
|
||||
|
||||
export interface FxContentItem {
|
||||
fxRateDetails: FxRateYearGroup;
|
||||
}
|
||||
|
||||
export interface SortInfo {
|
||||
empty: boolean;
|
||||
sorted: boolean;
|
||||
unsorted: boolean;
|
||||
}
|
||||
|
||||
export interface PageableInfo {
|
||||
pageNumber: number;
|
||||
pageSize: number;
|
||||
sort: SortInfo;
|
||||
offset: number;
|
||||
paged: boolean;
|
||||
unpaged: boolean;
|
||||
}
|
||||
|
||||
export interface FxRateEntry {
|
||||
id: string;
|
||||
currency: string;
|
||||
fxRate: number;
|
||||
activeStatus: boolean;
|
||||
year: string;
|
||||
}
|
||||
|
||||
export interface FxRateDetails {
|
||||
[key: string]: {
|
||||
[key: string]: FxRateEntry;
|
||||
};
|
||||
}
|
||||
|
||||
export interface FxRateResponse {
|
||||
content: FxContentItem[];
|
||||
pageable: PageableInfo;
|
||||
last: boolean;
|
||||
totalPages: number;
|
||||
totalElements: number;
|
||||
sort: SortInfo;
|
||||
first: boolean;
|
||||
number: number;
|
||||
size: number;
|
||||
numberOfElements: number;
|
||||
empty: boolean;
|
||||
}
|
||||
|
||||
export interface CurrencyOption {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
55
frontend/app/utils/api/issueApi/index.tsx
Normal file
55
frontend/app/utils/api/issueApi/index.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import { IssueData } from "../../interface/issue";
|
||||
import { RiskData } from "../../interface/risk";
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
|
||||
const ISSUE_API = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1/issues`;
|
||||
|
||||
|
||||
// CREATE
|
||||
export const createIssueApi = async (issue: IssueData) => {
|
||||
return baseApiRequest(
|
||||
ISSUE_API,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify(issue),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
||||
export const updateIssueApi = async (issueIdentifier: string, updatedIssue: IssueData) => {
|
||||
return baseApiRequest(
|
||||
`${ISSUE_API}/${issueIdentifier}`,
|
||||
{
|
||||
method: "PUT",
|
||||
body: JSON.stringify(updatedIssue),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
// READ
|
||||
export const issuesApi = async (projectIdentifier: string) => {
|
||||
return baseApiRequest(
|
||||
`${ISSUE_API}/project/${projectIdentifier}`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true }
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export const getIssueByIdentifierApi = async (issueId: string) => {
|
||||
return baseApiRequest(
|
||||
`${ISSUE_API}/${issueId}`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true }
|
||||
);
|
||||
};
|
||||
69
frontend/app/utils/api/meetingApi/index.tsx
Normal file
69
frontend/app/utils/api/meetingApi/index.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
import { MeetingData } from "@/app/main/planning/projects/[projectIdentifier]/component/momTab/components/meetingForm/types";
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
|
||||
const MEETING_API = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1/meetings`;
|
||||
|
||||
|
||||
// CREATE
|
||||
export const createMeetingApi = async (meeting: MeetingData) => {
|
||||
return baseApiRequest(
|
||||
MEETING_API,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify(meeting),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// READ ALL BY PROJECT ID
|
||||
export const meetingsApi = async (projectIdentifier: string) => {
|
||||
return baseApiRequest(
|
||||
`${MEETING_API}/project/${projectIdentifier}`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// READ BY ID
|
||||
export const getMeetingByIdApi = async (meetingId: string) => {
|
||||
return baseApiRequest(
|
||||
`${MEETING_API}/${meetingId}`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// UPDATE
|
||||
export const updateMeetingApi = async (meetingId: string, updatedMeeting: MeetingData) => {
|
||||
return baseApiRequest(
|
||||
`${MEETING_API}/${meetingId}`,
|
||||
{
|
||||
method: "PUT",
|
||||
body: JSON.stringify(updatedMeeting),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// DELETE
|
||||
export const deleteMeetingApi = async (meetingId: string) => {
|
||||
return baseApiRequest(
|
||||
`${MEETING_API}/${meetingId}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
26
frontend/app/utils/api/productDashboardApi/index.tsx
Normal file
26
frontend/app/utils/api/productDashboardApi/index.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
import { DashboardWidgetsResponseDto, StatusWiseProjectResponseData } from "./types";
|
||||
|
||||
const PROJECT_DASHBOARD_API = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1/dashboard`;
|
||||
|
||||
export const getWidgetsData: () => Promise<DashboardWidgetsResponseDto> = async () => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_DASHBOARD_API}/widgets`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
export const getStatusWiseProjectCount: () => Promise<StatusWiseProjectResponseData> = async () => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_DASHBOARD_API}/status-wise-projects`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
10
frontend/app/utils/api/productDashboardApi/types.ts
Normal file
10
frontend/app/utils/api/productDashboardApi/types.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export interface StatusWiseProjectResponseData {
|
||||
status: string;
|
||||
projectCount: number;
|
||||
}
|
||||
|
||||
export interface DashboardWidgetsResponseDto {
|
||||
totalProjects: number;
|
||||
totalIssues: number;
|
||||
totalRisksCount: number;
|
||||
}
|
||||
48
frontend/app/utils/api/productOfProjectApi/index.tsx
Normal file
48
frontend/app/utils/api/productOfProjectApi/index.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { ProjectFormData } from "@/app/main/planning/projects/projectModal/zodProject";
|
||||
import { Project } from "@/app/main/planning/projects/types/project";
|
||||
import { ProductOfProject } from "../../interface/productOfProject";
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
|
||||
const PROJECT_API = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1/projects`;
|
||||
const USER_API =
|
||||
"https://ikoncloud-dev.keross.com/ikon-api/platform/user/current";
|
||||
|
||||
// READ
|
||||
export const getProductsApi = async (projectId: string) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${projectId}/products`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
// UPDATE
|
||||
export const updateProductApi = async (product: ProductOfProject) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${product.projectIdentifier}/products/${product.productIdentifier}`,
|
||||
{
|
||||
method: "PUT",
|
||||
body: JSON.stringify(product),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
// WORKFLOW TRANSITION
|
||||
export const transitionProductStatusApi = async (
|
||||
projectId: string,
|
||||
productId: string,
|
||||
targetStatus: string,
|
||||
) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${projectId}/products/${productId}/transition`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({ targetStatus }),
|
||||
},
|
||||
{ isAccessTokenRequird: true, isReturnErrorResult: true },
|
||||
);
|
||||
};
|
||||
112
frontend/app/utils/api/productOfProjectApi/type.ts
Normal file
112
frontend/app/utils/api/productOfProjectApi/type.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
export interface ProductPSData {
|
||||
productIdentifier: string; // UUID
|
||||
|
||||
dealName: string;
|
||||
projectManager: string;
|
||||
productStatus: string;
|
||||
updatedOn: string;
|
||||
updatedBy: string;
|
||||
dealStatus: string;
|
||||
dealIdentifier: string; // UUID
|
||||
leadIdentifier: string; // UUID
|
||||
|
||||
quotation: Record<string, QuotationItemDto>;
|
||||
|
||||
productType: string;
|
||||
productDescription: string;
|
||||
|
||||
scheduleData: ScheduleDataDto;
|
||||
|
||||
resourceDataWithAllocation: ResourceAllocationDto[];
|
||||
|
||||
discountPercent: number | null;
|
||||
expenseDetails: Record<string, ExpenseDetailDto>;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
export interface QuotationItemDto {
|
||||
id: string;
|
||||
role: string;
|
||||
totalFTE: number;
|
||||
scr: number;
|
||||
expenses: number;
|
||||
otherCosts: number;
|
||||
billingAmount: number;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
export interface ScheduleDataDto {
|
||||
task: TaskDto[];
|
||||
dependency: DependencyDto[];
|
||||
group: Record<string, GroupItem>;
|
||||
}
|
||||
|
||||
export interface GroupItem {
|
||||
id?: string | number;
|
||||
name?: string;
|
||||
type?: string;
|
||||
order?: number;
|
||||
color?: string;
|
||||
isActive?: boolean;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
export interface TaskDto {
|
||||
id: number;
|
||||
parentId: number;
|
||||
taskName: string;
|
||||
taskDuration: number;
|
||||
taskPredecessor: string;
|
||||
dependencyType: number;
|
||||
taskColour: string;
|
||||
delayDuration: number;
|
||||
taskDescription: string;
|
||||
taskStart: string;
|
||||
taskEnd: string;
|
||||
milestoneTask: boolean;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
export interface DependencyDto {
|
||||
id: number;
|
||||
predecessorId: number;
|
||||
dependencyType: number;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
export interface ResourceAllocationDto {
|
||||
id?: string;
|
||||
allocation: Record<string, number>;
|
||||
detailedAllocation: Record<string, DetailedAllocationValue>;
|
||||
resourceType: string;
|
||||
role: string;
|
||||
gradeId: number;
|
||||
employeeName: string;
|
||||
taskName: string;
|
||||
resourceId: string;
|
||||
taskId: number;
|
||||
}
|
||||
|
||||
export interface DetailedAllocationValue {
|
||||
hours?: number;
|
||||
date?: string;
|
||||
cost?: number;
|
||||
comments?: string;
|
||||
approved?: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface ExpenseDetailDto {
|
||||
expenseName: string;
|
||||
location: string;
|
||||
currency: string;
|
||||
cost: number;
|
||||
quantity: number;
|
||||
totalCost: number;
|
||||
remarks: string;
|
||||
}
|
||||
48
frontend/app/utils/api/productOfprojectsApi/index.tsx
Normal file
48
frontend/app/utils/api/productOfprojectsApi/index.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { UUID } from "crypto";
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
|
||||
const PROJECT_API = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1/projects`;
|
||||
const USER_API =
|
||||
"https://ikoncloud-dev.keross.com/ikon-api/platform/user/current";
|
||||
|
||||
|
||||
// READ
|
||||
export const getAllProductsByProject = async (projectIdentifier: UUID) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${projectIdentifier}/products`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store", // optional but recommended for fresh data
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
export const getProductById = async (projectId: UUID, productIdentifier: UUID) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${projectId}/products/${productIdentifier}`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true }
|
||||
);
|
||||
};
|
||||
|
||||
// UPDATE
|
||||
export const updateProduct = async (projectId: UUID, productIdentifier: UUID, updatedProduct: any) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${projectId}/products/${productIdentifier}`,
|
||||
{
|
||||
method: "PUT",
|
||||
body: JSON.stringify(updatedProduct),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
85
frontend/app/utils/api/productsResourceAllocation/index.tsx
Normal file
85
frontend/app/utils/api/productsResourceAllocation/index.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
import { UUID } from "crypto";
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
|
||||
const PRODUCT_API = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1/products`;
|
||||
|
||||
// Allocation payload shape
|
||||
export interface ProductAllocation {
|
||||
id?: string;
|
||||
allocation: Record<string, number>;
|
||||
detailedAllocation: Record<string, Record<string, any>>;
|
||||
resourceType: string;
|
||||
role: string;
|
||||
gradeId: number;
|
||||
employeeName: string;
|
||||
taskName: string;
|
||||
resourceId: string;
|
||||
taskId: number;
|
||||
}
|
||||
|
||||
// List allocations for a product
|
||||
export const getResourceAllocations = async (productIdentifier: UUID) => {
|
||||
return baseApiRequest(
|
||||
`${PRODUCT_API}/${productIdentifier}/resource-allocations`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true }
|
||||
);
|
||||
};
|
||||
|
||||
// Get a single allocation
|
||||
export const getAllocation = async (productIdentifier: UUID, allocationIdentifier: UUID) => {
|
||||
return baseApiRequest(
|
||||
`${PRODUCT_API}/${productIdentifier}/resource-allocations/${allocationIdentifier}`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true }
|
||||
);
|
||||
};
|
||||
|
||||
// Create allocation
|
||||
export const createAllocation = async (productIdentifier: UUID, allocation: ProductAllocation) => {
|
||||
return baseApiRequest(
|
||||
`${PRODUCT_API}/${productIdentifier}/resource-allocations`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify(allocation),
|
||||
},
|
||||
{ isAccessTokenRequird: true }
|
||||
);
|
||||
};
|
||||
|
||||
// Update allocation
|
||||
export const updateAllocation = async (
|
||||
productIdentifier: UUID,
|
||||
allocationIdentifier: UUID,
|
||||
updatedAllocation: ProductAllocation
|
||||
) => {
|
||||
return baseApiRequest(
|
||||
`${PRODUCT_API}/${productIdentifier}/resource-allocations/${allocationIdentifier}`,
|
||||
{
|
||||
method: "PUT",
|
||||
body: JSON.stringify(updatedAllocation),
|
||||
},
|
||||
{ isAccessTokenRequird: true }
|
||||
);
|
||||
};
|
||||
|
||||
// Delete allocation
|
||||
export const deleteAllocation = async (productIdentifier: UUID, allocationIdentifier: UUID) => {
|
||||
return baseApiRequest(
|
||||
`${PRODUCT_API}/${productIdentifier}/resource-allocations/${allocationIdentifier}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
},
|
||||
{ isAccessTokenRequird: true }
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
111
frontend/app/utils/api/projectApi/index.tsx
Normal file
111
frontend/app/utils/api/projectApi/index.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import { ProjectFormData } from "@/app/main/planning/projects/projectModal/zodProject";
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
import { Project } from "@/app/main/planning/projects/types/project";
|
||||
|
||||
const PROJECT_API = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1/projects`;
|
||||
const USER_API =
|
||||
`${process.env.NEXT_PUBLIC_IKON_API_URL}/platform/user/current`;
|
||||
|
||||
// CREATE
|
||||
export const createProjectApi = async (project: ProjectFormData) => {
|
||||
return baseApiRequest(
|
||||
PROJECT_API,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify(project),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
// READ
|
||||
export const getProjectsApi = async () => {
|
||||
return baseApiRequest(
|
||||
PROJECT_API,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
export const getProjectByIdentifierApi = async (projectId: string) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${projectId}`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
// UPDATE
|
||||
export const updateProjectApi = async (project: Project) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${project.projectIdentifier}`,
|
||||
{
|
||||
method: "PUT",
|
||||
body: JSON.stringify(project),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
export const getScheduleApi = async (projectId: string) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${projectId}/schedules`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
export const getAllSchedulesApi = async () => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/schedules`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store"
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
export const saveScheduleApi = async (
|
||||
projectId: string,
|
||||
scheduleData: { task: any[]; dependency: any[]; group?: Record<string, any> },
|
||||
) => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/${projectId}/schedules`,
|
||||
{ method: "PUT", body: JSON.stringify(scheduleData) },
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
export const getUsersApi = async () => {
|
||||
return baseApiRequest(
|
||||
USER_API,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const getAllActiveProjectsTimelineApi = async () => {
|
||||
return baseApiRequest(
|
||||
`${PROJECT_API}/active-projects-timeline`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
88
frontend/app/utils/api/projectManager/index.tsx
Normal file
88
frontend/app/utils/api/projectManager/index.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
import { ManagerMemberships, Role, RoleMembership } from "./projectManager";
|
||||
|
||||
|
||||
const API_BASE_URL = "https://ikoncloud-dev.keross.com/ikon-api";
|
||||
|
||||
export const getAllRoles = async (): Promise<Role[]> => {
|
||||
return await baseApiRequest(
|
||||
`${API_BASE_URL}/role`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const getRoleMemberships = async (roleId: string): Promise<RoleMembership[]> => {
|
||||
return await baseApiRequest(
|
||||
`${API_BASE_URL}/role/${roleId}/membership`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const getRoleIdByName = (
|
||||
roles: Role[],
|
||||
roleName: string
|
||||
): string | undefined => {
|
||||
if (!roles || !Array.isArray(roles)) {
|
||||
console.error("getRoleIdByName received invalid roles data:", roles);
|
||||
return undefined;
|
||||
}
|
||||
const foundRole = roles.find((role) => role.roleName === roleName);
|
||||
|
||||
return foundRole?.roleId;
|
||||
};
|
||||
|
||||
export const getManagerMemberships = async (): Promise<ManagerMemberships> => {
|
||||
try {
|
||||
const response = await getAllRoles();
|
||||
const allRoles = Array.isArray(response) ? response : (response?.content || []);
|
||||
|
||||
const projectManagerId = getRoleIdByName(allRoles, "Project manager");
|
||||
const accountManagerId = getRoleIdByName(allRoles, "Account Manager");
|
||||
|
||||
if (!projectManagerId) {
|
||||
console.warn("Could not find roleId for 'Project Manager'");
|
||||
}
|
||||
if (!accountManagerId) {
|
||||
console.warn("Could not find roleId for 'Account Manager'");
|
||||
}
|
||||
|
||||
const pmPromise = projectManagerId
|
||||
? getRoleMemberships(projectManagerId)
|
||||
: Promise.resolve([]);
|
||||
|
||||
const amPromise = accountManagerId
|
||||
? getRoleMemberships(accountManagerId)
|
||||
: Promise.resolve([]);
|
||||
|
||||
const [projectManagerMembers, accountManagerMembers] = await Promise.all([
|
||||
pmPromise,
|
||||
amPromise,
|
||||
]);
|
||||
|
||||
return {
|
||||
projectManagerMembers,
|
||||
accountManagerMembers,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error in getManagerMemberships:", error);
|
||||
return {
|
||||
projectManagerMembers: [],
|
||||
accountManagerMembers: [],
|
||||
};
|
||||
}
|
||||
};
|
||||
54
frontend/app/utils/api/projectManager/projectManager.ts
Normal file
54
frontend/app/utils/api/projectManager/projectManager.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
export interface IkonGroup {
|
||||
groupId: string;
|
||||
groupName: string;
|
||||
softwareId: string;
|
||||
accountId: string | null;
|
||||
groupType: "STATIC" | "DYNAMIC" | string;
|
||||
active: boolean;
|
||||
groupDescription: string;
|
||||
}
|
||||
|
||||
export interface Role {
|
||||
roleId: string;
|
||||
roleName: string;
|
||||
active: boolean;
|
||||
softwareId: string;
|
||||
roleDescription: string;
|
||||
ikonGroups: IkonGroup[];
|
||||
}
|
||||
|
||||
export interface RoleMembership {
|
||||
roleMembershipId: string;
|
||||
userId: string;
|
||||
accountId: string;
|
||||
roleId: string;
|
||||
}
|
||||
|
||||
export interface ManagerMemberships {
|
||||
projectManagerMembers: RoleMembership[];
|
||||
accountManagerMembers: RoleMembership[];
|
||||
}
|
||||
|
||||
|
||||
export interface User {
|
||||
userId: string;
|
||||
userName: string;
|
||||
userLogin: string;
|
||||
userPhone: string | null;
|
||||
userEmail: string;
|
||||
userThumbnail: string | null;
|
||||
userType: string;
|
||||
active: boolean;
|
||||
dateOfBirth: string | null;
|
||||
userProfileImage: string | null;
|
||||
userDescription: string | null;
|
||||
userDesignation: string | null;
|
||||
invitedUser: boolean;
|
||||
userDeleted: boolean;
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
userName: string;
|
||||
userLogin: string;
|
||||
userEmail: string;
|
||||
}
|
||||
54
frontend/app/utils/api/riskApi/index.tsx
Normal file
54
frontend/app/utils/api/riskApi/index.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { RiskData } from "../../interface/risk";
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
|
||||
const RISK_API = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1/risks`;
|
||||
|
||||
|
||||
// CREATE
|
||||
export const createRiskApi = async (Risk: RiskData) => {
|
||||
return baseApiRequest(
|
||||
RISK_API,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify(Risk),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
||||
export const updateRiskApi = async (riskIdentifier: string, updatedRisk: RiskData) => {
|
||||
return baseApiRequest(
|
||||
`${RISK_API}/${riskIdentifier}`,
|
||||
{
|
||||
method: "PUT",
|
||||
body: JSON.stringify(updatedRisk),
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
// READ
|
||||
export const risksApi = async () => {
|
||||
return baseApiRequest(
|
||||
RISK_API,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true },
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export const getRiskByIdentifierApi = async (riskId: string) => {
|
||||
return baseApiRequest(
|
||||
`${RISK_API}/${riskId}`,
|
||||
{
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
},
|
||||
{ isAccessTokenRequird: true }
|
||||
);
|
||||
};
|
||||
65
frontend/app/utils/api/user-dashboard-platform/index.tsx
Normal file
65
frontend/app/utils/api/user-dashboard-platform/index.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
import { Role, User, RoleMembership } from "./type";
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL;
|
||||
const IKON_API_URL = process.env.NEXT_PUBLIC_IKON_API_URL;
|
||||
|
||||
export const getAllRoles = async (): Promise<Role[]> => {
|
||||
return await baseApiRequest(
|
||||
`${API_BASE_URL}/role`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: ["/roles"],
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const getAllUsers = async (): Promise<User[]> => {
|
||||
return await baseApiRequest(
|
||||
`${IKON_API_URL}/platform/user/current`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: ["/platform/user/current"],
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const getUserById = async (userId: string): Promise<User | null> => {
|
||||
return await baseApiRequest(
|
||||
`${IKON_API_URL}/platform/user/${userId}`, // Assuming this endpoint pattern
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: [`/platform/user/${userId}`],
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const getRoleMemberships = async (roleId: string): Promise<RoleMembership[]> => {
|
||||
return await baseApiRequest(
|
||||
`${API_BASE_URL}/role/${roleId}/membership`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,145 @@
|
||||
import { getAllRoles, getAllUsers, getRoleMemberships, getUserById } from ".";
|
||||
import { ManagerMemberships, Role, UserInfo } from "./type"; // Import User
|
||||
|
||||
export const getRoleIdByName = (
|
||||
roles: Role[],
|
||||
roleName: string
|
||||
): string | undefined => {
|
||||
if (!roles || !Array.isArray(roles)) {
|
||||
console.error("getRoleIdByName received invalid roles data:", roles);
|
||||
return undefined;
|
||||
}
|
||||
const foundRole = roles.find((role) => role.roleName === roleName);
|
||||
|
||||
return foundRole?.roleId;
|
||||
};
|
||||
|
||||
export const findUsersInRole = async (roleName: string) => {
|
||||
try {
|
||||
console.log("Step 1: Fetching all roles...");
|
||||
const allRoles = await getAllRoles();
|
||||
|
||||
console.log(`Step 2: Finding ID for role "${roleName}"...`);
|
||||
const roleId = getRoleIdByName(allRoles, roleName);
|
||||
|
||||
if (!roleId) {
|
||||
console.error(`Error: Role "${roleName}" not found.`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Found roleId: ${roleId}`);
|
||||
|
||||
console.log("Step 3: Fetching memberships for this role...");
|
||||
const memberships = await getRoleMemberships(roleId);
|
||||
|
||||
if (memberships.length === 0) {
|
||||
console.log(`No users found for role "${roleName}".`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Success! Found ${memberships.length} user(s) in "${roleName}":`
|
||||
);
|
||||
|
||||
const userIds = memberships.map((m: { userId: string }) => m.userId);
|
||||
console.log(userIds);
|
||||
return userIds;
|
||||
} catch (error) {
|
||||
console.error("An error occurred during the process:", error);
|
||||
}
|
||||
};
|
||||
|
||||
export const getManagerMemberships = async (): Promise<ManagerMemberships> => {
|
||||
try {
|
||||
const response = await getAllRoles();
|
||||
const allRoles = Array.isArray(response) ? response : (response?.content || []);
|
||||
console.log("rolesss", allRoles);
|
||||
const projectManagerId = getRoleIdByName(allRoles, "Project manager");
|
||||
const accountManagerId = getRoleIdByName(allRoles, "Account Manager");
|
||||
|
||||
if (!projectManagerId) {
|
||||
console.warn("Could not find roleId for 'Project Manager'");
|
||||
}
|
||||
if (!accountManagerId) {
|
||||
console.warn("Could not find roleId for 'Account Manager'");
|
||||
}
|
||||
|
||||
const pmPromise = projectManagerId
|
||||
? getRoleMemberships(projectManagerId)
|
||||
: Promise.resolve([]);
|
||||
|
||||
const amPromise = accountManagerId
|
||||
? getRoleMemberships(accountManagerId)
|
||||
: Promise.resolve([]);
|
||||
|
||||
const [projectManagerMembers, accountManagerMembers] = await Promise.all([
|
||||
pmPromise,
|
||||
amPromise,
|
||||
]);
|
||||
|
||||
return {
|
||||
projectManagerMembers,
|
||||
accountManagerMembers,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error in getManagerMemberships:", error);
|
||||
return {
|
||||
projectManagerMembers: [],
|
||||
accountManagerMembers: [],
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const createUserMaps = async (): Promise<{
|
||||
nameMap: Map<string, string>;
|
||||
designationMap: Map<string, string | null>;
|
||||
}> => {
|
||||
const nameMap = new Map<string, string>();
|
||||
const designationMap = new Map<string, string | null>();
|
||||
|
||||
try {
|
||||
const response = await getAllUsers();
|
||||
const userArray = response ?? response;
|
||||
|
||||
if (!userArray || !Array.isArray(userArray) || userArray.length === 0) {
|
||||
return { nameMap, designationMap };
|
||||
} else {
|
||||
for (const user of userArray) {
|
||||
if (user?.userId) {
|
||||
nameMap.set(user.userId, user.userName);
|
||||
designationMap.set(user.userId, user.userDesignation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { nameMap, designationMap };
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch users and create maps:", error);
|
||||
return { nameMap, designationMap };
|
||||
}
|
||||
};
|
||||
|
||||
export const getUserNameById = async (
|
||||
userId: string
|
||||
): Promise<string | undefined> => {
|
||||
try {
|
||||
const user = await getUserById(userId);
|
||||
return user?.userName;
|
||||
} catch (error) {
|
||||
console.error("Failed to get user name by ID:", error);
|
||||
}
|
||||
};
|
||||
|
||||
export const getUserInfo = async (userId: string): Promise<UserInfo | null> => {
|
||||
const user = await getUserById(userId);
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
userName: user.userName,
|
||||
userLogin: user.userLogin,
|
||||
userEmail: user.userEmail,
|
||||
};
|
||||
};
|
||||
54
frontend/app/utils/api/user-dashboard-platform/type.ts
Normal file
54
frontend/app/utils/api/user-dashboard-platform/type.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
export interface IkonGroup {
|
||||
groupId: string;
|
||||
groupName: string;
|
||||
softwareId: string;
|
||||
accountId: string | null;
|
||||
groupType: "STATIC" | "DYNAMIC" | string;
|
||||
active: boolean;
|
||||
groupDescription: string;
|
||||
}
|
||||
|
||||
export interface Role {
|
||||
roleId: string;
|
||||
roleName: string;
|
||||
active: boolean;
|
||||
softwareId: string;
|
||||
roleDescription: string;
|
||||
ikonGroups: IkonGroup[];
|
||||
}
|
||||
|
||||
export interface RoleMembership {
|
||||
roleMembershipId: string;
|
||||
userId: string;
|
||||
accountId: string;
|
||||
roleId: string;
|
||||
}
|
||||
|
||||
export interface ManagerMemberships {
|
||||
projectManagerMembers: RoleMembership[];
|
||||
accountManagerMembers: RoleMembership[];
|
||||
}
|
||||
|
||||
|
||||
export interface User {
|
||||
userId: string;
|
||||
userName: string;
|
||||
userLogin: string;
|
||||
userPhone: string | null;
|
||||
userEmail: string;
|
||||
userThumbnail: string | null;
|
||||
userType: string;
|
||||
active: boolean;
|
||||
dateOfBirth: string | null;
|
||||
userProfileImage: string | null;
|
||||
userDescription: string | null;
|
||||
userDesignation: string | null;
|
||||
invitedUser: boolean;
|
||||
userDeleted: boolean;
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
userName: string;
|
||||
userLogin: string;
|
||||
userEmail: string;
|
||||
}
|
||||
38
frontend/app/utils/api/workingDays/index.ts
Normal file
38
frontend/app/utils/api/workingDays/index.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { baseApiRequest } from "../apiRequests/baseApiRequest";
|
||||
import { WorkingDaysResponse } from "./type";
|
||||
|
||||
const PROJECT_MANAGEMENT_BASE_URL = `${process.env.NEXT_PUBLIC_PROJECT_MANAGEMENT_API_URL}/api/v1`;
|
||||
|
||||
export const getAllWorkingDays = async (): Promise<WorkingDaysResponse> => {
|
||||
return await baseApiRequest(
|
||||
`${PROJECT_MANAGEMENT_BASE_URL}/working-days`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: ["/working-days"],
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const getWorkingDaysByYear = async (
|
||||
year: string,
|
||||
): Promise<WorkingDaysResponse> => {
|
||||
return await baseApiRequest(
|
||||
`${PROJECT_MANAGEMENT_BASE_URL}/working-days/year/${year}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
},
|
||||
{
|
||||
isAccessTokenRequird: true,
|
||||
revalidatePaths: [`/working-days/year/${year}`],
|
||||
},
|
||||
);
|
||||
};
|
||||
40
frontend/app/utils/api/workingDays/type.ts
Normal file
40
frontend/app/utils/api/workingDays/type.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
export interface WorkingDaysMonthDto {
|
||||
year: string;
|
||||
month: string;
|
||||
workingDays: number;
|
||||
}
|
||||
|
||||
export interface WorkingDaysResponseDto {
|
||||
workingId: string;
|
||||
accountIdentifier: string;
|
||||
workingDaysDetails: Record<string, Record<string, WorkingDaysMonthDto>>;
|
||||
}
|
||||
|
||||
export interface WorkingDaysPageableInfo {
|
||||
offset: number;
|
||||
sort: SortInfo;
|
||||
pageSize: number;
|
||||
paged: boolean;
|
||||
unpaged: boolean;
|
||||
pageNumber: number;
|
||||
}
|
||||
|
||||
export interface SortInfo {
|
||||
empty: boolean;
|
||||
sorted: boolean;
|
||||
unsorted: boolean;
|
||||
}
|
||||
|
||||
export interface WorkingDaysResponse {
|
||||
content: WorkingDaysResponseDto[];
|
||||
pageable: WorkingDaysPageableInfo;
|
||||
last: boolean;
|
||||
totalPages: number;
|
||||
totalElements: number;
|
||||
sort: SortInfo;
|
||||
first: boolean;
|
||||
number: number;
|
||||
size: number;
|
||||
numberOfElements: number;
|
||||
empty: boolean;
|
||||
}
|
||||
Reference in New Issue
Block a user