feat: set default value for date, kandang ID, and category from url query

This commit is contained in:
ValdiANS
2026-01-21 12:37:53 +07:00
parent 248d4f75d8
commit 0dbcb83c54
@@ -41,6 +41,7 @@ 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
@@ -67,7 +68,23 @@ interface Phase {
}
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 } =
useSelect(KandangApi.basePath, 'id', 'name', 'search', {
@@ -104,12 +121,6 @@ export function DailyChecklistContent() {
? 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 [selectedEmployees, setSelectedEmployees] = useState<
@@ -118,7 +129,7 @@ export function DailyChecklistContent() {
const [dailyChecklistId, setDailyChecklistId] = useState<string | null>(null);
const [checklistStatus, setChecklistStatus] = useState<string>('DRAFT');
const [isEditMode, setIsEditMode] = useState(false);
// const [isEditMode, setIsEditMode] = useState(false);
// Activities grouped by phase
const [activitiesByPhase, setActivitiesByPhase] = useState<{
@@ -148,13 +159,57 @@ export function DailyChecklistContent() {
const [searchAbk, setSearchAbk] = 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 [existingDocuments, setExistingDocuments] = useState<Document[]>([]);
const [documents, setDocuments] = useState<File[]>([]);
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
const formatDateForDisplay = (dateStr: string) => {
if (!dateStr) return 'Pilih tanggal';
@@ -179,7 +234,7 @@ export function DailyChecklistContent() {
if (!date || !kandangId || !selectedCategory) {
setDailyChecklistId(null);
setChecklistStatus('DRAFT');
setIsEditMode(false);
// setIsEditMode(false);
setSelectedPhaseIds([]);
setActivitiesByPhase({});
setTaskIdsByPhaseActivityId({});
@@ -216,7 +271,7 @@ export function DailyChecklistContent() {
existingPhases.data.phases.length > 0
) {
// Existing checklist - EDIT MODE
setIsEditMode(true);
// setIsEditMode(true);
const phaseIds = existingPhases.data.phases.map((p) =>
String(p.phase_id)
);
@@ -234,7 +289,7 @@ export function DailyChecklistContent() {
}
} else {
// New checklist - CREATE MODE
setIsEditMode(false);
// setIsEditMode(false);
setSelectedPhaseIds([]);
}
} catch (error) {
@@ -608,7 +663,7 @@ export function DailyChecklistContent() {
// taskId,
// hasTaskId: !!taskId,
// checklistStatus,
// isEditable,
// isChecklistStatusDraft,
// });
if (!taskId) {
@@ -618,7 +673,7 @@ export function DailyChecklistContent() {
return;
}
if (!isEditable) {
if (!isChecklistStatusDraft) {
console.warn(
'[CHECKBOX] Checklist is not editable, status:',
checklistStatus
@@ -736,7 +791,7 @@ export function DailyChecklistContent() {
return;
}
setLoading(true);
setIsLoadingSubmit(true);
try {
const submitRes = await DailyChecklistApi.submit(
@@ -757,13 +812,15 @@ export function DailyChecklistContent() {
console.error('Error submitting:', error);
toast.error('Terjadi kesalahan');
} finally {
setLoading(false);
setIsLoadingSubmit(false);
}
};
const handleSaveDraft = async () => {
if (!dailyChecklistId) return;
setIsLoadingDraft(true);
const uploadImageRes = await DailyChecklistApi.uploadImage(
Number(dailyChecklistId),
'DRAFT',
@@ -774,9 +831,11 @@ export function DailyChecklistContent() {
if (isResponseError(uploadImageRes)) {
console.error('Error saving draft:', uploadImageRes.message);
toast.error('Gagal menyimpan draft');
setIsLoadingDraft(false);
return;
}
setIsLoadingDraft(false);
toast.success('Draft tersimpan!');
};
@@ -838,7 +897,7 @@ export function DailyChecklistContent() {
return grouped;
};
const isEditable = checklistStatus === 'DRAFT';
const isChecklistStatusDraft = checklistStatus === 'DRAFT';
if (initialLoading) {
return (
@@ -871,7 +930,7 @@ export function DailyChecklistContent() {
<h1 className='text-2xl font-semibold text-gray-900'>
Daily Checklist
</h1>
{isEditMode && (
{isChecklistStatusDraft && (
<Badge
variant='outline'
className='border-amber-300 text-amber-700 bg-white'
@@ -907,7 +966,7 @@ export function DailyChecklistContent() {
<DatePicker
date={date}
onDateChange={setDate}
disabled={!isEditable}
disabled={!isChecklistStatusDraft}
placeholder='Pilih tanggal'
formatDisplay={formatDateForDisplay}
/>
@@ -921,7 +980,7 @@ export function DailyChecklistContent() {
<Select
value={kandangId}
onValueChange={setKandangId}
disabled={!isEditable}
disabled={!isChecklistStatusDraft}
>
<SelectTrigger
id='kandang'
@@ -949,7 +1008,7 @@ export function DailyChecklistContent() {
<Select
value={selectedCategory}
onValueChange={setSelectedCategory}
disabled={!isEditable}
disabled={!isChecklistStatusDraft}
>
<SelectTrigger
id='category'
@@ -971,19 +1030,21 @@ export function DailyChecklistContent() {
{/* Phase Selection Section */}
{dailyChecklistId && (
<div className='mb-6 pb-6 border-b border-gray-200'>
<div className='flex items-center justify-between mb-3'>
<Label>Fase / Tahap</Label>
<Button
onClick={handleAddPhase}
size='sm'
variant='outline'
className='border-[#0069e0] text-[#0069e0] hover:bg-blue-50'
disabled={!selectedCategory || !isEditable}
>
<Plus className='w-4 h-4 mr-1' />
Pilih Fase
</Button>
</div>
{isChecklistStatusDraft && (
<div className='flex items-center justify-between mb-3'>
<Label>Fase / Tahap</Label>
<Button
onClick={handleAddPhase}
size='sm'
variant='outline'
className='border-[#0069e0] text-[#0069e0] hover:bg-blue-50'
disabled={!selectedCategory || !isChecklistStatusDraft}
>
<Plus className='w-4 h-4 mr-1' />
Pilih Fase
</Button>
</div>
)}
{selectedPhaseIds.length > 0 ? (
<div className='flex flex-wrap gap-2'>
@@ -1010,19 +1071,21 @@ export function DailyChecklistContent() {
{/* ABK Assignment Section */}
{dailyChecklistId && selectedPhaseIds.length > 0 && (
<div className='mb-6 pb-6 border-b border-gray-200'>
<div className='flex items-center justify-between mb-3'>
<Label>ABK Assignment</Label>
<Button
onClick={handleAddAbk}
size='sm'
variant='outline'
className='border-[#0069e0] text-[#0069e0] hover:bg-blue-50'
disabled={!kandangId || !isEditable}
>
<Plus className='w-4 h-4 mr-1' />
Tambah ABK
</Button>
</div>
{isChecklistStatusDraft && (
<div className='flex items-center justify-between mb-3'>
<Label>ABK Assignment</Label>
<Button
onClick={handleAddAbk}
size='sm'
variant='outline'
className='border-[#0069e0] text-[#0069e0] hover:bg-blue-50'
disabled={!kandangId || !isChecklistStatusDraft}
>
<Plus className='w-4 h-4 mr-1' />
Tambah ABK
</Button>
</div>
)}
{selectedEmployees.length > 0 ? (
<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'
>
{emp.name}
{isEditable && (
{isChecklistStatusDraft && (
<button
onClick={() => handleRemoveAbk(String(emp.id))}
className='ml-2 hover:text-gray-900'
@@ -1198,7 +1261,7 @@ export function DailyChecklistContent() {
e.target.checked
)
}
disabled={!isEditable}
disabled={!isChecklistStatusDraft}
className='checkbox-clean'
/>
</td>
@@ -1225,7 +1288,7 @@ export function DailyChecklistContent() {
);
}
}}
disabled={!isEditable}
disabled={!isChecklistStatusDraft}
/>
</td>
</tr>
@@ -1321,61 +1384,68 @@ export function DailyChecklistContent() {
/>
</Link>
<Button
type='button'
variant='ghost'
color='error'
onClick={() => {
setDeletedDocumentIds((prevIds) => [
...prevIds,
existingDocument.id,
]);
{isChecklistStatusDraft && (
<Button
type='button'
variant='ghost'
color='error'
onClick={() => {
setDeletedDocumentIds((prevIds) => [
...prevIds,
existingDocument.id,
]);
setExistingDocuments((prevExistingDocument) => {
const newExistingDocuments = [
...prevExistingDocument,
];
newExistingDocuments.splice(
existingDocumentIdx,
1
setExistingDocuments(
(prevExistingDocument) => {
const newExistingDocuments = [
...prevExistingDocument,
];
newExistingDocuments.splice(
existingDocumentIdx,
1
);
return newExistingDocuments;
}
);
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>
}}
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];
{isChecklistStatusDraft && (
<DropFileInput
name='Dokumen'
label='Dokumen'
values={documents}
onChange={(files) => {
setDocuments(files);
}}
onDelete={(deletedFileIdx: number) => {
const newRequestDocuments = [...documents];
newRequestDocuments?.splice(deletedFileIdx, 1);
newRequestDocuments?.splice(deletedFileIdx, 1);
setDocuments(newRequestDocuments);
}}
className={{
wrapper: 'mt-6',
inputWrapper: 'flex items-center',
label: 'font-semibold text-gray-900',
}}
/>
setDocuments(newRequestDocuments);
}}
disabled={!isChecklistStatusDraft}
className={{
wrapper: 'mt-6',
inputWrapper: 'flex items-center',
label: 'font-semibold text-gray-900',
}}
/>
)}
</>
)}
@@ -1383,24 +1453,30 @@ export function DailyChecklistContent() {
{dailyChecklistId &&
selectedPhaseIds.length > 0 &&
selectedEmployees.length > 0 &&
isEditable && (
isChecklistStatusDraft && (
<div className='flex justify-end gap-3 mt-6 pt-6 border-t border-gray-200'>
<Button
onClick={handleSaveDraft}
variant='outline'
disabled={loading}
disabled={isLoadingDraft}
className='border-gray-200'
>
<Save className='w-4 h-4 mr-2' />
Simpan Draft
{isLoadingDraft ? (
<span className='loading loading-spinner loading-sm' />
) : (
'Simpan Draft'
)}
</Button>
<Button
onClick={handleSubmit}
disabled={loading}
disabled={isLoadingSubmit}
className='bg-[#0069e0] hover:bg-[#0052b3] text-white'
>
<Send className='w-4 h-4 mr-2' />
Submit Checklist
{isLoadingSubmit
? 'Mengirim Checklist...'
: 'Submit Checklist'}
</Button>
</div>
)}