mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
401 lines
11 KiB
TypeScript
401 lines
11 KiB
TypeScript
import axios from 'axios';
|
|
import * as XLSX from 'xlsx';
|
|
|
|
import { BaseApiService } from '@/services/api/base';
|
|
import { httpClient, httpClientFetcher } from '@/services/http/client';
|
|
import { BaseApiResponse } from '@/types/api/api-general';
|
|
import {
|
|
CreateDailyChecklistPayload,
|
|
DailyChecklist,
|
|
DailyChecklistReport,
|
|
DetailDailyChecklist,
|
|
UpdateDailyChecklistPayload,
|
|
} from '@/types/api/daily-checklist/daily-checklist';
|
|
import { isResponseError } from '@/lib/api-helper';
|
|
import { toast } from 'sonner';
|
|
|
|
export class DailyChecklistApiService extends BaseApiService<
|
|
DailyChecklist,
|
|
CreateDailyChecklistPayload,
|
|
UpdateDailyChecklistPayload
|
|
> {
|
|
constructor(basePath: string = '/daily-checklists') {
|
|
super(basePath);
|
|
}
|
|
|
|
async update(id: number, payload: UpdateDailyChecklistPayload) {
|
|
const isFormData =
|
|
typeof FormData !== 'undefined' && payload instanceof FormData;
|
|
try {
|
|
const updatePath = `${this.basePath}/${id}`;
|
|
|
|
const headers = isFormData
|
|
? { ...(this.header ?? {}) }
|
|
: { 'Content-Type': 'application/json', ...(this.header ?? {}) };
|
|
|
|
const updateRes = await httpClient<BaseApiResponse<DailyChecklist>>(
|
|
updatePath,
|
|
{
|
|
method: 'PUT',
|
|
body: payload,
|
|
headers,
|
|
}
|
|
);
|
|
return updateRes;
|
|
} catch (error: unknown) {
|
|
if (axios.isAxiosError<BaseApiResponse<DailyChecklist>>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async getOneDailyChecklist(id: string) {
|
|
try {
|
|
const getOneDailyChecklistPath = `${this.basePath}/relation/${id}`;
|
|
const getOneDailyChecklistRes = await httpClient<
|
|
BaseApiResponse<DetailDailyChecklist>
|
|
>(getOneDailyChecklistPath);
|
|
|
|
return getOneDailyChecklistRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse<DetailDailyChecklist>>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async setDailyChecklistPhase(id: string, phaseIds: string[]) {
|
|
try {
|
|
const setDailyChecklistPhasePath = `${this.basePath}/phase/${id}`;
|
|
const setDailyChecklistPhaseRes = await httpClient<BaseApiResponse>(
|
|
setDailyChecklistPhasePath,
|
|
{
|
|
method: 'POST',
|
|
body: { phase_ids: phaseIds.join(',') },
|
|
}
|
|
);
|
|
|
|
return setDailyChecklistPhaseRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async removeEmployeeAssignment(id: string, employeeId: string) {
|
|
try {
|
|
const removeEmployeeAssignmentPath = `${this.basePath}/${id}/assignments/${employeeId}`;
|
|
const removeEmployeeAssignmentRes = await httpClient<BaseApiResponse>(
|
|
removeEmployeeAssignmentPath,
|
|
{
|
|
method: 'DELETE',
|
|
}
|
|
);
|
|
|
|
return removeEmployeeAssignmentRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async setDailyChecklistEmployees(checklistId: string, employeeIds: string[]) {
|
|
try {
|
|
const setDailyChecklistPhasePath = `${this.basePath}/assignment/${checklistId}`;
|
|
const setDailyChecklistPhaseRes = await httpClient<BaseApiResponse>(
|
|
setDailyChecklistPhasePath,
|
|
{
|
|
method: 'POST',
|
|
body: { employee_ids: employeeIds.join(',') },
|
|
}
|
|
);
|
|
|
|
return setDailyChecklistPhaseRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async getTasksByChecklistId(id: string) {
|
|
try {
|
|
const getTasksByChecklistIdPath = `${this.basePath}/tasks?checklist_id=${id}&page=1&limit=100`;
|
|
const getTasksByChecklistIdRes = await httpClient<BaseApiResponse>(
|
|
getTasksByChecklistIdPath
|
|
);
|
|
|
|
return getTasksByChecklistIdRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async checkOrUncheckAssignment(payload: {
|
|
task_id: number;
|
|
employee_id: number;
|
|
checked: boolean;
|
|
note: string | null;
|
|
}) {
|
|
try {
|
|
const checkOrUncheckAssignmentPath = `${this.basePath}/assignment`;
|
|
const checkOrUncheckAssignmentRes = await httpClient<BaseApiResponse>(
|
|
checkOrUncheckAssignmentPath,
|
|
{
|
|
method: 'POST',
|
|
body: payload,
|
|
}
|
|
);
|
|
|
|
return checkOrUncheckAssignmentRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async submit(
|
|
id: string,
|
|
files: File[] = [],
|
|
deletedDocumentIds: number[] = []
|
|
) {
|
|
try {
|
|
const formData = new FormData();
|
|
|
|
formData.append('status', 'SUBMITTED');
|
|
|
|
formData.append('reject_reason', '');
|
|
|
|
files.forEach((file) => formData.append(`documents`, file));
|
|
|
|
formData.append('deleted_document_ids', deletedDocumentIds.join(','));
|
|
|
|
const submitPath = `${this.basePath}/${id}`;
|
|
const submitRes = await httpClient<BaseApiResponse>(submitPath, {
|
|
method: 'PATCH',
|
|
body: formData,
|
|
});
|
|
|
|
return submitRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async approve(id: string) {
|
|
try {
|
|
const formData = new FormData();
|
|
|
|
formData.append('status', 'APPROVED');
|
|
|
|
formData.append('reject_reason', '');
|
|
|
|
const approvePath = `${this.basePath}/${id}`;
|
|
const approveRes = await httpClient<BaseApiResponse>(approvePath, {
|
|
method: 'PATCH',
|
|
body: formData,
|
|
});
|
|
|
|
return approveRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async bulkApprove(ids: string[]) {
|
|
try {
|
|
const formData = new FormData();
|
|
|
|
formData.append('ids', ids.join(','));
|
|
formData.append('status', 'APPROVED');
|
|
formData.append('reject_reason', '');
|
|
|
|
const approvePath = `${this.basePath}/bulk-update`;
|
|
const approveRes = await httpClient<BaseApiResponse>(approvePath, {
|
|
method: 'PATCH',
|
|
body: formData,
|
|
});
|
|
|
|
return approveRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async reject(id: string, rejectReason: string) {
|
|
try {
|
|
const formData = new FormData();
|
|
|
|
formData.append('status', 'REJECTED');
|
|
|
|
formData.append('reject_reason', rejectReason);
|
|
|
|
const rejectPath = `${this.basePath}/${id}`;
|
|
const rejectRes = await httpClient<BaseApiResponse>(rejectPath, {
|
|
method: 'PATCH',
|
|
body: formData,
|
|
});
|
|
|
|
return rejectRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async bulkReject(ids: string[], rejectReason: string) {
|
|
try {
|
|
const formData = new FormData();
|
|
|
|
formData.append('ids', ids.join(','));
|
|
formData.append('status', 'REJECTED');
|
|
formData.append('reject_reason', rejectReason);
|
|
|
|
const rejectPath = `${this.basePath}/bulk-update`;
|
|
const rejectRes = await httpClient<BaseApiResponse>(rejectPath, {
|
|
method: 'PATCH',
|
|
body: formData,
|
|
});
|
|
|
|
return rejectRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async uploadImage(
|
|
id: number,
|
|
status: string,
|
|
files: File[],
|
|
deletedDocumentIds: number[] = []
|
|
) {
|
|
try {
|
|
const formData = new FormData();
|
|
|
|
formData.append('status', status);
|
|
|
|
files.forEach((file) => formData.append(`documents`, file));
|
|
|
|
formData.append('deleted_document_ids', deletedDocumentIds.join(','));
|
|
|
|
const uploadImagePath = `${this.basePath}/${id}`;
|
|
const uploadImageRes = await httpClient<BaseApiResponse>(
|
|
uploadImagePath,
|
|
{
|
|
method: 'PATCH',
|
|
body: formData,
|
|
}
|
|
);
|
|
|
|
return uploadImageRes;
|
|
} catch (error) {
|
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
|
return error.response?.data;
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
async exportDailyChecklistReportToExcel(initialQueryString: string) {
|
|
const params = new URLSearchParams(initialQueryString);
|
|
|
|
params.set('limit', '2000');
|
|
|
|
const queryString = `?${params.toString()}`;
|
|
|
|
try {
|
|
const dailyMarketingsReport = await httpClientFetcher<
|
|
BaseApiResponse<DailyChecklistReport[]>
|
|
>(`${this.basePath}/report${queryString}`);
|
|
|
|
if (isResponseError(dailyMarketingsReport)) {
|
|
toast.error('Gagal melakukan export daily checklist! Coba lagi.');
|
|
return;
|
|
}
|
|
|
|
const currentMonthMaxDay = new Date(
|
|
Number(params.get('tahun')),
|
|
Number(params.get('bulan')),
|
|
0
|
|
).getDate();
|
|
|
|
const rows = dailyMarketingsReport.data;
|
|
|
|
const formattedRows = [];
|
|
|
|
for (let i = 0; i < rows.length; i++) {
|
|
const formattedData: Record<string, string | number> = {
|
|
Area: rows[i].area.name,
|
|
Farm: rows[i].farm.name,
|
|
Kandang: rows[i].kandang.name,
|
|
ABK: rows[i].abk.name,
|
|
Phase: rows[i].phase,
|
|
};
|
|
|
|
// Add day
|
|
for (let j = 1; j <= currentMonthMaxDay; j++) {
|
|
formattedData[`Day ${j}`] = rows[i].daily_activities[`${j}`];
|
|
}
|
|
|
|
// add summary
|
|
formattedData['Total Checklist'] = rows[i].summary.total_checklist;
|
|
formattedData['Jumlah Hari Efektif'] =
|
|
rows[i].summary.jumlah_hari_efektif;
|
|
formattedData['ABK %'] = rows[i].summary.abk_percentage;
|
|
formattedData['Kandang %'] = rows[i].summary.kandang_percentage;
|
|
formattedData['Kategori Kurang'] = rows[i].summary.kategori.kurang;
|
|
formattedData['Kategori Cukup'] = rows[i].summary.kategori.cukup;
|
|
formattedData['Kategori Baik'] = rows[i].summary.kategori.baik;
|
|
|
|
formattedRows.push(formattedData);
|
|
}
|
|
|
|
const ws = XLSX.utils.json_to_sheet(formattedRows);
|
|
const wb = XLSX.utils.book_new();
|
|
XLSX.utils.book_append_sheet(
|
|
wb,
|
|
ws,
|
|
`Daily Checklist ${params.get('tahun')}-${params.get('bulan')?.slice(0, 3)}`
|
|
);
|
|
|
|
// triggers download in browser
|
|
XLSX.writeFile(
|
|
wb,
|
|
`laporan-daily-checklist-${params.get('tahun')}-${params.get('bulan')}.xlsx`
|
|
);
|
|
} catch {
|
|
toast.error('Gagal melakukan export daily checklist! Coba lagi.');
|
|
}
|
|
}
|
|
}
|
|
|
|
export const DailyChecklistApi = new DailyChecklistApiService(
|
|
'/daily-checklists'
|
|
);
|