Merge branch 'fix/daily-checklist' into 'development'

[FIX/FE] Daily Checklist Enhancement

See merge request mbugroup/lti-web-client!284
This commit is contained in:
Rivaldi A N S
2026-01-30 04:49:13 +00:00
3 changed files with 95 additions and 22 deletions
@@ -127,6 +127,10 @@ export function DailyChecklistContent() {
{ id: number; name: string }[]
>([]);
const sortedSelectedEmployees = selectedEmployees.toSorted((a, b) =>
a.name.localeCompare(b.name)
);
const [dailyChecklistId, setDailyChecklistId] = useState<string | null>(null);
const [checklistStatus, setChecklistStatus] = useState<string>('DRAFT');
// const [isEditMode, setIsEditMode] = useState(false);
@@ -486,6 +490,11 @@ export function DailyChecklistContent() {
return;
}
if (!tempSelectedPhaseIds.length) {
toast.error('Pilih minimal satu fase');
return;
}
try {
// Insert new phase links
const setDailyChecklistPhaseRes =
@@ -535,14 +544,6 @@ export function DailyChecklistContent() {
}
};
const toggleSelectAllAbk = () => {
if (tempSelectedEmployees.length === employees.length) {
setTempSelectedEmployees([]);
} else {
setTempSelectedEmployees([...employees]);
}
};
const applyAbkSelection = async () => {
if (!dailyChecklistId) {
toast.error('Checklist belum tersedia');
@@ -853,10 +854,34 @@ export function DailyChecklistContent() {
);
const isAllAbkSelected =
tempSelectedEmployees.length === employees.length && employees.length > 0;
tempSelectedEmployees.length === filteredEmployees.length &&
filteredEmployees.length > 0 &&
tempSelectedEmployees.every((tempSelectedEmployee) => {
return (
filteredEmployees.findIndex(
(filteredEmployee) => filteredEmployee.id === tempSelectedEmployee.id
) >= 0
);
});
const isAllPhasesSelected =
tempSelectedPhaseIds.length === availablePhases.length &&
availablePhases.length > 0;
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 = () => {
@@ -1130,7 +1155,7 @@ export function DailyChecklistContent() {
<th className='text-left py-3 px-4 text-sm font-semibold text-gray-700 border-r border-gray-200 min-w-[200px]'>
Aktivitas
</th>
{selectedEmployees.map((emp) => (
{sortedSelectedEmployees.map((emp) => (
<th
key={emp.id}
className='text-center py-3 px-4 text-sm font-semibold text-gray-700 border-r border-gray-200 min-w-[100px]'
@@ -1216,6 +1241,14 @@ export function DailyChecklistContent() {
}
// 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];
@@ -1244,7 +1277,7 @@ export function DailyChecklistContent() {
</p>
)}
</td>
{selectedEmployees.map((emp) => (
{sortedSelectedEmployees.map((emp) => (
<td
key={emp.id}
className='text-center py-3 px-4 border-r border-gray-200'
@@ -1519,14 +1552,14 @@ export function DailyChecklistContent() {
setTempSelectedPhaseIds([]);
} else {
setTempSelectedPhaseIds(
availablePhases.map((p) => String(p.id))
filteredPhases.map((p) => String(p.id))
);
}
}}
className='checkbox-clean'
/>
<span className='text-sm font-medium text-gray-700 group-hover:text-gray-900'>
Pilih Semua ({availablePhases.length} Fase)
Pilih Semua ({filteredPhases.length} Fase)
</span>
</label>
</div>
@@ -1621,7 +1654,7 @@ export function DailyChecklistContent() {
/>
</div>
{employees.length > 0 && (
{filteredEmployees.length > 0 && (
<div className='flex items-center gap-3 px-1 py-2'>
<label className='flex items-center gap-2 cursor-pointer group'>
<input
@@ -1631,7 +1664,7 @@ export function DailyChecklistContent() {
className='checkbox-clean'
/>
<span className='text-sm font-medium text-gray-700 group-hover:text-gray-900'>
Pilih Semua ({employees.length} ABK)
Pilih Semua ({filteredEmployees.length} ABK)
</span>
</label>
</div>
@@ -275,6 +275,13 @@ export function DetailDailyChecklistContent() {
])
).values()
);
uniqueEmployees.sort((a, b) =>
a.name.localeCompare(b.name, undefined, {
sensitivity: 'base',
})
);
setEmployees(uniqueEmployees);
// Group data by Phase → Time Type → Activity
@@ -779,11 +786,23 @@ export function DetailDailyChecklistContent() {
}
// ACTIVITY rows
timeGroup.activities.forEach((activity, index) => {
const activities = timeGroup.activities;
activities.sort((a, b) =>
a.name.localeCompare(b.name, undefined, {
sensitivity: 'base',
})
);
activities.forEach((activity, index) => {
const indentClass = hasMultipleTimeTypes
? 'pl-12'
: 'pl-8';
console.log({
activity,
});
rows.push(
<tr
key={`activity-${activity.id}-${index}`}
@@ -823,9 +842,15 @@ export function DetailDailyChecklistContent() {
})}
<td className='py-3 px-4'>
{activity.employees.length > 0 &&
activity.employees[0].note ? (
activity.employees[
activity.employees.length - 1
].note ? (
<p className='text-sm text-gray-600'>
{activity.employees[0].note}
{
activity.employees[
activity.employees.length - 1
].note
}
</p>
) : (
<p className='text-xs text-gray-400 italic'>
@@ -1,6 +1,6 @@
'use client';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { Plus, MoreVertical, Pencil, Trash2 } from 'lucide-react';
import { Card, CardContent } from '@/figma-make/components/base/card';
import { Button } from '@/figma-make/components/base/button';
@@ -404,7 +404,22 @@ export function MasterConfigurationContent() {
</div>
{/* Add/Edit Modal */}
<Dialog open={showModal} onOpenChange={setShowModal}>
<Dialog
open={showModal}
onOpenChange={(open) => {
if (!open) {
setIsFormInvalid(false);
setConfigurationForm({
id: 0,
date: '',
percentage_threshold_bad: '',
percentage_threshold_enough: '',
});
}
setShowModal(open);
}}
>
<DialogContent className='sm:max-w-md bg-white rounded-xl shadow-lg'>
<DialogHeader>
<DialogTitle>