文件
hyb-oa/client/src/api/leave.ts
T

259 行
6.5 KiB
TypeScript

import { apiRequestData } from "./http";
export type LeaveSession = "am" | "pm";
export type LeaveRequestStatus = "draft" | "reviewing" | "approved" | "rejected" | "cancelled";
export type LeaveType = {
id: string;
code: string;
name: string;
description: string | null;
enabled: boolean;
requiresAttachment: boolean;
attachmentMimeTypes: string[];
sortOrder: number;
policy: {
id: string;
annualQuotaDays: number;
enabled: boolean;
description: string | null;
} | null;
createdAt: string | null;
updatedAt: string | null;
};
export type LeaveBalanceItem = {
leaveType: LeaveType;
policy: {
id: string;
annualQuotaDays: number;
enabled: boolean;
description: string | null;
};
granted: number;
adjusted: number;
reserved: number;
used: number;
available: number;
periodStart: string | null;
periodEnd: string | null;
};
export type LeaveRequestItem = {
id: string;
ownerId: string;
departmentId: string;
status: LeaveRequestStatus;
startDate: string;
endDate: string;
startSession: LeaveSession;
endSession: LeaveSession;
requestedDays: number;
reason: string | null;
attachment: {
originalName: string | null;
mimeType: string | null;
} | null;
leaveType: {
id: string;
code: string;
name: string;
requiresAttachment: boolean;
attachmentMimeTypes: string[];
} | null;
owner: {
id: string;
employeeNo: string;
name: string;
} | null;
createdAt: string | null;
updatedAt: string | null;
};
export type LeaveRequestListResponse = {
page: number;
pageSize: number;
total: number;
scope: "own" | "all";
items: LeaveRequestItem[];
};
export type LeaveBalanceResponse = {
employeeId: string;
items: LeaveBalanceItem[];
};
export type LeaveWorkingDaysPreview = {
requestedDays: number;
naturalRequestedDays: number;
holidayDayCount: number;
weekendDayCount: number;
adjustedWorkdayCount: number;
calendarApplied: boolean;
};
export type LeaveListQuery = {
status?: LeaveRequestStatus;
scope?: "own" | "all";
page?: number;
pageSize?: number;
dateFrom?: string;
dateTo?: string;
departmentId?: string;
};
function toQueryString(query: Record<string, string | number | undefined>) {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
if (value == null || value === "") {
continue;
}
params.set(key, String(value));
}
const encoded = params.toString();
return encoded ? `?${encoded}` : "";
}
export async function fetchLeaveTypes(params?: { enabled?: boolean }) {
return apiRequestData<{ items: LeaveType[] }>(
`/api/leave-types${toQueryString({ enabled: params?.enabled == null ? undefined : String(params.enabled) })}`,
);
}
export async function createLeaveType(payload: {
code: string;
name: string;
description?: string | null;
enabled?: boolean;
requiresAttachment?: boolean;
attachmentMimeTypes?: string[];
sortOrder?: number;
annualQuotaDays: number;
policyDescription?: string | null;
}) {
return apiRequestData<LeaveType>("/api/leave-types", {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function patchLeaveType(
leaveTypeId: string,
payload: Partial<{
code: string;
name: string;
description: string | null;
enabled: boolean;
requiresAttachment: boolean;
attachmentMimeTypes: string[];
sortOrder: number;
annualQuotaDays: number;
policyDescription: string | null;
}>,
) {
return apiRequestData<LeaveType>(`/api/leave-types/${leaveTypeId}`, {
method: "PATCH",
body: JSON.stringify(payload),
});
}
export async function fetchLeaveBalances(employeeId?: string) {
return apiRequestData<LeaveBalanceResponse>(
`/api/leave-balances${toQueryString({ employeeId })}`,
);
}
export async function fetchLeaveRequests(query: LeaveListQuery = {}) {
return apiRequestData<LeaveRequestListResponse>(
`/api/leave-requests${toQueryString(query as Record<string, string | number | undefined>)}`,
);
}
export async function fetchLeaveRequestDetail(leaveRequestId: string) {
return apiRequestData<LeaveRequestItem>(`/api/leave-requests/${leaveRequestId}`);
}
export async function fetchLeaveWorkingDaysPreview(query: {
startDate: string;
endDate: string;
startSession: LeaveSession;
endSession: LeaveSession;
}) {
return apiRequestData<LeaveWorkingDaysPreview>(
`/api/leave-requests/working-days${toQueryString(query)}`,
);
}
export async function createLeaveRequest(payload: {
leaveTypeId: string;
startDate: string;
endDate: string;
startSession: LeaveSession;
endSession: LeaveSession;
reason?: string;
file?: File | null;
}) {
const formData = new FormData();
formData.append("leaveTypeId", payload.leaveTypeId);
formData.append("startDate", payload.startDate);
formData.append("endDate", payload.endDate);
formData.append("startSession", payload.startSession);
formData.append("endSession", payload.endSession);
if (payload.reason?.trim()) {
formData.append("reason", payload.reason.trim());
}
if (payload.file) {
formData.append("file", payload.file);
}
return apiRequestData<LeaveRequestItem>("/api/leave-requests", {
method: "POST",
body: formData,
});
}
export async function submitLeaveRequest(leaveRequestId: string) {
return apiRequestData<Record<string, unknown>>(`/api/leave-requests/${leaveRequestId}/submit`, {
method: "POST",
body: JSON.stringify({}),
});
}
export async function patchLeaveRequest(
leaveRequestId: string,
payload: {
leaveTypeId: string;
startDate: string;
endDate: string;
startSession: LeaveSession;
endSession: LeaveSession;
reason?: string;
file?: File | null;
},
) {
const formData = new FormData();
formData.append("leaveTypeId", payload.leaveTypeId);
formData.append("startDate", payload.startDate);
formData.append("endDate", payload.endDate);
formData.append("startSession", payload.startSession);
formData.append("endSession", payload.endSession);
if (payload.reason?.trim()) {
formData.append("reason", payload.reason.trim());
}
if (payload.file) {
formData.append("file", payload.file);
}
return apiRequestData<LeaveRequestItem>(`/api/leave-requests/${leaveRequestId}`, {
method: "PATCH",
body: formData,
});
}
export async function withdrawLeaveRequest(leaveRequestId: string, comment?: string) {
return apiRequestData<Record<string, unknown>>(`/api/leave-requests/${leaveRequestId}/withdraw`, {
method: "POST",
body: JSON.stringify({ comment }),
});
}