first commit

This commit is contained in:
Your NamebaishaliHolocron
2026-06-15 12:57:03 +05:30
commit b9ac5ae0b2
398 changed files with 49583 additions and 0 deletions

View 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();
};

View 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}`],
},
);
};

View 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;
}

View 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}`],
},
);
};

View 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;
}

View 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"],
},
);
};

View 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}`);
// }
// }

View 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;
}

View 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 }
);
};

View 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 },
);
};

View 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 },
);
};

View File

@@ -0,0 +1,10 @@
export interface StatusWiseProjectResponseData {
status: string;
projectCount: number;
}
export interface DashboardWidgetsResponseDto {
totalProjects: number;
totalIssues: number;
totalRisksCount: number;
}

View 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 },
);
};

View 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;
}

View 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 },
);
};

View 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 }
);
};

View 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 },
);
};

View 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: [],
};
}
};

View 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;
}

View 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 }
);
};

View 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,
}
);
};

View File

@@ -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,
};
};

View 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;
}

View 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}`],
},
);
};

View 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;
}