Files
dashboard-cpsp/components/weight/DailyDetailPanel.tsx
T

104 lines
3.4 KiB
TypeScript

import React from 'react';
import type { ChickenWeight } from '../../types/api.ts';
import { formatDateId, formatNumber } from '../../utils/format.ts';
import { formatWeight, getTargetWeightForAge } from '../../utils/weight.ts';
interface DailyDetailPanelProps {
row: ChickenWeight | null;
docWeight: number;
}
const DetailCard: React.FC<{
label: string;
value: string;
icon: React.ReactNode;
highlight?: boolean;
}> = ({ label, value, icon, highlight = false }) => (
<div
className={`bg-white rounded-xl shadow-sm p-4 ${
highlight ? 'border-2 border-red-500' : 'border border-gray-100'
}`}
>
<div className="flex items-center gap-3">
<div className="text-2xl text-red-500 flex-shrink-0">{icon}</div>
<div className="min-w-0">
<p className="text-xs text-gray-500">{label}</p>
<p className="text-xl font-bold text-gray-800 truncate">{value}</p>
</div>
</div>
</div>
);
const DailyDetailPanel: React.FC<DailyDetailPanelProps> = ({ row, docWeight }) => {
if (!row) {
return (
<div className="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
<div className="flex flex-col items-center justify-center py-6 text-center">
<i className="fa-solid fa-calendar-xmark text-4xl text-gray-300 mb-3"></i>
<p className="text-gray-500 font-medium">Belum ada data untuk tanggal ini</p>
<p className="text-gray-400 text-sm mt-1">
Pilih tanggal lain untuk melihat rincian harian
</p>
</div>
</div>
);
}
const target = getTargetWeightForAge(row.age, docWeight);
const deviation = target != null && row.average_weight > 0 ? row.average_weight - target : null;
return (
<div className="space-y-4">
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4">
<DetailCard
label="Tanggal"
value={formatDateId(row.date)}
icon={<i className="fa-solid fa-calendar-day"></i>}
/>
<DetailCard
label="Umur"
value={`${row.age} hari`}
icon={<i className="fa-solid fa-clock"></i>}
/>
<DetailCard
label="DOC"
value={formatWeight(row.doc_weight, { decimals: 0 })}
icon={<i className="fa-solid fa-egg"></i>}
/>
<DetailCard
label="AVG Berat"
value={formatWeight(row.average_weight, { stripTrailingZeros: true })}
icon={<i className="fa-solid fa-weight-scale"></i>}
highlight
/>
<DetailCard
label="Uniformity"
value={`${formatNumber(row.uniformity, 2, 2, true)}%`}
icon={<i className="fa-solid fa-percent"></i>}
/>
<DetailCard
label="ADG"
value={`${formatNumber(row.average_daily_gain, 2, 2, true)} g/hari`}
icon={<i className="fa-solid fa-chart-line"></i>}
/>
<DetailCard
label="Populasi"
value={`${formatNumber(row.chicken_count, 0)} ekor`}
icon={<i className="fa-solid fa-users"></i>}
/>
{deviation != null && (
<DetailCard
label="Deviasi vs Target"
value={`${deviation >= 0 ? '+' : ''}${formatWeight(Math.abs(deviation), {
stripTrailingZeros: true,
})}`}
icon={<i className="fa-solid fa-arrow-trend-up"></i>}
/>
)}
</div>
</div>
);
};
export default DailyDetailPanel;