'use client'; import { useState, useEffect } from 'react'; import { Plus, MoreVertical, Pencil, Trash2, Search } 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 { Textarea } from '@/figma-make/components/base/textarea'; 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 { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/figma-make/components/base/alert-dialog'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/figma-make/components/base/dropdown-menu'; import { toast } from 'sonner'; import useSWR from 'swr'; import { PhaseApi } from '@/services/api/daily-checklist/phase'; import { BaseApiResponse } from '@/types/api/api-general'; import { AxiosError } from 'axios'; import { httpClientFetcher, SWRHttpKey } from '@/services/http/client'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { PhaseActivityApi } from '@/services/api/daily-checklist/phase-activity'; import { PhaseActivity } from '@/types/api/daily-checklist/phase-activity'; import { Phase } from '@/types/api/daily-checklist/phase'; // Static categories - tidak bisa CRUD 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_TYPES = [ { value: 'Umum', label: 'Umum' }, { value: 'Pagi', label: 'Pagi' }, { value: 'Siang', label: 'Siang' }, { value: 'Sore', label: 'Sore' }, { value: 'Malam', label: 'Malam' }, ]; export function MasterAktivitasContent() { const [selectedCategory, setSelectedCategory] = useState(''); const [selectedPhase, setSelectedPhase] = useState(null); const { data: phases, isLoading: isLoadingPhases, mutate: refreshPhases, } = useSWR< BaseApiResponse, AxiosError, SWRHttpKey >( selectedCategory ? `${PhaseApi.basePath}?page=1&limit=100&category=${selectedCategory}` : '', httpClientFetcher, { keepPreviousData: true, } ); const { data: phaseActivities, isLoading: isLoadingPhaseActivities, mutate: refreshPhaseActivities, } = useSWR< BaseApiResponse, AxiosError, SWRHttpKey >( selectedPhase?.id ? `${PhaseActivityApi.basePath}?page=1&limit=100&phase_ids=${selectedPhase.id}` : '', httpClientFetcher, { keepPreviousData: true, } ); const [showPhaseModal, setShowPhaseModal] = useState(false); const [showActivityModal, setShowActivityModal] = useState(false); const [showPhaseDeleteConfirm, setShowPhaseDeleteConfirm] = useState(false); const [showActivityDeleteConfirm, setShowActivityDeleteConfirm] = useState(false); const [phaseToDelete, setPhaseToDelete] = useState(null); const [activityToDelete, setActivityToDelete] = useState(null); const [loading, setLoading] = useState(false); const [initialLoading, setInitialLoading] = useState(true); const [phaseSearchQuery, setPhaseSearchQuery] = useState(''); const [phaseModalMode, setPhaseModalMode] = useState<'create' | 'edit'>( 'create' ); const filteredPhases = (isResponseSuccess(phases) && phases?.data?.filter((phase) => { return phase.name .toLowerCase() .includes(phaseSearchQuery.toLowerCase()); })) || []; const [activityModalMode, setActivityModalMode] = useState<'create' | 'edit'>( 'create' ); const [phaseForm, setPhaseForm] = useState({ id: '', name: '', }); const [activityForm, setActivityForm] = useState({ id: '', name: '', description: '', time_type: 'umum', }); useEffect(() => { setInitialLoading(false); }, []); // Phase handlers const handleAddPhase = () => { if (!selectedCategory) { toast.error('Pilih kategori terlebih dahulu'); return; } setPhaseModalMode('create'); setPhaseForm({ id: '', name: '' }); setShowPhaseModal(true); }; const handleEditPhase = (phase: Phase) => { setPhaseModalMode('edit'); setPhaseForm({ id: String(phase.id), name: phase.name, }); setShowPhaseModal(true); }; const handleSavePhase = async () => { if (!phaseForm.name.trim()) { toast.error('Nama phase harus diisi'); return; } if (phaseForm.name.trim().length < 3) { toast.error('Nama phase minimal 3 karakter!'); return; } if (!selectedCategory) { toast.error('Pilih kategori terlebih dahulu'); return; } setLoading(true); try { if (phaseModalMode === 'create') { const createPhaseResponse = await PhaseApi.create({ category: selectedCategory, name: phaseForm.name.trim(), }); if (isResponseError(createPhaseResponse)) { console.error('Error creating phase:', createPhaseResponse.message); toast.error('Gagal menambahkan phase'); return; } refreshPhases(); toast.success('Phase berhasil ditambahkan'); } else { const updatePhaseResponse = await PhaseApi.update( Number(phaseForm.id), { name: phaseForm.name.trim(), } ); if (isResponseError(updatePhaseResponse)) { console.error('Error creating phase:', updatePhaseResponse.message); toast.error('Gagal menambahkan phase'); return; } refreshPhases(); toast.success('Phase berhasil diubah'); } setShowPhaseModal(false); setPhaseForm({ id: '', name: '' }); } catch (error) { console.error('Error saving phase:', error); toast.error('Terjadi kesalahan saat menyimpan phase'); } finally { setLoading(false); } }; const handleDeletePhaseClick = (phaseId: string) => { setPhaseToDelete(phaseId); setShowPhaseDeleteConfirm(true); }; const handleConfirmDeletePhase = async () => { if (!phaseToDelete || !selectedCategory) return; setLoading(true); try { const deletePhaseResponse = await PhaseApi.delete(Number(phaseToDelete)); if (isResponseError(deletePhaseResponse)) { console.error('Error deleting phase:', deletePhaseResponse.message); toast.error('Gagal menghapus phase'); setLoading(false); return; } refreshPhases(); toast.success('Phase dan semua aktivitasnya berhasil dihapus'); setShowPhaseDeleteConfirm(false); setPhaseToDelete(null); // Clear selection if deleted phase was selected if (selectedPhase?.id === Number(phaseToDelete)) { setSelectedPhase(null); } } catch (error) { console.error('Error deleting phase:', error); toast.error('Terjadi kesalahan saat menghapus phase'); } finally { setLoading(false); } }; // Activity handlers const handleAddActivity = () => { if (!selectedPhase) { toast.error('Pilih phase terlebih dahulu'); return; } setActivityModalMode('create'); setActivityForm({ id: '', name: '', description: '', time_type: 'umum' }); setShowActivityModal(true); }; const handleEditActivity = (activity: PhaseActivity) => { setActivityModalMode('edit'); setActivityForm({ id: String(activity.id), name: activity.name, description: activity.description || '', time_type: activity.time_type, }); setShowActivityModal(true); }; const handleSaveActivity = async () => { if (!activityForm.name.trim()) { toast.error('Nama aktivitas harus diisi'); return; } if (activityForm.name.trim().length < 3) { toast.error('Nama aktivitas minimal 3 karakter!'); return; } if (!selectedPhase) { toast.error('Pilih phase terlebih dahulu'); return; } setLoading(true); try { if (activityModalMode === 'create') { const createActivityResponse = await PhaseActivityApi.create({ phase_id: Number(selectedPhase.id), name: activityForm.name.trim(), description: activityForm.description.trim() || '', time_type: activityForm.time_type, }); if (isResponseError(createActivityResponse)) { console.error( 'Error creating activity:', createActivityResponse.message ); toast.error('Gagal menambahkan aktivitas'); return; } refreshPhases(); refreshPhaseActivities(); toast.success('Aktivitas berhasil ditambahkan'); } else { const updateActivityResponse = await PhaseActivityApi.update( Number(activityForm.id), { name: activityForm.name.trim(), description: activityForm.description.trim() || '', time_type: activityForm.time_type, } ); if (isResponseError(updateActivityResponse)) { console.error( 'Error updating activity:', updateActivityResponse.message ); toast.error('Gagal mengubah aktivitas'); return; } refreshPhases(); refreshPhaseActivities(); toast.success('Aktivitas berhasil diubah'); } setShowActivityModal(false); setActivityForm({ id: '', name: '', description: '', time_type: 'umum' }); } catch (error) { console.error('Error saving activity:', error); toast.error('Terjadi kesalahan saat menyimpan aktivitas'); } finally { setLoading(false); } }; const handleDeleteActivityClick = (activityId: string) => { setActivityToDelete(activityId); setShowActivityDeleteConfirm(true); }; const handleConfirmDeleteActivity = async () => { if (!activityToDelete || !selectedPhase || !selectedCategory) return; setLoading(true); try { const deleteActivityResponse = await PhaseActivityApi.delete( Number(activityToDelete) ); if (isResponseError(deleteActivityResponse)) { console.error( 'Error deleting activity:', deleteActivityResponse.message ); toast.error('Gagal menghapus aktivitas'); return; } refreshPhases(); refreshPhaseActivities(); toast.success('Aktivitas berhasil dihapus'); setShowActivityDeleteConfirm(false); setActivityToDelete(null); } catch (error) { console.error('Error deleting activity:', error); toast.error('Terjadi kesalahan saat menghapus aktivitas'); } finally { setLoading(false); } }; const getTimeTypeLabel = (timeType: string) => { return TIME_TYPES.find((t) => t.value === timeType)?.label || timeType; }; const getTimeTypeBadgeClass = (timeType: string) => { switch (timeType.toLowerCase()) { case 'umum': return 'bg-gray-50 text-gray-700 border-gray-300'; case 'pagi': return 'bg-orange-50 text-orange-700 border-orange-300'; case 'siang': return 'bg-amber-50 text-amber-700 border-amber-300'; case 'sore': return 'bg-purple-50 text-purple-700 border-purple-300'; case 'malam': return 'bg-indigo-50 text-indigo-700 border-indigo-300'; default: return 'bg-gray-50 text-gray-700 border-gray-300'; } }; if (initialLoading) { return (

Master Aktivitas

Master Data • Aktivitas

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

Master Aktivitas

Master Data • Aktivitas

{/* Category Selector Card */}

Pilih kategori untuk melihat dan mengelola phase dan aktivitas

{selectedCategory ? (
{/* LEFT PANEL: Phase List */}
{/* Phase Toolbar */}
setPhaseSearchQuery(e.target.value)} className='pl-10 border-gray-200' />
{/* Phase List */}
{!isResponseSuccess(phases) || (isResponseSuccess(phases) && phases.data?.length === 0) ? (
{phaseSearchQuery ? 'Tidak ada phase yang ditemukan' : 'Belum ada data phase'}
) : ( filteredPhases.map((phase) => (
setSelectedPhase(phase)} >

{phase.name}

{phase.activity_count || 0} aktivitas

e.stopPropagation()} > handleEditPhase(phase)} > Edit handleDeletePhaseClick(String(phase.id)) } className='text-red-600' > Hapus
)) )}
{/* RIGHT PANEL: Activity Detail */}
{selectedPhase ? ( <> {/* Activity Header */}

Aktivitas di Phase: {selectedPhase.name}

{isResponseSuccess(phaseActivities) && (

{phaseActivities.data?.length} aktivitas

)}
{/* Activity Table */}
{!isResponseSuccess(phaseActivities) || (isResponseSuccess(phaseActivities) && phaseActivities.data?.length === 0) ? ( ) : ( phaseActivities.data?.map((activity) => ( )) )}
Nama Aktivitas Aksi
Belum ada aktivitas di phase ini

{activity.name}

{activity.description && (

{activity.description}

)}
{getTimeTypeLabel(activity.time_type)}
handleEditActivity(activity) } > Edit handleDeleteActivityClick( String(activity.id) ) } className='text-red-600' > Hapus
) : (
Pilih phase untuk melihat aktivitas
)}
) : ( Pilih kategori terlebih dahulu untuk mengelola phase dan aktivitas )}
{/* Phase Add/Edit Modal */} {phaseModalMode === 'create' ? 'Tambah Phase' : 'Edit Phase'} {phaseModalMode === 'create' ? 'Masukkan detail phase baru' : 'Ubah detail phase'}
setPhaseForm({ ...phaseForm, name: e.target.value }) } placeholder='Masukkan nama phase' className='mt-1.5' disabled={loading} />
{/* Activity Add/Edit Modal */} {activityModalMode === 'create' ? 'Tambah Aktivitas' : 'Edit Aktivitas'} {activityModalMode === 'create' ? 'Masukkan detail aktivitas baru' : 'Ubah detail aktivitas'}
setActivityForm({ ...activityForm, name: e.target.value }) } placeholder='Masukkan nama aktivitas' className='mt-1.5' disabled={loading} />