This commit is contained in:
natib21
2026-07-10 11:25:59 +00:00
parent 2696ca7498
commit e6e44e773b
1146 changed files with 200266 additions and 90527 deletions

View File

@@ -0,0 +1,201 @@
import { withHeaders } from "@/record-management/services/api/withHeaders";
import axiosInstance from "@/shared/services/axiosInstance";
import performanceInstance from "@/shared/services/performanceInstance";
import { AxiosResponse } from "axios";
export interface CreateEmployeePlanDto {
planId: string;
employeePositionId: string;
serviceId?: string;
parentEmployeePlanId?: string;
expectedQuantity: number;
planType: "number" | "percent" | "boolean";
timeframe: string;
week?: number;
month?: number;
quarter?: number;
}
export interface EmployeeDTO {
createdAt: string;
updatedAt: string;
id: string;
isCurrent: boolean;
status: string;
name: LocalizedName;
organizationId: string;
unitId: string;
userId: string;
employeePositions: EmployeePositionDTO[];
}
export interface LocalizedName {
am: string;
en: string;
}
export interface planParam {
timeframe: string;
skip?: number;
take?: number;
}
export interface EmployeePositionDTO {
createdAt: string;
updatedAt: string;
id: string;
isDelegate: boolean;
isCurrent: boolean;
startDate: string;
amharicStartDate: string;
endDate: string | null;
amharicEndDate: string | null;
unitId: string;
delegatorId: string | null;
employeeId: string;
positionId: string;
delegationLetterId: string | null;
position: PositionDTO;
}
export interface PositionDTO {
createdAt: string;
updatedAt: string;
id: string;
name: LocalizedName;
key: string;
rank: number;
parentPositionId: string | null;
unitId: string;
organizationId: string;
projectId: string | null;
positionTypeId: string;
}
export interface ImmediateChildResponse {
count: number;
items: EmployeeDTO[];
}
export const createEmployeePlan = async (
data: CreateEmployeePlanDto
): Promise<AxiosResponse> => {
return performanceInstance.post("/employee-plans", data, {
headers: withHeaders(),
});
};
export const getEmployeePlans = async (
planId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(`/employee-plans/list/${planId}`, {
headers: withHeaders(),
});
};
export const getEmployeePlan = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.get(`/employee-plans/${id}`, {
headers: withHeaders(),
});
};
export const updateEmployeePlan = async (
id: string,
data: CreateEmployeePlanDto
): Promise<AxiosResponse> => {
return performanceInstance.put(`/employee-plans/${id}`, data, {
headers: withHeaders(),
});
};
export const deleteEmployeePlan = async (
id: string
): Promise<AxiosResponse> => {
return performanceInstance.delete(`/employee-plans/${id}`, {
headers: withHeaders(),
});
};
export const getPlansByUnit = async (
unitId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plans/mine`, {
headers: withHeaders(),
params: { unitId },
});
};
export const getPositionsByUnit = async (
unitId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(`/positions`, {
headers: withHeaders(),
params: { unitId },
});
};
export const getEmployeePositions = async (
positionId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(`/employee-positions`, {
headers: withHeaders(),
params: { positionId },
});
};
export const getServices = async (): Promise<AxiosResponse> => {
return performanceInstance.get(`/services`, {
headers: withHeaders(),
});
};
export const getParentEmployeePlanDetail = async (
id: string
): Promise<AxiosResponse> => {
return performanceInstance.get(`/employee-plans/${id}`, {
headers: withHeaders(),
});
};
export const fetchImmediateChild =
async (): Promise<ImmediateChildResponse> => {
try {
const { data } = await axiosInstance.get(`/employees/immediate-child`, {
headers: withHeaders(),
});
return data;
} catch (error: any) {
throw new Error(
error?.response?.data?.message || "Failed to fetch immediate child"
);
}
};
export const getEmployeePlanByPlanId = async (
planId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(
`/employee-plans/plan/${planId}/employee-plans`,
{
headers: withHeaders(),
}
);
};
export const getEmployeeSubPlanByPlanId = async (
planId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(
`/employee-plans/${planId}/sub-employee-plans`,
{
headers: withHeaders(),
}
);
};
export const getMyEmployeePlan = async (
params?: planParam
): Promise<AxiosResponse> => {
return performanceInstance.get(`/employee-plans/mine`, {
headers: withHeaders(),
params,
});
};

View File

@@ -0,0 +1,147 @@
import axios, { AxiosResponse } from "axios";
import Cookies from "js-cookie";
import { getEnvUrl } from "@/shared/config/env";
export interface MetabaseDashboard {
id: string;
name: {
am: string;
en: string;
};
description: {
am: string;
en: string;
};
metabaseDashboardNumber: number;
permissionId: string;
createdAt: string;
updatedAt: string;
tenantId: string;
params: string[];
}
export interface MetabaseDashboardsResponse {
count: number;
items: MetabaseDashboard[];
}
export interface MetabaseIframeResponse {
iframeUrl: string;
}
export interface CreateDashboardRequest {
name: {
am: string;
en: string;
};
metabaseDashboardNumber: number;
description: {
am: string;
en: string;
};
permissionId: string;
params: Record<string, unknown>[];
}
export interface GetIframeUrlRequest {
params: Record<string, unknown>;
}
// Create a dedicated axios instance for Metabase API
const metabaseAxios = axios.create({
baseURL: getEnvUrl("VITE_CHRONICLE_URL"),
});
// Add auth token interceptor
metabaseAxios.interceptors.request.use((config) => {
const token = Cookies.get("auth-token");
if (token) {
config.headers["Authorization"] = `Bearer ${token}`;
}
// Add tenant ID header
config.headers["x-tenant-id"] = "adf98293-41ba-4bda-bdb4-70e30a70c1b7";
return config;
});
class MetabaseService {
private baseUrl = "/metabase-dashboards";
async createDashboard(
data: CreateDashboardRequest,
): Promise<MetabaseDashboard> {
const response: AxiosResponse<MetabaseDashboard> = await metabaseAxios.post(
this.baseUrl,
data,
);
return response.data;
}
async getAllDashboards(): Promise<MetabaseDashboardsResponse> {
const response: AxiosResponse<MetabaseDashboardsResponse> =
await metabaseAxios.get(this.baseUrl);
return response.data;
}
async getPermittedDashboards(
locale: string = "en",
): Promise<MetabaseDashboardsResponse> {
const response: AxiosResponse<MetabaseDashboardsResponse> =
await metabaseAxios.get(`${this.baseUrl}/permitted`, {
params: {
locale,
},
});
return response.data;
}
async getIframeUrl(
dashboardId: string,
params: GetIframeUrlRequest,
): Promise<MetabaseIframeResponse> {
const response: AxiosResponse<MetabaseIframeResponse> =
await metabaseAxios.post(
`${this.baseUrl}/${dashboardId}/iframe-url`,
params,
);
return response.data;
}
async getFilteredDashboardUrl(
dashboardId: string,
planYearId: string,
): Promise<MetabaseIframeResponse> {
const params: GetIframeUrlRequest = {
params: {
plan_year: planYearId,
},
};
const response: AxiosResponse<MetabaseIframeResponse> =
await metabaseAxios.post(
`${this.baseUrl}/${dashboardId}/iframe-url`,
params,
);
return response.data;
}
}
export const metabaseService = new MetabaseService();
// Helper function to create a performance dashboard
export const createPerformanceDashboard = async () => {
const dashboardData: CreateDashboardRequest = {
name: {
am: "performance",
en: "performance",
},
metabaseDashboardNumber: 2,
description: {
am: "performance",
en: "performance",
},
permissionId: "a83825b9-9806-4918-bc10-56226bbe41d4",
params: [],
};
return metabaseService.createDashboard(dashboardData);
};

View File

@@ -0,0 +1,65 @@
import { Axios, AxiosResponse } from "axios";
import performanceInstance from "@/shared/services/performanceInstance";
import { withHeaders } from "@/record-management/services/api/withHeaders";
import DateMeasurementUnit from "@/performance-management/utils/data-measurement-unit";
export interface CreateServiceDto {
id?: string; // Optional for create, required for update
slug: string;
prefix: string;
name: {
am: string;
en: string;
};
description: {
am: string;
en: string;
};
organizationId: string;
serviceCategoryId?: string;
parentServiceId?: string;
estimatedTime: number;
estimatedTimeUnit: DateMeasurementUnit;
}
export const createService = async (
data: CreateServiceDto
): Promise<AxiosResponse> => {
return performanceInstance.post("/services", data, {
headers: withHeaders(),
});
};
export const getService = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.get(`/services/${id}`, {
headers: withHeaders(),
});
};
export const getServiceList = async (
organizationId: string,
serviceCategoryId?: string,
parentServiceId?: string
): Promise<AxiosResponse> => {
const params: any = {};
if (serviceCategoryId) params.serviceCategoryId = serviceCategoryId;
if (parentServiceId) params.parentServiceId = parentServiceId;
return performanceInstance.get(`/services/list/${organizationId}`, {
headers: withHeaders(),
params,
});
};
export const updateService = async (
data: CreateServiceDto
): Promise<AxiosResponse> => {
return performanceInstance.put(`/services/${data.id}`, data, {
headers: withHeaders(),
});
};
export const deleteService = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.delete(`/services/${id}`, {
headers: withHeaders(),
});
};

View File

@@ -0,0 +1,155 @@
import { SectorListParam } from "@/performance-management/types/planTypes";
import PlanType from "@/performance-management/utils/plan-unit";
import { withHeaders } from "@/record-management/services/api/withHeaders";
import performanceInstance from "@/shared/services/performanceInstance";
import { AxiosResponse } from "axios";
export interface PlanParams {
serviceId?: string;
positionId?: string;
parentPlanId?: string;
skip?: number;
take?: number;
orderBy?: string;
planFor?: "team" | "self" | "position";
}
export interface CreatePlanDto {
id?: string;
name: {
am: string;
en: string;
};
description: {
am: string;
en: string;
};
positionId?: string;
parentPlanId?: string; //
planType: PlanType; //
planYearId: string; //
// initialGoal: number;
// expectedGoal: number;
weight: number;
month?: number;
week?: number;
day?: number;
quarter?: number;
timeframe: string;
}
export const createPlan = async (
data: CreatePlanDto,
): Promise<AxiosResponse> => {
return performanceInstance.post("/plans", data, {
headers: withHeaders(),
});
};
export const updatePlan = async (
data: CreatePlanDto,
): Promise<AxiosResponse> => {
return performanceInstance.put(`/plans/${data?.id}`, data, {
headers: withHeaders(),
});
};
export const requestApproval = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.post(
`/plans/${id}/sent`,
{},
{
headers: withHeaders(),
},
);
};
export const approvePlan = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.post(
`/plans/${id}/approve`,
{},
{
headers: withHeaders(),
},
);
};
export const rejectPlan = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.post(
`/plans/${id}/reject`,
{},
{
headers: withHeaders(),
},
);
};
export const deletePlan = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.delete(`/plans/${id}`, {
headers: withHeaders(),
});
};
export const getPlan = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.get(`/plans/${id}`, {
headers: withHeaders(),
});
};
export const getPlanList = async (
id: string,
params?: PlanParams,
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plans/list/${id}`, {
headers: withHeaders(),
params,
});
};
export const getSectorList = async (
id?: string,
params?: SectorListParam,
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plans/${id}/sector`, {
headers: withHeaders(),
params,
});
};
export const getMinePlan = async (
params?: SectorListParam,
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plans/mine`, {
headers: withHeaders(),
params,
});
};
export const getSubPlans = async (
id: string,
params?: SectorListParam,
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plans/${id}/sub-plans`, {
headers: withHeaders(),
params,
});
};
export const getMySubPlans = async (
id: string,
params?: SectorListParam,
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plans/${id}/mine-sub-plans`, {
headers: withHeaders(),
params,
});
};
export const getTeamSubPlans = async (
id: string,
params?: SectorListParam,
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plans/${id}/team-sub-plans`, {
headers: withHeaders(),
params,
});
};

View File

@@ -0,0 +1,120 @@
import { withHeaders } from "@/record-management/services/api/withHeaders";
import performanceInstance from "@/shared/services/performanceInstance";
import { AxiosResponse } from "axios";
export interface CreatePlanTeamDto {
name: {
am: string;
en: string;
};
description: {
am: string;
en: string;
};
teamLeaderId: string;
positionId: string;
}
export interface CreatePlanTeamMemberDto {
planTeamId: string;
employeePositionIds: string;
}
export interface CreatePlanBulkTeamMemberDto {
planTeamId: string;
employeePositionIds: string[];
}
export interface PlanTeamParams {
skip?: number;
take?: number;
orderBy?: string;
}
export interface CreatePlanTeamMemberDto {
planTeamId: string;
employeePositionId: string;
}
export const getPlanTeam = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.get(`/plan-teams/${id}`, {
headers: withHeaders(),
});
};
export const updatePlanTeam = async (
id: string,
data: CreatePlanTeamDto
): Promise<AxiosResponse> => {
return performanceInstance.put(`/plan-teams/${id}`, data, {
headers: withHeaders(),
});
};
export const deletePlanTeam = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.delete(`/plan-teams/${id}`, {
headers: withHeaders(),
});
};
export const createPlanTeam = async (
data: CreatePlanTeamDto
): Promise<AxiosResponse> => {
return performanceInstance.post(`/plan-teams`, data, {
headers: withHeaders(),
});
};
export const getPlanTeamList = async (
id: string,
params?: PlanTeamParams
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plan-teams/list/${id}`, {
headers: withHeaders(),
params,
});
};
export const getPlanTeamMembers = async (
id: string
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plan-team-members/${id}`, {
headers: withHeaders(),
});
};
export const createPlanTeamMember = async (
data: CreatePlanTeamMemberDto
): Promise<AxiosResponse> => {
return performanceInstance.post(`/plan-team-members`, data, {
headers: withHeaders(),
});
};
export const createPlanBulkTeamMember = async (
data: CreatePlanBulkTeamMemberDto
): Promise<AxiosResponse> => {
return performanceInstance.post(`/plan-team-members/bulk-create`, data, {
headers: withHeaders(),
});
};
export const deletePlanTeamMember = async (
id: string
): Promise<AxiosResponse> => {
return performanceInstance.delete(`/plan-team-members/${id}`, {
headers: withHeaders(),
});
};
export const updatePlanTeamMember = async (
id: string,
data: CreatePlanTeamMemberDto
): Promise<AxiosResponse> => {
return performanceInstance.put(`/plan-team-members/${id}`, data, {
headers: withHeaders(),
});
};
export const getPlanTeamMemberList = async (
id: string,
params?: PlanTeamParams
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plan-team-members/list/${id}`, {
headers: withHeaders(),
params,
});
};

View File

@@ -0,0 +1,90 @@
import { withHeaders } from "@/record-management/services/api/withHeaders";
import performanceInstance from "@/shared/services/performanceInstance";
import { AxiosResponse } from "axios";
import { CreatePlanYearDto } from "../../types/planYearTypes";
export interface PlanYearParams {
skip?: number;
take?: number;
orderBy?: string;
isActive?: boolean;
}
// Get all plan years
export const getPlanYears = async (
organizationId: string,
params?: PlanYearParams
): Promise<AxiosResponse> => {
return performanceInstance.get(`/plan-years/list/${organizationId}`, {
headers: withHeaders(),
params,
});
};
// Get single plan year by ID
export const getPlanYear = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.get(`/plan-years/${id}`, {
headers: withHeaders(),
});
};
// Create new plan year
export const createPlanYear = async (
data: CreatePlanYearDto
): Promise<AxiosResponse> => {
// return new Promise((resolve) => {
// setTimeout(() => {
// resolve({
// data: { ...data, id: `py-${data.year}` },
// status: 201,
// statusText: "Created",
// headers: {},
// config: {} as any,
// });
// }, 500);
// });
return performanceInstance.post("/plan-years", data, {
headers: withHeaders(),
});
};
// Update existing plan year
export const updatePlanYear = async (
data: CreatePlanYearDto
): Promise<AxiosResponse> => {
// return new Promise((resolve) => {
// setTimeout(() => {
// resolve({
// data: data,
// status: 200,
// statusText: "OK",
// headers: {},
// config: {} as any,
// });
// }, 500);
// });
return performanceInstance.put(`/plan-years/${data.id}`, data, {
headers: withHeaders(),
});
};
// Delete plan year
export const deletePlanYear = async (id: string): Promise<AxiosResponse> => {
// return new Promise((resolve) => {
// setTimeout(() => {
// resolve({
// data: { success: true },
// status: 200,
// statusText: "OK",
// headers: {},
// config: {} as any,
// });
// }, 500);
// });
return performanceInstance.delete(`/plan-years/${id}`, {
headers: withHeaders(),
});
};

View File

@@ -0,0 +1,125 @@
import performanceInstance from "@/shared/services/performanceInstance";
import { withHeaders } from "@/record-management/services/api/withHeaders";
import { AxiosResponse } from "axios";
export interface ServiceAssignment {
id: string;
positionId: string;
serviceId: string;
assignedAt: string;
}
export interface AssignServicesPayload {
positionId: string;
serviceIds: string[];
}
/**
* Fetch services assigned to a specific position
* Returns the service (second) assigned to a position (first)
*/
export const getAssignedServices = async (
positionId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(
`/position-services/seconds-for-first/${positionId}`,
{
headers: withHeaders(),
}
);
};
/**
* Assign service(s) to a position
* API expects: firstIds (positions array) and secondId (service)
*/
export const assignServicesToPosition = async (
positionId: string,
serviceIds: string[]
): Promise<AxiosResponse> => {
return performanceInstance.post(
`/position-services/assign-firsts-for-second`,
{
firstIds: [positionId],
secondId: serviceIds[0], // Single service ID
},
{
headers: withHeaders(),
}
);
};
/**
* Remove a service assignment from a position
*/
export const removeServiceFromPosition = async (
positionId: string,
serviceId: string
): Promise<AxiosResponse> => {
return performanceInstance.delete(
`/positions/${positionId}/services/${serviceId}`,
{
headers: withHeaders(),
}
);
};
/**
* Get all services for a specific organization
*/
export const getServicesByOrganization = async (
organizationId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(`/services/list/${organizationId}`, {
headers: withHeaders(),
});
};
// Keep backward compatibility
export const getServicesByUnit = getServicesByOrganization;
/**
* Get all services (active and published) - deprecated, use getServicesByUnit
*/
export const getAvailableServices = async (): Promise<AxiosResponse> => {
return performanceInstance.get("/services", {
headers: withHeaders(),
params: {
isActive: true,
status: "PUBLISHED",
},
});
};
/**
* Get services associated with a position (using position endpoint)
*/
export const getPositionServices = async (
positionId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(`/position-services/position/${positionId}`, {
headers: withHeaders(),
});
};
/**
* Get position services by position ID (for working days configuration)
*/
export const getPositionServicesByPositionId = async (
positionId: string
): Promise<AxiosResponse> => {
return performanceInstance.get(`/position-services/position/${positionId}`, {
headers: withHeaders(),
});
};
/**
* Delete a position service by ID
*/
export const deletePositionService = async (
positionServiceId: string
): Promise<AxiosResponse> => {
return performanceInstance.delete(`/position-services/${positionServiceId}`, {
headers: withHeaders(),
});
};

View File

@@ -0,0 +1,66 @@
import { AxiosResponse } from "axios";
import performanceInstance from "@/shared/services/performanceInstance";
import { withHeaders } from "@/record-management/services/api/withHeaders";
export interface ServiceCategory {
id: string;
slug: string;
name: {
am: string;
en: string;
};
description: {
am: string;
en: string;
};
organizationId: string;
createdAt: string;
updatedAt?: string;
}
export interface CreateServiceCategoryRequest {
slug: string;
name: {
am: string;
en: string;
};
description: {
am: string;
en: string;
};
organizationId: string;
}
export const serviceCategoryService = {
create: async (
data: CreateServiceCategoryRequest
): Promise<AxiosResponse> => {
return performanceInstance.post("/service-categories", data, {
headers: withHeaders(),
});
},
getList: async (organizationId: string): Promise<AxiosResponse> => {
return performanceInstance.get(
`/service-categories/list/${organizationId}`,
{
headers: withHeaders(),
}
);
},
update: async (
id: string,
data: CreateServiceCategoryRequest
): Promise<AxiosResponse> => {
return performanceInstance.put(`/service-categories/${id}`, data, {
headers: withHeaders(),
});
},
delete: async (id: string): Promise<AxiosResponse> => {
return performanceInstance.delete(`/service-categories/${id}`, {
headers: withHeaders(),
});
},
};

View File

@@ -0,0 +1,52 @@
import { AxiosResponse } from "axios";
import performanceInstance from "@/shared/services/performanceInstance";
import { withHeaders } from "@/record-management/services/api/withHeaders";
import { CreateWorkingHoursDto } from "@/performance-management/types/workingHoursTypes";
export const createWorkingHours = async (
data: CreateWorkingHoursDto
): Promise<AxiosResponse> => {
return performanceInstance.post("/working-days", data, {
headers: withHeaders(),
});
};
export const getWorkingHours = async (id: string): Promise<AxiosResponse> => {
return performanceInstance.get(`/working-days/${id}`, {
headers: withHeaders(),
});
};
export const getWorkingHoursList = async (): Promise<AxiosResponse> => {
return performanceInstance.get("/working-days", {
headers: withHeaders(),
});
};
export const getWorkingHoursByPositionServiceId = async (
positionServiceId: string
): Promise<AxiosResponse> => {
return performanceInstance.get("/working-days", {
headers: withHeaders(),
params: {
positionServiceId,
},
});
};
export const updateWorkingHours = async (
id: string,
data: CreateWorkingHoursDto
): Promise<AxiosResponse> => {
return performanceInstance.put(`/working-days/${id}`, data, {
headers: withHeaders(),
});
};
export const deleteWorkingHours = async (
id: string
): Promise<AxiosResponse> => {
return performanceInstance.delete(`/working-days/${id}`, {
headers: withHeaders(),
});
};