mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat: add upload document in daily checklist
This commit is contained in:
@@ -30,7 +30,7 @@ import { KandangApi } from '@/services/api/master-data';
|
||||
import { DailyChecklistApi } from '@/services/api/daily-checklist/daily-checklist';
|
||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||
import useSWR from 'swr';
|
||||
import { BaseApiResponse } from '@/types/api/api-general';
|
||||
import { BaseApiResponse, Document } from '@/types/api/api-general';
|
||||
import { AxiosError } from 'axios';
|
||||
import { httpClientFetcher, SWRHttpKey } from '@/services/http/client';
|
||||
import { PhaseApi } from '@/services/api/daily-checklist/phase';
|
||||
@@ -39,6 +39,9 @@ import { Employee } from '@/types/api/daily-checklist/employee';
|
||||
import { PhaseActivityApi } from '@/services/api/daily-checklist/phase-activity';
|
||||
import { PhaseActivity } from '@/types/api/daily-checklist/phase-activity';
|
||||
import DebouncedTextArea from '@/components/input/DebouncedTextArea';
|
||||
import DropFileInput from '@/components/input/DropFileInput';
|
||||
import Link from 'next/link';
|
||||
import { Icon } from '@iconify/react';
|
||||
|
||||
// Static categories
|
||||
const CATEGORIES = [
|
||||
@@ -148,6 +151,10 @@ export function DailyChecklistContent() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [initialLoading, setInitialLoading] = useState(true);
|
||||
|
||||
const [existingDocuments, setExistingDocuments] = useState<Document[]>([]);
|
||||
const [documents, setDocuments] = useState<File[]>([]);
|
||||
const [deletedDocumentIds, setDeletedDocumentIds] = useState<number[]>([]);
|
||||
|
||||
// Format date for display
|
||||
const formatDateForDisplay = (dateStr: string) => {
|
||||
if (!dateStr) return 'Pilih tanggal';
|
||||
@@ -340,6 +347,9 @@ export function DailyChecklistContent() {
|
||||
return;
|
||||
}
|
||||
|
||||
// set existing document
|
||||
setExistingDocuments(existingDailyChecklist?.data.document_urls || []);
|
||||
|
||||
// Build assignments map
|
||||
const assignmentMap: {
|
||||
[taskId: string]: {
|
||||
@@ -729,7 +739,11 @@ export function DailyChecklistContent() {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const submitRes = await DailyChecklistApi.submit(dailyChecklistId);
|
||||
const submitRes = await DailyChecklistApi.submit(
|
||||
dailyChecklistId,
|
||||
documents,
|
||||
deletedDocumentIds
|
||||
);
|
||||
|
||||
if (isResponseError(submitRes)) {
|
||||
console.error('Error submitting:', submitRes.message);
|
||||
@@ -750,6 +764,19 @@ export function DailyChecklistContent() {
|
||||
const handleSaveDraft = async () => {
|
||||
if (!dailyChecklistId) return;
|
||||
|
||||
const uploadImageRes = await DailyChecklistApi.uploadImage(
|
||||
Number(dailyChecklistId),
|
||||
'DRAFT',
|
||||
documents,
|
||||
deletedDocumentIds
|
||||
);
|
||||
|
||||
if (isResponseError(uploadImageRes)) {
|
||||
console.error('Error saving draft:', uploadImageRes.message);
|
||||
toast.error('Gagal menyimpan draft');
|
||||
return;
|
||||
}
|
||||
|
||||
toast.success('Draft tersimpan otomatis');
|
||||
};
|
||||
|
||||
@@ -1263,6 +1290,94 @@ export function DailyChecklistContent() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{dailyChecklistId &&
|
||||
selectedPhaseIds.length > 0 &&
|
||||
selectedEmployees.length > 0 && (
|
||||
<>
|
||||
{existingDocuments.length > 0 && (
|
||||
<div className='mt-6'>
|
||||
<h3 className='font-semibold text-gray-900 mb-2'>
|
||||
Dokumen yang telah diupload
|
||||
</h3>
|
||||
{existingDocuments.map(
|
||||
(existingDocument, existingDocumentIdx) => (
|
||||
<div
|
||||
key={existingDocumentIdx}
|
||||
className='w-full flex flex-wrap justify-between'
|
||||
>
|
||||
<Link
|
||||
href={existingDocument.url}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='text-blue-500 underline'
|
||||
>
|
||||
{existingDocument.name}{' '}
|
||||
<Icon
|
||||
icon='cuida:open-in-new-tab-outline'
|
||||
width={12}
|
||||
height={12}
|
||||
className='inline'
|
||||
/>
|
||||
</Link>
|
||||
|
||||
<Button
|
||||
type='button'
|
||||
variant='ghost'
|
||||
color='error'
|
||||
onClick={() => {
|
||||
setDeletedDocumentIds((prevIds) => [
|
||||
...prevIds,
|
||||
existingDocument.id,
|
||||
]);
|
||||
|
||||
setExistingDocuments((prevExistingDocument) => {
|
||||
const newExistingDocuments = [
|
||||
...prevExistingDocument,
|
||||
];
|
||||
newExistingDocuments.splice(
|
||||
existingDocumentIdx,
|
||||
1
|
||||
);
|
||||
return newExistingDocuments;
|
||||
});
|
||||
}}
|
||||
className='p-1 rounded-full text-error focus-visible:text-error-content hover:text-error-content'
|
||||
>
|
||||
<Icon
|
||||
icon='fluent:delete-12-regular'
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<DropFileInput
|
||||
name='Dokumen'
|
||||
label='Dokumen'
|
||||
values={documents}
|
||||
onChange={(files) => {
|
||||
setDocuments(files);
|
||||
}}
|
||||
onDelete={(deletedFileIdx: number) => {
|
||||
const newRequestDocuments = [...documents];
|
||||
|
||||
newRequestDocuments?.splice(deletedFileIdx, 1);
|
||||
|
||||
setDocuments(newRequestDocuments);
|
||||
}}
|
||||
className={{
|
||||
wrapper: 'mt-6',
|
||||
inputWrapper: 'flex items-center',
|
||||
label: 'font-semibold text-gray-900',
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Action Buttons */}
|
||||
{dailyChecklistId &&
|
||||
selectedPhaseIds.length > 0 &&
|
||||
|
||||
Reference in New Issue
Block a user