mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 05:22:02 +00:00
Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist See merge request mbugroup/lti-web-client!224
This commit is contained in:
@@ -28,7 +28,7 @@ export const MAIN_DRAWER_LINKS: SidebarMenuItem[] = [
|
|||||||
permission: ['lti.daily_checklist.dashboard.list'],
|
permission: ['lti.daily_checklist.dashboard.list'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Daily Checklist',
|
text: 'Formulir',
|
||||||
link: '/daily-checklist/daily-checklist',
|
link: '/daily-checklist/daily-checklist',
|
||||||
icon: 'lucide:clipboard-check',
|
icon: 'lucide:clipboard-check',
|
||||||
permission: ['lti.daily_checklist.create'],
|
permission: ['lti.daily_checklist.create'],
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import { PhaseActivity } from '@/types/api/daily-checklist/phase-activity';
|
|||||||
import DebouncedTextArea from '@/components/input/DebouncedTextArea';
|
import DebouncedTextArea from '@/components/input/DebouncedTextArea';
|
||||||
import DropFileInput from '@/components/input/DropFileInput';
|
import DropFileInput from '@/components/input/DropFileInput';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { useRouter, useSearchParams, usePathname } from 'next/navigation';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
|
|
||||||
// Static categories
|
// Static categories
|
||||||
@@ -51,7 +52,7 @@ const CATEGORIES = [
|
|||||||
{ value: 'produksi_close', label: 'Produksi Close' },
|
{ value: 'produksi_close', label: 'Produksi Close' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const TIME_TYPE_ORDER = ['umum', 'pagi', 'siang', 'sore', 'malam'];
|
const TIME_TYPE_ORDER = ['Umum', 'Pagi', 'Siang', 'Sore', 'Malam'];
|
||||||
const TIME_TYPE_LABELS: { [key: string]: string } = {
|
const TIME_TYPE_LABELS: { [key: string]: string } = {
|
||||||
Umum: 'Umum',
|
Umum: 'Umum',
|
||||||
Pagi: 'Pagi',
|
Pagi: 'Pagi',
|
||||||
@@ -67,7 +68,23 @@ interface Phase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function DailyChecklistContent() {
|
export function DailyChecklistContent() {
|
||||||
const [kandangId, setKandangId] = useState('');
|
const router = useRouter();
|
||||||
|
const pathname = usePathname();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
|
const [kandangId, setKandangId] = useState(
|
||||||
|
searchParams.get('kandang_id') || ''
|
||||||
|
);
|
||||||
|
const [date, setDate] = useState(() => {
|
||||||
|
const paramDate = searchParams.get('date');
|
||||||
|
if (paramDate) return paramDate;
|
||||||
|
|
||||||
|
const today = new Date();
|
||||||
|
return today.toISOString().split('T')[0];
|
||||||
|
});
|
||||||
|
const [selectedCategory, setSelectedCategory] = useState(
|
||||||
|
searchParams.get('category') || ''
|
||||||
|
);
|
||||||
|
|
||||||
const { options: kandangOptions, isLoadingOptions: isLoadingKandangs } =
|
const { options: kandangOptions, isLoadingOptions: isLoadingKandangs } =
|
||||||
useSelect(KandangApi.basePath, 'id', 'name', 'search', {
|
useSelect(KandangApi.basePath, 'id', 'name', 'search', {
|
||||||
@@ -104,12 +121,6 @@ export function DailyChecklistContent() {
|
|||||||
? employeesRes.data || []
|
? employeesRes.data || []
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const [date, setDate] = useState(() => {
|
|
||||||
const today = new Date();
|
|
||||||
return today.toISOString().split('T')[0];
|
|
||||||
});
|
|
||||||
|
|
||||||
const [selectedCategory, setSelectedCategory] = useState('');
|
|
||||||
const [selectedPhaseIds, setSelectedPhaseIds] = useState<string[]>([]);
|
const [selectedPhaseIds, setSelectedPhaseIds] = useState<string[]>([]);
|
||||||
|
|
||||||
const [selectedEmployees, setSelectedEmployees] = useState<
|
const [selectedEmployees, setSelectedEmployees] = useState<
|
||||||
@@ -118,7 +129,7 @@ export function DailyChecklistContent() {
|
|||||||
|
|
||||||
const [dailyChecklistId, setDailyChecklistId] = useState<string | null>(null);
|
const [dailyChecklistId, setDailyChecklistId] = useState<string | null>(null);
|
||||||
const [checklistStatus, setChecklistStatus] = useState<string>('DRAFT');
|
const [checklistStatus, setChecklistStatus] = useState<string>('DRAFT');
|
||||||
const [isEditMode, setIsEditMode] = useState(false);
|
// const [isEditMode, setIsEditMode] = useState(false);
|
||||||
|
|
||||||
// Activities grouped by phase
|
// Activities grouped by phase
|
||||||
const [activitiesByPhase, setActivitiesByPhase] = useState<{
|
const [activitiesByPhase, setActivitiesByPhase] = useState<{
|
||||||
@@ -148,13 +159,57 @@ export function DailyChecklistContent() {
|
|||||||
const [searchAbk, setSearchAbk] = useState('');
|
const [searchAbk, setSearchAbk] = useState('');
|
||||||
const [searchPhase, setSearchPhase] = useState('');
|
const [searchPhase, setSearchPhase] = useState('');
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [isLoadingSubmit, setIsLoadingSubmit] = useState(false);
|
||||||
|
const [isLoadingDraft, setIsLoadingDraft] = useState(false);
|
||||||
const [initialLoading, setInitialLoading] = useState(true);
|
const [initialLoading, setInitialLoading] = useState(true);
|
||||||
|
|
||||||
const [existingDocuments, setExistingDocuments] = useState<Document[]>([]);
|
const [existingDocuments, setExistingDocuments] = useState<Document[]>([]);
|
||||||
const [documents, setDocuments] = useState<File[]>([]);
|
const [documents, setDocuments] = useState<File[]>([]);
|
||||||
const [deletedDocumentIds, setDeletedDocumentIds] = useState<number[]>([]);
|
const [deletedDocumentIds, setDeletedDocumentIds] = useState<number[]>([]);
|
||||||
|
|
||||||
|
// Sync state to URL query params
|
||||||
|
useEffect(() => {
|
||||||
|
const params = new URLSearchParams(searchParams.toString());
|
||||||
|
let pendingUpdate = false;
|
||||||
|
|
||||||
|
// Sync date
|
||||||
|
if (date) {
|
||||||
|
if (params.get('date') !== date) {
|
||||||
|
params.set('date', date);
|
||||||
|
pendingUpdate = true;
|
||||||
|
}
|
||||||
|
} else if (params.has('date')) {
|
||||||
|
params.delete('date');
|
||||||
|
pendingUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync kandang_id
|
||||||
|
if (kandangId) {
|
||||||
|
if (params.get('kandang_id') !== kandangId) {
|
||||||
|
params.set('kandang_id', kandangId);
|
||||||
|
pendingUpdate = true;
|
||||||
|
}
|
||||||
|
} else if (params.has('kandang_id')) {
|
||||||
|
params.delete('kandang_id');
|
||||||
|
pendingUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync category
|
||||||
|
if (selectedCategory) {
|
||||||
|
if (params.get('category') !== selectedCategory) {
|
||||||
|
params.set('category', selectedCategory);
|
||||||
|
pendingUpdate = true;
|
||||||
|
}
|
||||||
|
} else if (params.has('category')) {
|
||||||
|
params.delete('category');
|
||||||
|
pendingUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pendingUpdate) {
|
||||||
|
router.replace(`${pathname}?${params.toString()}`);
|
||||||
|
}
|
||||||
|
}, [date, kandangId, selectedCategory, pathname, router, searchParams]);
|
||||||
|
|
||||||
// Format date for display
|
// Format date for display
|
||||||
const formatDateForDisplay = (dateStr: string) => {
|
const formatDateForDisplay = (dateStr: string) => {
|
||||||
if (!dateStr) return 'Pilih tanggal';
|
if (!dateStr) return 'Pilih tanggal';
|
||||||
@@ -179,7 +234,7 @@ export function DailyChecklistContent() {
|
|||||||
if (!date || !kandangId || !selectedCategory) {
|
if (!date || !kandangId || !selectedCategory) {
|
||||||
setDailyChecklistId(null);
|
setDailyChecklistId(null);
|
||||||
setChecklistStatus('DRAFT');
|
setChecklistStatus('DRAFT');
|
||||||
setIsEditMode(false);
|
// setIsEditMode(false);
|
||||||
setSelectedPhaseIds([]);
|
setSelectedPhaseIds([]);
|
||||||
setActivitiesByPhase({});
|
setActivitiesByPhase({});
|
||||||
setTaskIdsByPhaseActivityId({});
|
setTaskIdsByPhaseActivityId({});
|
||||||
@@ -216,7 +271,7 @@ export function DailyChecklistContent() {
|
|||||||
existingPhases.data.phases.length > 0
|
existingPhases.data.phases.length > 0
|
||||||
) {
|
) {
|
||||||
// Existing checklist - EDIT MODE
|
// Existing checklist - EDIT MODE
|
||||||
setIsEditMode(true);
|
// setIsEditMode(true);
|
||||||
const phaseIds = existingPhases.data.phases.map((p) =>
|
const phaseIds = existingPhases.data.phases.map((p) =>
|
||||||
String(p.phase_id)
|
String(p.phase_id)
|
||||||
);
|
);
|
||||||
@@ -234,7 +289,7 @@ export function DailyChecklistContent() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// New checklist - CREATE MODE
|
// New checklist - CREATE MODE
|
||||||
setIsEditMode(false);
|
// setIsEditMode(false);
|
||||||
setSelectedPhaseIds([]);
|
setSelectedPhaseIds([]);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -608,7 +663,7 @@ export function DailyChecklistContent() {
|
|||||||
// taskId,
|
// taskId,
|
||||||
// hasTaskId: !!taskId,
|
// hasTaskId: !!taskId,
|
||||||
// checklistStatus,
|
// checklistStatus,
|
||||||
// isEditable,
|
// isChecklistStatusDraft,
|
||||||
// });
|
// });
|
||||||
|
|
||||||
if (!taskId) {
|
if (!taskId) {
|
||||||
@@ -618,7 +673,7 @@ export function DailyChecklistContent() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEditable) {
|
if (!isChecklistStatusDraft) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'[CHECKBOX] Checklist is not editable, status:',
|
'[CHECKBOX] Checklist is not editable, status:',
|
||||||
checklistStatus
|
checklistStatus
|
||||||
@@ -736,7 +791,7 @@ export function DailyChecklistContent() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(true);
|
setIsLoadingSubmit(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const submitRes = await DailyChecklistApi.submit(
|
const submitRes = await DailyChecklistApi.submit(
|
||||||
@@ -757,13 +812,15 @@ export function DailyChecklistContent() {
|
|||||||
console.error('Error submitting:', error);
|
console.error('Error submitting:', error);
|
||||||
toast.error('Terjadi kesalahan');
|
toast.error('Terjadi kesalahan');
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setIsLoadingSubmit(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveDraft = async () => {
|
const handleSaveDraft = async () => {
|
||||||
if (!dailyChecklistId) return;
|
if (!dailyChecklistId) return;
|
||||||
|
|
||||||
|
setIsLoadingDraft(true);
|
||||||
|
|
||||||
const uploadImageRes = await DailyChecklistApi.uploadImage(
|
const uploadImageRes = await DailyChecklistApi.uploadImage(
|
||||||
Number(dailyChecklistId),
|
Number(dailyChecklistId),
|
||||||
'DRAFT',
|
'DRAFT',
|
||||||
@@ -774,10 +831,12 @@ export function DailyChecklistContent() {
|
|||||||
if (isResponseError(uploadImageRes)) {
|
if (isResponseError(uploadImageRes)) {
|
||||||
console.error('Error saving draft:', uploadImageRes.message);
|
console.error('Error saving draft:', uploadImageRes.message);
|
||||||
toast.error('Gagal menyimpan draft');
|
toast.error('Gagal menyimpan draft');
|
||||||
|
setIsLoadingDraft(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.success('Draft tersimpan otomatis');
|
setIsLoadingDraft(false);
|
||||||
|
toast.success('Draft tersimpan!');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Filter functions
|
// Filter functions
|
||||||
@@ -825,7 +884,7 @@ export function DailyChecklistContent() {
|
|||||||
|
|
||||||
// Group activities by time_type within this phase
|
// Group activities by time_type within this phase
|
||||||
phaseActivities.forEach((activity) => {
|
phaseActivities.forEach((activity) => {
|
||||||
const timeType = activity.time_type || 'umum';
|
const timeType = activity.time_type || 'Umum';
|
||||||
|
|
||||||
if (!grouped[phase.id].timeGroups[timeType]) {
|
if (!grouped[phase.id].timeGroups[timeType]) {
|
||||||
grouped[phase.id].timeGroups[timeType] = [];
|
grouped[phase.id].timeGroups[timeType] = [];
|
||||||
@@ -838,7 +897,7 @@ export function DailyChecklistContent() {
|
|||||||
return grouped;
|
return grouped;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isEditable = checklistStatus === 'DRAFT';
|
const isChecklistStatusDraft = checklistStatus === 'DRAFT';
|
||||||
|
|
||||||
if (initialLoading) {
|
if (initialLoading) {
|
||||||
return (
|
return (
|
||||||
@@ -871,7 +930,7 @@ export function DailyChecklistContent() {
|
|||||||
<h1 className='text-2xl font-semibold text-gray-900'>
|
<h1 className='text-2xl font-semibold text-gray-900'>
|
||||||
Daily Checklist
|
Daily Checklist
|
||||||
</h1>
|
</h1>
|
||||||
{isEditMode && (
|
{isChecklistStatusDraft && (
|
||||||
<Badge
|
<Badge
|
||||||
variant='outline'
|
variant='outline'
|
||||||
className='border-amber-300 text-amber-700 bg-white'
|
className='border-amber-300 text-amber-700 bg-white'
|
||||||
@@ -907,7 +966,7 @@ export function DailyChecklistContent() {
|
|||||||
<DatePicker
|
<DatePicker
|
||||||
date={date}
|
date={date}
|
||||||
onDateChange={setDate}
|
onDateChange={setDate}
|
||||||
disabled={!isEditable}
|
disabled={!isChecklistStatusDraft}
|
||||||
placeholder='Pilih tanggal'
|
placeholder='Pilih tanggal'
|
||||||
formatDisplay={formatDateForDisplay}
|
formatDisplay={formatDateForDisplay}
|
||||||
/>
|
/>
|
||||||
@@ -921,7 +980,7 @@ export function DailyChecklistContent() {
|
|||||||
<Select
|
<Select
|
||||||
value={kandangId}
|
value={kandangId}
|
||||||
onValueChange={setKandangId}
|
onValueChange={setKandangId}
|
||||||
disabled={!isEditable}
|
disabled={!isChecklistStatusDraft}
|
||||||
>
|
>
|
||||||
<SelectTrigger
|
<SelectTrigger
|
||||||
id='kandang'
|
id='kandang'
|
||||||
@@ -949,7 +1008,7 @@ export function DailyChecklistContent() {
|
|||||||
<Select
|
<Select
|
||||||
value={selectedCategory}
|
value={selectedCategory}
|
||||||
onValueChange={setSelectedCategory}
|
onValueChange={setSelectedCategory}
|
||||||
disabled={!isEditable}
|
disabled={!isChecklistStatusDraft}
|
||||||
>
|
>
|
||||||
<SelectTrigger
|
<SelectTrigger
|
||||||
id='category'
|
id='category'
|
||||||
@@ -971,19 +1030,21 @@ export function DailyChecklistContent() {
|
|||||||
{/* Phase Selection Section */}
|
{/* Phase Selection Section */}
|
||||||
{dailyChecklistId && (
|
{dailyChecklistId && (
|
||||||
<div className='mb-6 pb-6 border-b border-gray-200'>
|
<div className='mb-6 pb-6 border-b border-gray-200'>
|
||||||
<div className='flex items-center justify-between mb-3'>
|
{isChecklistStatusDraft && (
|
||||||
<Label>Fase / Tahap</Label>
|
<div className='flex items-center justify-between mb-3'>
|
||||||
<Button
|
<Label>Fase / Tahap</Label>
|
||||||
onClick={handleAddPhase}
|
<Button
|
||||||
size='sm'
|
onClick={handleAddPhase}
|
||||||
variant='outline'
|
size='sm'
|
||||||
className='border-[#0069e0] text-[#0069e0] hover:bg-blue-50'
|
variant='outline'
|
||||||
disabled={!selectedCategory || !isEditable}
|
className='border-[#0069e0] text-[#0069e0] hover:bg-blue-50'
|
||||||
>
|
disabled={!selectedCategory || !isChecklistStatusDraft}
|
||||||
<Plus className='w-4 h-4 mr-1' />
|
>
|
||||||
Pilih Fase
|
<Plus className='w-4 h-4 mr-1' />
|
||||||
</Button>
|
Pilih Fase
|
||||||
</div>
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{selectedPhaseIds.length > 0 ? (
|
{selectedPhaseIds.length > 0 ? (
|
||||||
<div className='flex flex-wrap gap-2'>
|
<div className='flex flex-wrap gap-2'>
|
||||||
@@ -1010,19 +1071,21 @@ export function DailyChecklistContent() {
|
|||||||
{/* ABK Assignment Section */}
|
{/* ABK Assignment Section */}
|
||||||
{dailyChecklistId && selectedPhaseIds.length > 0 && (
|
{dailyChecklistId && selectedPhaseIds.length > 0 && (
|
||||||
<div className='mb-6 pb-6 border-b border-gray-200'>
|
<div className='mb-6 pb-6 border-b border-gray-200'>
|
||||||
<div className='flex items-center justify-between mb-3'>
|
{isChecklistStatusDraft && (
|
||||||
<Label>ABK Assignment</Label>
|
<div className='flex items-center justify-between mb-3'>
|
||||||
<Button
|
<Label>ABK Assignment</Label>
|
||||||
onClick={handleAddAbk}
|
<Button
|
||||||
size='sm'
|
onClick={handleAddAbk}
|
||||||
variant='outline'
|
size='sm'
|
||||||
className='border-[#0069e0] text-[#0069e0] hover:bg-blue-50'
|
variant='outline'
|
||||||
disabled={!kandangId || !isEditable}
|
className='border-[#0069e0] text-[#0069e0] hover:bg-blue-50'
|
||||||
>
|
disabled={!kandangId || !isChecklistStatusDraft}
|
||||||
<Plus className='w-4 h-4 mr-1' />
|
>
|
||||||
Tambah ABK
|
<Plus className='w-4 h-4 mr-1' />
|
||||||
</Button>
|
Tambah ABK
|
||||||
</div>
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{selectedEmployees.length > 0 ? (
|
{selectedEmployees.length > 0 ? (
|
||||||
<div className='flex flex-wrap gap-2'>
|
<div className='flex flex-wrap gap-2'>
|
||||||
@@ -1033,7 +1096,7 @@ export function DailyChecklistContent() {
|
|||||||
className='px-3 py-1.5 bg-gray-100 text-gray-700 border border-gray-200 rounded-lg'
|
className='px-3 py-1.5 bg-gray-100 text-gray-700 border border-gray-200 rounded-lg'
|
||||||
>
|
>
|
||||||
{emp.name}
|
{emp.name}
|
||||||
{isEditable && (
|
{isChecklistStatusDraft && (
|
||||||
<button
|
<button
|
||||||
onClick={() => handleRemoveAbk(String(emp.id))}
|
onClick={() => handleRemoveAbk(String(emp.id))}
|
||||||
className='ml-2 hover:text-gray-900'
|
className='ml-2 hover:text-gray-900'
|
||||||
@@ -1084,6 +1147,7 @@ export function DailyChecklistContent() {
|
|||||||
(phaseId) => {
|
(phaseId) => {
|
||||||
const phaseData = groupActivitiesByPhase()[phaseId];
|
const phaseData = groupActivitiesByPhase()[phaseId];
|
||||||
const { phase, timeGroups } = phaseData;
|
const { phase, timeGroups } = phaseData;
|
||||||
|
|
||||||
const timeTypes = Object.keys(timeGroups).sort(
|
const timeTypes = Object.keys(timeGroups).sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
TIME_TYPE_ORDER.indexOf(a) -
|
TIME_TYPE_ORDER.indexOf(a) -
|
||||||
@@ -1197,7 +1261,7 @@ export function DailyChecklistContent() {
|
|||||||
e.target.checked
|
e.target.checked
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
disabled={!isEditable}
|
disabled={!isChecklistStatusDraft}
|
||||||
className='checkbox-clean'
|
className='checkbox-clean'
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
@@ -1224,7 +1288,7 @@ export function DailyChecklistContent() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={!isEditable}
|
disabled={!isChecklistStatusDraft}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -1320,61 +1384,68 @@ export function DailyChecklistContent() {
|
|||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Button
|
{isChecklistStatusDraft && (
|
||||||
type='button'
|
<Button
|
||||||
variant='ghost'
|
type='button'
|
||||||
color='error'
|
variant='ghost'
|
||||||
onClick={() => {
|
color='error'
|
||||||
setDeletedDocumentIds((prevIds) => [
|
onClick={() => {
|
||||||
...prevIds,
|
setDeletedDocumentIds((prevIds) => [
|
||||||
existingDocument.id,
|
...prevIds,
|
||||||
]);
|
existingDocument.id,
|
||||||
|
]);
|
||||||
|
|
||||||
setExistingDocuments((prevExistingDocument) => {
|
setExistingDocuments(
|
||||||
const newExistingDocuments = [
|
(prevExistingDocument) => {
|
||||||
...prevExistingDocument,
|
const newExistingDocuments = [
|
||||||
];
|
...prevExistingDocument,
|
||||||
newExistingDocuments.splice(
|
];
|
||||||
existingDocumentIdx,
|
newExistingDocuments.splice(
|
||||||
1
|
existingDocumentIdx,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
return newExistingDocuments;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return newExistingDocuments;
|
}}
|
||||||
});
|
className='p-1 rounded-full text-error focus-visible:text-error-content hover:text-error-content'
|
||||||
}}
|
>
|
||||||
className='p-1 rounded-full text-error focus-visible:text-error-content hover:text-error-content'
|
<Icon
|
||||||
>
|
icon='fluent:delete-12-regular'
|
||||||
<Icon
|
width={20}
|
||||||
icon='fluent:delete-12-regular'
|
height={20}
|
||||||
width={20}
|
/>
|
||||||
height={20}
|
</Button>
|
||||||
/>
|
)}
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DropFileInput
|
{isChecklistStatusDraft && (
|
||||||
name='Dokumen'
|
<DropFileInput
|
||||||
label='Dokumen'
|
name='Dokumen'
|
||||||
values={documents}
|
label='Dokumen'
|
||||||
onChange={(files) => {
|
values={documents}
|
||||||
setDocuments(files);
|
onChange={(files) => {
|
||||||
}}
|
setDocuments(files);
|
||||||
onDelete={(deletedFileIdx: number) => {
|
}}
|
||||||
const newRequestDocuments = [...documents];
|
onDelete={(deletedFileIdx: number) => {
|
||||||
|
const newRequestDocuments = [...documents];
|
||||||
|
|
||||||
newRequestDocuments?.splice(deletedFileIdx, 1);
|
newRequestDocuments?.splice(deletedFileIdx, 1);
|
||||||
|
|
||||||
setDocuments(newRequestDocuments);
|
setDocuments(newRequestDocuments);
|
||||||
}}
|
}}
|
||||||
className={{
|
disabled={!isChecklistStatusDraft}
|
||||||
wrapper: 'mt-6',
|
className={{
|
||||||
inputWrapper: 'flex items-center',
|
wrapper: 'mt-6',
|
||||||
label: 'font-semibold text-gray-900',
|
inputWrapper: 'flex items-center',
|
||||||
}}
|
label: 'font-semibold text-gray-900',
|
||||||
/>
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -1382,24 +1453,30 @@ export function DailyChecklistContent() {
|
|||||||
{dailyChecklistId &&
|
{dailyChecklistId &&
|
||||||
selectedPhaseIds.length > 0 &&
|
selectedPhaseIds.length > 0 &&
|
||||||
selectedEmployees.length > 0 &&
|
selectedEmployees.length > 0 &&
|
||||||
isEditable && (
|
isChecklistStatusDraft && (
|
||||||
<div className='flex justify-end gap-3 mt-6 pt-6 border-t border-gray-200'>
|
<div className='flex justify-end gap-3 mt-6 pt-6 border-t border-gray-200'>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleSaveDraft}
|
onClick={handleSaveDraft}
|
||||||
variant='outline'
|
variant='outline'
|
||||||
disabled={loading}
|
disabled={isLoadingDraft}
|
||||||
className='border-gray-200'
|
className='border-gray-200'
|
||||||
>
|
>
|
||||||
<Save className='w-4 h-4 mr-2' />
|
<Save className='w-4 h-4 mr-2' />
|
||||||
Simpan Draft
|
{isLoadingDraft ? (
|
||||||
|
<span className='loading loading-spinner loading-sm' />
|
||||||
|
) : (
|
||||||
|
'Simpan Draft'
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
disabled={loading}
|
disabled={isLoadingSubmit}
|
||||||
className='bg-[#0069e0] hover:bg-[#0052b3] text-white'
|
className='bg-[#0069e0] hover:bg-[#0052b3] text-white'
|
||||||
>
|
>
|
||||||
<Send className='w-4 h-4 mr-2' />
|
<Send className='w-4 h-4 mr-2' />
|
||||||
Submit Checklist
|
{isLoadingSubmit
|
||||||
|
? 'Mengirim Checklist...'
|
||||||
|
: 'Submit Checklist'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -1440,7 +1517,9 @@ export function DailyChecklistContent() {
|
|||||||
if (isAllPhasesSelected) {
|
if (isAllPhasesSelected) {
|
||||||
setTempSelectedPhaseIds([]);
|
setTempSelectedPhaseIds([]);
|
||||||
} else {
|
} else {
|
||||||
setTempSelectedPhaseIds(availablePhases.map((p) => p.id));
|
setTempSelectedPhaseIds(
|
||||||
|
availablePhases.map((p) => String(p.id))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className='checkbox-clean'
|
className='checkbox-clean'
|
||||||
|
|||||||
+36
-10
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Eye, CheckCircle, XCircle, Search, Trash2 } from 'lucide-react';
|
import { Eye, CheckCircle, XCircle, Search, Trash2, Edit } from 'lucide-react';
|
||||||
import { Card, CardContent } from '@/figma-make/components/base/card';
|
import { Card, CardContent } from '@/figma-make/components/base/card';
|
||||||
import { Button } from '@/figma-make/components/base/button';
|
import { Button } from '@/figma-make/components/base/button';
|
||||||
import { Badge } from '@/figma-make/components/base/badge';
|
import { Badge } from '@/figma-make/components/base/badge';
|
||||||
@@ -121,6 +121,16 @@ export function ListDailyChecklistContent() {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEdit = (item: DailyChecklist) => {
|
||||||
|
const formattedDate = new Date(item.date).toISOString().split('T')[0];
|
||||||
|
const kandangId = item.kandang.id;
|
||||||
|
const category = item.category;
|
||||||
|
|
||||||
|
router.push(
|
||||||
|
`/daily-checklist/daily-checklist?date=${formattedDate}&kandang_id=${kandangId}&category=${category}`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const handleApprove = (item: DailyChecklist) => {
|
const handleApprove = (item: DailyChecklist) => {
|
||||||
setSelectedItem(item);
|
setSelectedItem(item);
|
||||||
setShowApproveModal(true);
|
setShowApproveModal(true);
|
||||||
@@ -377,6 +387,19 @@ export function ListDailyChecklistContent() {
|
|||||||
<Eye className='w-4 h-4 mr-1' />
|
<Eye className='w-4 h-4 mr-1' />
|
||||||
Detail
|
Detail
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{row.original.status === 'DRAFT' && (
|
||||||
|
<Button
|
||||||
|
size='sm'
|
||||||
|
variant='outline'
|
||||||
|
onClick={() => handleEdit(row.original)}
|
||||||
|
className='border-gray-200 text-gray-700 hover:bg-gray-50'
|
||||||
|
>
|
||||||
|
<Edit className='w-4 h-4 mr-1' />
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
{row.original.status === 'SUBMITTED' && (
|
{row.original.status === 'SUBMITTED' && (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
@@ -398,15 +421,18 @@ export function ListDailyChecklistContent() {
|
|||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Button
|
|
||||||
size='sm'
|
{row.original.status === 'DRAFT' && (
|
||||||
variant='destructive'
|
<Button
|
||||||
onClick={() => handleDelete(row.original)}
|
size='sm'
|
||||||
className='bg-red-600 hover:bg-red-700 text-white'
|
variant='destructive'
|
||||||
>
|
onClick={() => handleDelete(row.original)}
|
||||||
<Trash2 className='w-4 h-4 mr-1' />
|
className='bg-red-600 hover:bg-red-700 text-white'
|
||||||
Hapus
|
>
|
||||||
</Button>
|
<Trash2 className='w-4 h-4 mr-1' />
|
||||||
|
Hapus
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -389,7 +389,7 @@ export function DetailDailyChecklistContent() {
|
|||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
phaseData.activities.forEach((activityData) => {
|
phaseData.activities.forEach((activityData) => {
|
||||||
const timeType = activityData.time_type || 'umum';
|
const timeType = activityData.time_type || 'Umum';
|
||||||
|
|
||||||
if (!timeGroups[timeType]) {
|
if (!timeGroups[timeType]) {
|
||||||
timeGroups[timeType] = { activities: [] };
|
timeGroups[timeType] = { activities: [] };
|
||||||
|
|||||||
Reference in New Issue
Block a user