239 行
6.0 KiB
TypeScript
239 行
6.0 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 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 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 }),
|
|
});
|
|
}
|