import React, { useEffect, useState } from 'react'; import { useFarm } from '../context/FarmContext.tsx'; import { formatDateId, formatDateRange, resolveCycleBoundDate, resolveCycleStatus, cycleLastDayIndex, } from '../utils/format.ts'; import type { Cycle } from '../types/api.ts'; type Phase = { name: string; startDay: number; endDay: number; color: string }; function phasesFor(totalDays: number): Phase[] { const safeDays = Math.max(totalDays, 1); const starterEnd = Math.min(10, safeDays); const growerEnd = Math.min(24, safeDays); const phases: Phase[] = [ { name: 'Starter', startDay: 1, endDay: starterEnd, color: 'bg-red-400' }, ]; if (growerEnd > starterEnd) { phases.push({ name: 'Grower', startDay: starterEnd + 1, endDay: growerEnd, color: 'bg-orange-400', }); } if (safeDays > growerEnd) { phases.push({ name: 'Finisher', startDay: growerEnd + 1, endDay: safeDays, color: 'bg-yellow-500', }); } return phases; } const statusConfig = { active: { label: 'Active', bg: 'bg-red-100', text: 'text-red-800', icon: 'fa-running' }, pending_close: { label: 'Menunggu GM', bg: 'bg-amber-100', text: 'text-amber-800', icon: 'fa-hourglass-half', }, closed: { label: 'Completed', bg: 'bg-green-100', text: 'text-green-800', icon: 'fa-check-circle', }, }; const SingleCycleView: React.FC<{ cycle: Cycle }> = ({ cycle }) => { const boundDate = resolveCycleBoundDate(cycle); const displayTotalDays = Math.max(cycle.total_days || 1, cycleLastDayIndex(cycle) + 1); const phases = phasesFor(displayTotalDays); const currentDay = Math.min(Math.max(cycle.current_day, 0), displayTotalDays); const cycleStatus = resolveCycleStatus(cycle); const progress = displayTotalDays > 0 ? (currentDay / displayTotalDays) * 100 : 0; const showMarker = cycleStatus === 'active' || cycleStatus === 'pending_close'; return (

Siklus:{' '} {formatDateRange(cycle.start_date, cycle.end_date)}

{cycle.end_date ? 'Estimasi Panen' : 'Batas data'}

{formatDateId(cycle.end_date ?? boundDate)}

{phases.map((phase) => { const width = ((phase.endDay - phase.startDay + 1) / displayTotalDays) * 100; return (
{phase.name}
); })}
{showMarker && (
Hari ke-{currentDay}
)}
Hari 1 {formatDateId(cycle.start_date)} Berat DOC: {cycle.chick_in_weight} gram DOC In: {cycle.doc_in_count.toLocaleString('id-ID')} ekor
Hari {displayTotalDays} {formatDateId(cycle.end_date ?? boundDate)}
); }; const CycleTimeline: React.FC = () => { const { cycles, selectedCycleId, setSelectedCycleId } = useFarm(); const [localId, setLocalId] = useState(selectedCycleId); useEffect(() => { setLocalId(selectedCycleId); }, [selectedCycleId]); const selected = cycles.find((c) => c.id === localId) ?? null; return (

Linimasa Siklus Produksi

{cycles.length === 0 ? (

Belum ada siklus untuk kandang ini. Buat di Pengaturan.

) : ( <>
{selected ? ( ) : (

Pilih tab siklus di atas, atau buat di Pengaturan.

)} )}
); }; export default CycleTimeline;