import React, { useMemo, useState } from 'react'; import { api, errorMessage } from '../../services/apiClient.ts'; import type { Cycle, InitialBalanceResult } from '../../types/api.ts'; import { formatNumber } from '../../utils/format.ts'; interface InitialBalanceCardProps { cycle: Cycle; onSaved: () => void; } const InitialBalanceCard: React.FC = ({ cycle, onSaved }) => { const [balanceDate, setBalanceDate] = useState(cycle.start_date); const [manualEntry, setManualEntry] = useState( cycle.feed_initial_balance > 0 ? String(cycle.feed_initial_balance) : '' ); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const [result, setResult] = useState(null); const canSave = useMemo( () => balanceDate !== '' && manualEntry !== '' && Number(manualEntry) >= 0 && !saving, [balanceDate, manualEntry, saving] ); const handleSave = async () => { if (!canSave) return; setSaving(true); setError(null); try { const saved = await api.cycles.initialBalance(cycle.id, { date: balanceDate, feed_in_manual: Number(manualEntry), }); setResult(saved); onSaved(); } catch (err) { setError(errorMessage(err)); } finally { setSaving(false); } }; const accuracy = result?.accuracy; const accuracyLabel = accuracy == null ? 'N/A' : `${formatNumber(accuracy, 1)}%`; const accuracyColor = accuracy == null ? 'text-gray-500' : accuracy >= 95 ? 'text-green-600' : accuracy >= 80 ? 'text-yellow-600' : 'text-red-600'; return (

Saldo Awal

Masukkan saldo awal karung pakan pada tanggal tertentu, lalu bandingkan dengan deteksi IoT.

setBalanceDate(event.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm" />
setManualEntry(event.target.value)} placeholder="Contoh: 120" className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm" />
{error && (

{error}

)}
{cycle.feed_initial_balance > 0 && result == null && (

Saldo awal tersimpan:{' '} {formatNumber(cycle.feed_initial_balance)} karung

)}
{result && (

Perbandingan {result.date}

Manual

{formatNumber(result.manual)} karung

IOT

{result.iot == null ? 'N/A' : `${formatNumber(result.iot)} karung`}

Akurasi

{accuracyLabel}

{result.sync_error && (

Gagal menarik data IoT dari karung-web-admin: {result.sync_error}

)}
)}
); }; export default InitialBalanceCard;