adjust dashboard berat page to match dashboard-cpsp
This commit is contained in:
1 parent
c71dcc188b
commit
236c83ec3d
2 files changed
+21
-27
No files matched your search
@@ -2,8 +2,12 @@ import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { api, ApiError, errorMessage } from '../services/apiClient.ts';
|
||||
import type { ChickenWeight, LatestAvg } from '../types/api.ts';
|
||||
import { useFarm } from '../context/FarmContext.tsx';
|
||||
import { Banner, EmptyFarm, Spinner } from './ui/Feedback.tsx';
|
||||
import { formatDateId, formatNumber } from '../utils/format.ts';
|
||||
import { Banner, EmptyFarm, PageHeader, Spinner } from './ui/Feedback.tsx';
|
||||
import {
|
||||
formatDateId,
|
||||
formatDateRange,
|
||||
formatNumber,
|
||||
} from '../utils/format.ts';
|
||||
import { formatWeight } from '../utils/weight.ts';
|
||||
import { buildWeightInsightContext } from '../utils/insightContextBuilders.ts';
|
||||
import { PageAiInsight } from './shared/PageAiInsight.tsx';
|
||||
@@ -13,7 +17,7 @@ import DailyWeightGainChart from './weight/DailyWeightGainChart.tsx';
|
||||
import DailyDetailPanel from './weight/DailyDetailPanel.tsx';
|
||||
|
||||
const WeightMonitoringPage: React.FC<{ onSettings: () => void }> = ({ onSettings }) => {
|
||||
const { selectedCycle, selectedKandang } = useFarm();
|
||||
const { selectedCycle, selectedSite, selectedKandang } = useFarm();
|
||||
const [rows, setRows] = useState<ChickenWeight[]>([]);
|
||||
const [latest, setLatest] = useState<LatestAvg | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -119,26 +123,11 @@ const WeightMonitoringPage: React.FC<{ onSettings: () => void }> = ({ onSettings
|
||||
|
||||
return (
|
||||
<main className="pb-8">
|
||||
{/* Header */}
|
||||
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 mb-6">
|
||||
<div className="flex items-center">
|
||||
<div className="bg-red-600 text-white p-3 rounded-lg mr-4">
|
||||
<i className="fa-solid fa-chart-line text-2xl sm:text-3xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-2xl lg:text-3xl font-bold text-gray-800">Dashboard Berat Ayam</h1>
|
||||
<p className="mt-1 text-gray-600">
|
||||
Analisis pertumbuhan dan kesejahteraan bobot ayam secara real-time.
|
||||
</p>
|
||||
{!loading && latest?.date && (
|
||||
<p className="mt-1 text-sm text-gray-500">
|
||||
<i className="fa-solid fa-clock mr-1"></i>
|
||||
Terakhir diperbarui: {formatDateId(latest.date)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<PageHeader
|
||||
title="Dashboard Berat Ayam"
|
||||
icon={<i className="fa-solid fa-chart-line" />}
|
||||
subtitle={`Analisis pertumbuhan bobot ayam secara real-time · ${selectedSite?.site_name ?? ''} · ${selectedKandang?.kandang_name ?? ''} · Siklus ${formatDateRange(selectedCycle.start_date, selectedCycle.end_date)}`}
|
||||
/>
|
||||
|
||||
{error && (
|
||||
<div className="mb-4">
|
||||
@@ -295,9 +284,8 @@ const WeightMonitoringPage: React.FC<{ onSettings: () => void }> = ({ onSettings
|
||||
<div>
|
||||
<h3 className="font-semibold text-blue-900 mb-2">Informasi Pembaruan Data</h3>
|
||||
<ul className="text-sm text-blue-800 space-y-1">
|
||||
<li>• Data berat diperbarui lewat Sync di header (dari site dashboard)</li>
|
||||
<li>• Grafik menampilkan data dari awal siklus hingga hari ini</li>
|
||||
<li>• Target berat menggunakan standar performa Ross 308</li>
|
||||
<li>• Hari 0 memakai berat DOC dan uniformity 0%</li>
|
||||
<li>• Target berat menggunakan standar performa berdasarkan DOC</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+7
-1
@@ -61,6 +61,7 @@ function pickStandardValues(docWeight: number): number[] {
|
||||
|
||||
/** Target body weight (grams) for a given age from the Ross 308 DOC-weight table. */
|
||||
export function getTargetWeightForAge(age: number, docWeight: number): number | null {
|
||||
if (age === 0) return docWeight > 0 ? docWeight : null;
|
||||
const values = pickStandardValues(docWeight);
|
||||
if (age < 1 || age > values.length) return null;
|
||||
return values[age - 1] ?? null;
|
||||
@@ -69,7 +70,12 @@ export function getTargetWeightForAge(age: number, docWeight: number): number |
|
||||
/** Target daily weight gain (grams/day) for a given age from the standard. */
|
||||
export function getTargetGainForAge(age: number, docWeight: number): number | null {
|
||||
const values = pickStandardValues(docWeight);
|
||||
if (age < 2 || age > values.length) return null;
|
||||
if (age < 1 || age > values.length) return null;
|
||||
if (age === 1) {
|
||||
const current = values[0];
|
||||
if (current == null || docWeight <= 0) return null;
|
||||
return current - docWeight;
|
||||
}
|
||||
const current = values[age - 1];
|
||||
const previous = values[age - 2];
|
||||
if (current == null || previous == null) return null;
|
||||
|
||||
Reference in new issue
Block a user