'use client'; import * as React from 'react'; import { useState, useEffect } from 'react'; import { Plus, X, Save, Send, Info, FilePlus, ListChecks } from 'lucide-react'; import { Card, CardContent } from '@/figma-make/components/base/card'; import { Button } from '@/figma-make/components/base/button'; import { Label } from '@/figma-make/components/base/label'; import { Input } from '@/figma-make/components/base/input'; import { Badge } from '@/figma-make/components/base/badge'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/figma-make/components/base/select'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '@/figma-make/components/base/dialog'; import { DatePicker } from '@/figma-make/components/base/date-picker'; import { toast } from 'sonner'; import { useSelect } from '@/components/input/SelectInput'; 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, 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'; import { EmployeeApi } from '@/services/api/daily-checklist/employee'; 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 { useRouter, useSearchParams, usePathname } from 'next/navigation'; import { Icon } from '@iconify/react'; // Static categories const CATEGORIES = [ { value: 'pullet_open', label: 'Pullet Open' }, { value: 'pullet_close', label: 'Pullet Close' }, { value: 'produksi_open', label: 'Produksi Open' }, { value: 'produksi_close', label: 'Produksi Close' }, ]; const TIME_TYPE_ORDER = ['Umum', 'Pagi', 'Siang', 'Sore', 'Malam']; const TIME_TYPE_LABELS: { [key: string]: string } = { Umum: 'Umum', Pagi: 'Pagi', Siang: 'Siang', Sore: 'Sore', Malam: 'Malam', }; interface Phase { id: string; name: 'string'; category: string; } export function DailyChecklistContent() { 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 } = useSelect(KandangApi.basePath, 'id', 'name', 'search', { page: '1', limit: '100', }); const { data: phases, isLoading: isLoadingPhases, mutate: refreshPhases, } = useSWR< BaseApiResponse, AxiosError, SWRHttpKey >(`${PhaseApi.basePath}?page=1&limit=100`, httpClientFetcher, { keepPreviousData: true, }); const { data: employeesRes, isLoading: isLoadingEmployees, mutate: refreshEmployees, } = useSWR( `${EmployeeApi.basePath}?page=1&limit=500&kandang_id=${kandangId}&is_active=true`, EmployeeApi.getAllFetcher, { keepPreviousData: true, } ); const allPhases = isResponseSuccess(phases) ? phases.data || [] : []; const employees = isResponseSuccess(employeesRes) ? employeesRes.data || [] : []; const [selectedPhaseIds, setSelectedPhaseIds] = useState([]); const [selectedEmployees, setSelectedEmployees] = useState< { id: number; name: string }[] >([]); const sortedSelectedEmployees = selectedEmployees.toSorted((a, b) => a.name.localeCompare(b.name) ); const [dailyChecklistId, setDailyChecklistId] = useState(null); const [checklistStatus, setChecklistStatus] = useState('DRAFT'); // const [isEditMode, setIsEditMode] = useState(false); // Activities grouped by phase const [activitiesByPhase, setActivitiesByPhase] = useState<{ [phaseId: string]: PhaseActivity[]; }>({}); // Task IDs mapped by phase_activity_id for quick lookup const [taskIdsByPhaseActivityId, setTaskIdsByPhaseActivityId] = useState<{ [phaseActivityId: string]: string; }>({}); // Assignments: { task_id: { employee_id: { checked, note } } } const [assignments, setAssignments] = useState<{ [taskId: string]: { [employeeId: string]: { checked: boolean; note: string }; }; }>({}); const [showAbkModal, setShowAbkModal] = useState(false); const [showPhaseModal, setShowPhaseModal] = useState(false); const [tempSelectedEmployees, setTempSelectedEmployees] = useState< { id: number; name: string }[] >([]); const [tempSelectedPhaseIds, setTempSelectedPhaseIds] = useState( [] ); const [searchAbk, setSearchAbk] = useState(''); const [searchPhase, setSearchPhase] = useState(''); const [isLoadingSubmit, setIsLoadingSubmit] = useState(false); const [isLoadingDraft, setIsLoadingDraft] = useState(false); const [initialLoading, setInitialLoading] = useState(true); const [existingDocuments, setExistingDocuments] = useState([]); const [documents, setDocuments] = useState([]); const [deletedDocumentIds, setDeletedDocumentIds] = useState([]); // 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 const formatDateForDisplay = (dateStr: string) => { if (!dateStr) return 'Pilih tanggal'; const [year, month, day] = dateStr.split('-'); const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day)); return date.toLocaleDateString('id-ID', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', }); }; // Fetch master data on mount useEffect(() => { setInitialLoading(false); }, []); // Check for existing checklist when unique key changes useEffect(() => { const checkAndLoadChecklist = async () => { if (!date || !kandangId || !selectedCategory) { setDailyChecklistId(null); setChecklistStatus('DRAFT'); // setIsEditMode(false); setSelectedPhaseIds([]); setActivitiesByPhase({}); setTaskIdsByPhaseActivityId({}); setAssignments({}); return; } try { const checklist = await DailyChecklistApi.create({ date, kandang_id: Number(kandangId), category: selectedCategory, status: 'DRAFT', }); if (isResponseError(checklist)) { console.error('Error upserting checklist:', checklist.message); toast.error('Gagal memuat checklist'); return; } setDailyChecklistId(String(checklist?.data?.id)); setChecklistStatus(String(checklist?.data?.status)); const existingPhases = await DailyChecklistApi.getOneDailyChecklist( String(checklist?.data.id) ); if (isResponseError(existingPhases)) { console.error('Error loading phases:', existingPhases.message); } else if ( existingPhases && existingPhases.data && existingPhases.data.phases.length > 0 ) { // Existing checklist - EDIT MODE // setIsEditMode(true); const phaseIds = existingPhases.data.phases.map((p) => String(p.phase_id) ); setSelectedPhaseIds(phaseIds); if (checklist?.data?.status === 'DRAFT') { toast.info('Checklist ditemukan - Mode Edit (Draft)', { description: 'Anda dapat menambah atau mengubah data checklist ini', }); } else { toast.warning(`Checklist sudah ${checklist?.data?.status}`, { description: 'Checklist tidak dapat diedit', }); } } else { // New checklist - CREATE MODE // setIsEditMode(false); setSelectedPhaseIds([]); } } catch (error) { console.error('Error checking checklist:', error); } }; checkAndLoadChecklist(); }, [date, kandangId, selectedCategory]); // Load activities and tasks when phases change useEffect(() => { const loadActivitiesAndTasks = async () => { if (!dailyChecklistId || selectedPhaseIds.length === 0) { setActivitiesByPhase({}); setTaskIdsByPhaseActivityId({}); return; } try { const activitiesRes = await PhaseActivityApi.getAll({ phase_ids: selectedPhaseIds.join(','), limit: '100', }); if (isResponseError(activitiesRes)) { console.error('Error loading activities:', activitiesRes.message); toast.error('Gagal memuat aktivitas'); return; } const activities = activitiesRes?.data || []; // Group activities by phase const grouped: { [phaseId: string]: PhaseActivity[] } = {}; (activities || []).forEach((act) => { if (!grouped[act.phase_id]) { grouped[act.phase_id] = []; } grouped[act.phase_id].push(act); }); setActivitiesByPhase(grouped); // Ensure tasks exist for all activities (UPSERT) const taskUpserts = (activities || []).map((act) => ({ checklist_id: dailyChecklistId, phase_activity_id: act.id, phase_id: act.phase_id, time_type: act.time_type, notes: null, })); if (taskUpserts.length > 0) { const existingDailyChecklist = await DailyChecklistApi.getOneDailyChecklist( String(dailyChecklistId) ); if (isResponseError(existingDailyChecklist)) { console.error( 'Error loading assignments:', existingDailyChecklist.message ); return; } // Build task ID lookup const taskMap: { [phaseActivityId: string]: string } = {}; (existingDailyChecklist?.data?.tasks || []).forEach((task) => { taskMap[String(task.phase_activity_id)] = String(task.id); }); setTaskIdsByPhaseActivityId(taskMap); // Load existing assignments for these tasks await loadAssignments( existingDailyChecklist?.data?.tasks?.map((t) => String(t.id)) || [] ); } } catch (error) { console.error('Error loading activities and tasks:', error); } }; loadActivitiesAndTasks(); }, [dailyChecklistId, selectedPhaseIds]); // Load employees when kandang changes useEffect(() => { if (kandangId) { // ✅ Clear selected employees ketika kandang berubah (reset ABK assignment) setSelectedEmployees([]); setAssignments({}); } else { setSelectedEmployees([]); setAssignments({}); } }, [kandangId]); const loadAssignments = async (taskIds: string[]) => { if (taskIds.length === 0) return; try { const existingDailyChecklist = await DailyChecklistApi.getOneDailyChecklist(String(dailyChecklistId)); if (isResponseError(existingDailyChecklist)) { console.error( 'Error loading assignments:', existingDailyChecklist.message ); return; } // set existing document setExistingDocuments(existingDailyChecklist?.data.document_urls || []); // Build assignments map const assignmentMap: { [taskId: string]: { [employeeId: string]: { checked: boolean; note: string }; }; } = {}; (existingDailyChecklist?.data.tasks || []).forEach( (dailyChecklistTask) => { if (!assignmentMap[dailyChecklistTask.id]) { assignmentMap[dailyChecklistTask.id] = {}; } dailyChecklistTask.assignments.forEach((assignment) => { if (!assignmentMap[dailyChecklistTask.id]) { assignmentMap[dailyChecklistTask.id] = {}; } assignmentMap[dailyChecklistTask.id][assignment.employee.id] = { checked: assignment.checked, note: assignment.note || '', }; }); } ); setAssignments(assignmentMap); // Load employees from assignments const employeeIds = Array.from( new Set( (existingDailyChecklist?.data.assigned_employees || []).map( (a) => a.id ) ) ); if (employeeIds.length > 0) { const existingDailyChecklist = await DailyChecklistApi.getOneDailyChecklist( String(dailyChecklistId) ); if (isResponseSuccess(existingDailyChecklist)) { setSelectedEmployees(existingDailyChecklist.data.assigned_employees); } } } catch (error) { console.error('Error loading assignments:', error); } }; // Phase selection modal const handleAddPhase = () => { if (!selectedCategory) { toast.error('Pilih kategori terlebih dahulu'); return; } setTempSelectedPhaseIds([...selectedPhaseIds]); setSearchPhase(''); setShowPhaseModal(true); setTempSelectedEmployees([]); setSelectedEmployees([]); }; const toggleTempPhase = (phaseId: string) => { if (tempSelectedPhaseIds.includes(phaseId)) { setTempSelectedPhaseIds( tempSelectedPhaseIds.filter((id) => id !== phaseId) ); } else { setTempSelectedPhaseIds([...tempSelectedPhaseIds, phaseId]); } }; const applyPhaseSelection = async () => { if (!dailyChecklistId) { toast.error('Checklist belum tersedia'); return; } if (!tempSelectedPhaseIds.length) { toast.error('Pilih minimal satu fase'); return; } try { // Insert new phase links const setDailyChecklistPhaseRes = await DailyChecklistApi.setDailyChecklistPhase( dailyChecklistId, tempSelectedPhaseIds ); if (isResponseError(setDailyChecklistPhaseRes)) { console.error( 'Error saving phases:', setDailyChecklistPhaseRes.message ); toast.error('Gagal menyimpan fase'); return; } setSelectedPhaseIds([...tempSelectedPhaseIds]); setShowPhaseModal(false); setSearchPhase(''); toast.success('Fase berhasil disimpan'); } catch (error) { console.error('Error applying phase selection:', error); toast.error('Terjadi kesalahan'); } }; // ABK selection modal const handleAddAbk = () => { if (!kandangId) { toast.error('Pilih kandang terlebih dahulu'); return; } setTempSelectedEmployees([...selectedEmployees]); setSearchAbk(''); setShowAbkModal(true); }; const toggleTempEmployee = (employee: Employee) => { const isSelected = tempSelectedEmployees.find((e) => e.id === employee.id); if (isSelected) { setTempSelectedEmployees( tempSelectedEmployees.filter((e) => e.id !== employee.id) ); } else { setTempSelectedEmployees([...tempSelectedEmployees, employee]); } }; const applyAbkSelection = async () => { if (!dailyChecklistId) { toast.error('Checklist belum tersedia'); return; } // Remove assignments for employees that were deselected const removedEmployees = selectedEmployees.filter( (emp) => !tempSelectedEmployees.find((temp) => temp.id === emp.id) ); if (removedEmployees.length > 0) { removedEmployees.forEach(async (removedEmp) => { const removeEmployeeAssignmentRes = await DailyChecklistApi.removeEmployeeAssignment( dailyChecklistId, String(removedEmp.id) ); if (isResponseError(removeEmployeeAssignmentRes)) { console.error( 'Error removing employee assignment:', removeEmployeeAssignmentRes.message ); toast.error('Gagal menghapus tugas'); return; } }); // Remove from state const newAssignments = { ...assignments }; Object.keys(newAssignments).forEach((taskId) => { removedEmployees.forEach((emp) => { delete newAssignments[taskId][emp.id]; }); }); setAssignments(newAssignments); } // Add assignments for newly selected employees (upsert with checked=false) const addedEmployees = tempSelectedEmployees.filter( (temp) => !selectedEmployees.find((emp) => emp.id === temp.id) ); if (addedEmployees.length > 0) { const taskIds = Object.values(taskIdsByPhaseActivityId); const newAssignments: { task_id: string; employee_id: string; checked: boolean; note: string | null; }[] = []; taskIds.forEach((taskId) => { addedEmployees.forEach((emp) => { newAssignments.push({ task_id: taskId, employee_id: String(emp.id), checked: false, note: null, }); }); }); const assignEmployeeRes = await DailyChecklistApi.setDailyChecklistEmployees( dailyChecklistId, addedEmployees.map((emp) => String(emp.id)) ); if (isResponseError(assignEmployeeRes)) { console.error('Error assigning employees:', assignEmployeeRes.message); toast.error('Gagal mengassign ABK: ' + assignEmployeeRes.message); return; } } setSelectedEmployees([...tempSelectedEmployees]); setShowAbkModal(false); setSearchAbk(''); toast.success('ABK berhasil disimpan'); }; const handleRemoveAbk = async (employeeId: string) => { const deleteEmployeeRes = await DailyChecklistApi.removeEmployeeAssignment( String(dailyChecklistId), String(employeeId) ); if (isResponseError(deleteEmployeeRes)) { console.error('Error deleting employee:', deleteEmployeeRes.message); toast.error('Gagal menghapus ABK: ' + deleteEmployeeRes.message); return; } // Remove from state const newAssignments = { ...assignments }; Object.keys(newAssignments).forEach((taskId) => { delete newAssignments[taskId][employeeId]; }); setAssignments(newAssignments); setSelectedEmployees( selectedEmployees.filter((e) => String(e.id) !== employeeId) ); }; const handleCheckboxChange = async ( activityId: string, employeeId: string, checked: boolean ) => { const taskId = taskIdsByPhaseActivityId[activityId]; // console.log('[CHECKBOX] Click detected:', { // activityId, // employeeId, // checked, // taskId, // hasTaskId: !!taskId, // checklistStatus, // isChecklistStatusDraft, // }); if (!taskId) { console.error('[CHECKBOX] No taskId found for activityId:', activityId); console.error('[CHECKBOX] Available taskIds:', taskIdsByPhaseActivityId); toast.error('Task ID tidak ditemukan. Coba refresh halaman.'); return; } if (!isChecklistStatusDraft) { console.warn( '[CHECKBOX] Checklist is not editable, status:', checklistStatus ); return; } // Optimistically update UI first setAssignments((prev) => { const updated = { ...prev, [taskId]: { ...prev[taskId], [employeeId]: { checked, note: prev[taskId]?.[employeeId]?.note || '', }, }, }; // console.log( // '[CHECKBOX] State updated optimistically:', // updated[taskId]?.[employeeId] // ); return updated; }); // Update database const payload = { task_id: Number(taskId), employee_id: Number(employeeId), checked, note: assignments[taskId]?.[employeeId]?.note || null, }; // console.log('[CHECKBOX] Saving to database:', payload); const checkOrUncheckAssignmentRes = await DailyChecklistApi.checkOrUncheckAssignment(payload); if (isResponseError(checkOrUncheckAssignmentRes)) { console.error( '[CHECKBOX] Database error:', checkOrUncheckAssignmentRes.message ); toast.error('Gagal menyimpan: ' + checkOrUncheckAssignmentRes.message); // Revert state on error setAssignments((prev) => ({ ...prev, [taskId]: { ...prev[taskId], [employeeId]: { checked: !checked, note: prev[taskId]?.[employeeId]?.note || '', }, }, })); return; } // console.log('[CHECKBOX] Saved successfully'); }; const handleNoteChange = async ( activityId: string, employeeId: string, note: string ) => { const taskId = taskIdsByPhaseActivityId[activityId]; if (!taskId) return; // Update database const payload = { task_id: Number(taskId), employee_id: Number(employeeId), checked: assignments[taskId]?.[employeeId]?.checked || false, note: note || null, }; const checkOrUncheckAssignmentRes = await DailyChecklistApi.checkOrUncheckAssignment(payload); if (isResponseError(checkOrUncheckAssignmentRes)) { console.error( '[CHECKBOX] Database error:', checkOrUncheckAssignmentRes.message ); toast.error('Gagal menyimpan: ' + checkOrUncheckAssignmentRes.message); return; } // Update state setAssignments((prev) => ({ ...prev, [taskId]: { ...prev[taskId], [employeeId]: { checked: prev[taskId]?.[employeeId]?.checked || false, note, }, }, })); }; const handleSubmit = async () => { if (!dailyChecklistId) return; if (selectedEmployees.length === 0) { toast.error('Pilih minimal 1 ABK'); return; } if (selectedPhaseIds.length === 0) { toast.error('Pilih minimal 1 fase'); return; } setIsLoadingSubmit(true); try { const submitRes = await DailyChecklistApi.submit( dailyChecklistId, documents, deletedDocumentIds ); if (isResponseError(submitRes)) { console.error('Error submitting:', submitRes.message); toast.error('Gagal submit checklist'); return; } setChecklistStatus('SUBMITTED'); toast.success('Checklist berhasil disubmit untuk approval'); } catch (error) { console.error('Error submitting:', error); toast.error('Terjadi kesalahan'); } finally { setIsLoadingSubmit(false); } }; const handleSaveDraft = async () => { if (!dailyChecklistId) return; setIsLoadingDraft(true); 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'); setIsLoadingDraft(false); return; } setIsLoadingDraft(false); toast.success('Draft tersimpan!'); }; // Filter functions const filteredEmployees = employees.filter((emp) => emp.name.toLowerCase().includes(searchAbk.toLowerCase()) ); const availablePhases = allPhases.filter( (p) => p.category === selectedCategory ); const filteredPhases = availablePhases.filter((phase) => phase.name.toLowerCase().includes(searchPhase.toLowerCase()) ); const isAllAbkSelected = tempSelectedEmployees.length === filteredEmployees.length && filteredEmployees.length > 0 && tempSelectedEmployees.every((tempSelectedEmployee) => { return ( filteredEmployees.findIndex( (filteredEmployee) => filteredEmployee.id === tempSelectedEmployee.id ) >= 0 ); }); const isAllPhasesSelected = tempSelectedPhaseIds.length === filteredPhases.length && filteredPhases.length > 0 && tempSelectedPhaseIds.every((tempSelectedPhaseId) => { return ( filteredPhases.findIndex( (filteredPhase) => String(filteredPhase.id) === String(tempSelectedPhaseId) ) >= 0 ); }); const toggleSelectAllAbk = () => { if (isAllAbkSelected) { setTempSelectedEmployees([]); } else { setTempSelectedEmployees([...filteredEmployees]); } }; // Group activities by PHASE → TIME_TYPE → ACTIVITIES const groupActivitiesByPhase = () => { const grouped: { [phaseId: string]: { phase: Phase; timeGroups: { [timeType: string]: PhaseActivity[]; }; }; } = {}; const selectedPhasesData = allPhases.filter((p) => selectedPhaseIds.includes(String(p.id)) ); selectedPhasesData.forEach((phase) => { const phaseActivities = activitiesByPhase[phase.id] || []; if (!grouped[phase.id]) { grouped[phase.id] = { phase, timeGroups: {}, }; } // Group activities by time_type within this phase phaseActivities.forEach((activity) => { const timeType = activity.time_type || 'Umum'; if (!grouped[phase.id].timeGroups[timeType]) { grouped[phase.id].timeGroups[timeType] = []; } grouped[phase.id].timeGroups[timeType].push(activity); }); }); return grouped; }; const isChecklistStatusDraft = checklistStatus === 'DRAFT'; if (initialLoading) { return (

Daily Checklist

Checklist Harian Aktivitas Kandang

Memuat data...
); } return (
{/* Page Title */}

Daily Checklist

{isChecklistStatusDraft && ( Mode Edit )} {checklistStatus !== 'DRAFT' && ( {checklistStatus} )}

Checklist Harian Aktivitas Kandang

{/* Main Card */} {/* Form Section */}
{/* Phase Selection Section */} {dailyChecklistId && (
{isChecklistStatusDraft && (
)} {selectedPhaseIds.length > 0 ? (
{allPhases .filter((p) => selectedPhaseIds.includes(String(p.id))) .map((phase) => ( {phase.name} ))}
) : (

Belum ada fase dipilih

)}
)} {/* ABK Assignment Section */} {dailyChecklistId && selectedPhaseIds.length > 0 && (
{isChecklistStatusDraft && (
)} {selectedEmployees.length > 0 ? (
{selectedEmployees.map((emp) => ( {emp.name} {isChecklistStatusDraft && ( )} ))}
) : (

Belum ada ABK dipilih

)}
)} {/* Activity Checklist Table */} {dailyChecklistId && selectedPhaseIds.length > 0 && selectedEmployees.length > 0 ? (

Checklist Aktivitas

{Object.keys(activitiesByPhase).length > 0 ? (
{sortedSelectedEmployees.map((emp) => ( ))} {Object.keys(groupActivitiesByPhase()).flatMap( (phaseId) => { const phaseData = groupActivitiesByPhase()[phaseId]; const { phase, timeGroups } = phaseData; const timeTypes = Object.keys(timeGroups).sort( (a, b) => TIME_TYPE_ORDER.indexOf(a) - TIME_TYPE_ORDER.indexOf(b) ); // Count total activities in this phase const totalActivities = timeTypes.reduce( (sum, timeType) => sum + timeGroups[timeType].length, 0 ); // Build all rows for this phase const rows = []; // PHASE Header (Main parent) - BLUE rows.push( ); // TIME_TYPE sub-headers and activities timeTypes.forEach((timeType) => { const activities = timeGroups[timeType]; const hasMultipleTimeTypes = timeTypes.length > 1; // TIME Header (optional, only if phase has multiple time types) - GRAY SOFT if (hasMultipleTimeTypes) { rows.push( ); } // ACTIVITY rows (Child rows with checkboxes) activities.sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: 'base', }) ); console.log(activities); activities.forEach((activity, index) => { const taskId = taskIdsByPhaseActivityId[activity.id]; const indentClass = hasMultipleTimeTypes ? 'pl-12' : 'pl-8'; rows.push( {sortedSelectedEmployees.map((emp) => ( ))} ); }); }); return rows; } )}
Aktivitas {emp.name} Catatan
{phase.name} {totalActivities} aktivitas
{TIME_TYPE_LABELS[timeType]} ( {activities.length} aktivitas)

{activity.name}

{activity.description && (

{activity.description}

)}
handleCheckboxChange( String(activity.id), String(emp.id), e.target.checked ) } disabled={!isChecklistStatusDraft} className='checkbox-clean' /> 0 ? assignments[taskId]?.[ selectedEmployees[0].id ]?.note || '' : '' } onChange={(e) => { if (selectedEmployees.length > 0) { handleNoteChange( String(activity.id), String(selectedEmployees[0].id), e.target.value ); } }} disabled={!isChecklistStatusDraft} />
) : (

Tidak Ada Aktivitas

Tidak ada aktivitas untuk fase yang dipilih. Silakan tambahkan aktivitas di Master Aktivitas.

)}
) : (
{!dailyChecklistId ? (

Mulai Checklist Baru

Pilih tanggal, kandang, dan kategori untuk memulai checklist harian Anda.

) : selectedPhaseIds.length === 0 ? (

Pilih Fase / Tahap

Klik tombol {'"'}Pilih Fase{'"'} untuk memilih tahap aktivitas yang akan dikerjakan.

) : (

Pilih ABK

Klik tombol {'"'}Tambah ABK{'"'} untuk memilih pekerja yang akan ditugaskan.

)}
)} {dailyChecklistId && selectedPhaseIds.length > 0 && selectedEmployees.length > 0 && ( <> {existingDocuments.length > 0 && (

Dokumen yang telah diupload

{existingDocuments.map( (existingDocument, existingDocumentIdx) => (
{existingDocument.name}{' '} {isChecklistStatusDraft && ( )}
) )}
)} {isChecklistStatusDraft && ( { setDocuments(files); }} onDelete={(deletedFileIdx: number) => { const newRequestDocuments = [...documents]; newRequestDocuments?.splice(deletedFileIdx, 1); setDocuments(newRequestDocuments); }} disabled={!isChecklistStatusDraft} className={{ wrapper: 'mt-6', inputWrapper: 'flex items-center', label: 'font-semibold text-gray-900', }} maxSize={5242880} // 5 MB bottomLabel='Ukuran file maksimal 5MB' /> )} )} {/* Action Buttons */} {dailyChecklistId && selectedPhaseIds.length > 0 && selectedEmployees.length > 0 && isChecklistStatusDraft && (
)}
{/* Phase Selection Modal */} setShowPhaseModal(false)} > Pilih Fase / Tahap Pilih satu atau lebih fase yang akan dikerjakan
setSearchPhase(e.target.value)} className='border-gray-200' />
{availablePhases.length > 0 && (
)}
{filteredPhases.length > 0 ? (
{filteredPhases.map((phase) => { const isChecked = tempSelectedPhaseIds.includes( String(phase.id) ); return ( ); })}
) : (

{searchPhase ? 'Tidak ada fase ditemukan' : 'Tidak ada fase tersedia'}

)}
Terpilih: {tempSelectedPhaseIds.length} Fase
{/* ABK Selection Modal */} setShowAbkModal(false)}> Pilih ABK Pilih satu atau lebih ABK yang ditugaskan
setSearchAbk(e.target.value)} className='border-gray-200' />
{filteredEmployees.length > 0 && (
)}
{filteredEmployees.length > 0 ? (
{filteredEmployees.map((emp) => { const isChecked = tempSelectedEmployees.find( (e) => e.id === emp.id ); // const kandang = kandangOptions.find((k) => { // const formattedKandangIds = emp.kandangs.map((empKandang) => // String(empKandang.id) // ); // return formattedKandangIds.includes(String(k.value)); // }); const kandang = emp.kandangs .map((empKandang) => { if (String(empKandang.id) === kandangId) { return `${empKandang.name}`; } return empKandang.name; }) .join(', '); return ( ); })}
) : (

{searchAbk ? 'Tidak ada ABK ditemukan' : 'Tidak ada ABK tersedia'}

)}
Terpilih: {tempSelectedEmployees.length} ABK
); }