109 lines
3.5 KiB
TypeScript
109 lines
3.5 KiB
TypeScript
import React, { useMemo } from 'react';
|
|
import {
|
|
BarChart,
|
|
Bar,
|
|
XAxis,
|
|
YAxis,
|
|
CartesianGrid,
|
|
Tooltip,
|
|
Legend,
|
|
ResponsiveContainer,
|
|
} from 'recharts';
|
|
import type { Karung } from '../../types/api.ts';
|
|
|
|
interface FeedTrendChartProps {
|
|
rows: Karung[];
|
|
cycleStartDate: string;
|
|
currentDay: number;
|
|
}
|
|
|
|
const FeedTrendChart: React.FC<FeedTrendChartProps> = ({ rows, cycleStartDate, currentDay }) => {
|
|
const chartData = useMemo(() => {
|
|
const cycleStart = new Date(`${cycleStartDate}T00:00:00`);
|
|
|
|
const dailyData: { label: string; masuk: number; dituang: number; keluar: number }[] = [];
|
|
for (let d = 0; d <= currentDay; d++) {
|
|
const date = new Date(cycleStart);
|
|
date.setDate(cycleStart.getDate() + d);
|
|
dailyData.push({
|
|
label: date.toLocaleDateString('id-ID', { day: '2-digit', month: 'short' }),
|
|
masuk: 0,
|
|
dituang: 0,
|
|
keluar: 0,
|
|
});
|
|
}
|
|
|
|
const byKey = new Map<string, { masuk: number; dituang: number; keluar: number }>();
|
|
for (const row of rows) {
|
|
const bucket = byKey.get(row.date) ?? { masuk: 0, dituang: 0, keluar: 0 };
|
|
bucket.masuk += row.in_today;
|
|
bucket.dituang += row.feed_use_today ?? 0;
|
|
bucket.keluar += row.out_today ?? 0;
|
|
byKey.set(row.date, bucket);
|
|
}
|
|
|
|
for (let d = 0; d <= currentDay; d++) {
|
|
const date = new Date(cycleStart);
|
|
date.setDate(cycleStart.getDate() + d);
|
|
const key = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(
|
|
date.getDate()
|
|
).padStart(2, '0')}`;
|
|
const bucket = byKey.get(key);
|
|
const entry = dailyData[d];
|
|
if (bucket && entry) {
|
|
entry.masuk = bucket.masuk;
|
|
entry.dituang = bucket.dituang;
|
|
entry.keluar = bucket.keluar;
|
|
}
|
|
}
|
|
|
|
return dailyData;
|
|
}, [rows, cycleStartDate, currentDay]);
|
|
|
|
const seriesLabel = (name: string) => {
|
|
if (name === 'masuk') return 'Karung Masuk';
|
|
if (name === 'dituang') return 'Karung Dituang';
|
|
return 'Karung Keluar';
|
|
};
|
|
|
|
return (
|
|
<div className="bg-white p-6 rounded-xl shadow-sm">
|
|
<h2 className="text-xl font-bold text-gray-800 mb-4">Tren Harian Karung IOT</h2>
|
|
<div className="h-60">
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<BarChart data={chartData} margin={{ top: 5, right: 20, left: -15, bottom: 5 }}>
|
|
<CartesianGrid strokeDasharray="3 3" stroke="#e0e0e0" />
|
|
<XAxis
|
|
dataKey="label"
|
|
fontSize={11}
|
|
tick={{ fill: '#6b7280' }}
|
|
angle={-45}
|
|
textAnchor="end"
|
|
height={70}
|
|
/>
|
|
<YAxis fontSize={12} tick={{ fill: '#6b7280' }} allowDecimals={false} />
|
|
<Tooltip
|
|
contentStyle={{
|
|
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
|
border: '1px solid #ccc',
|
|
borderRadius: '8px',
|
|
}}
|
|
formatter={(value: unknown, name: unknown) => [
|
|
`${Number(value ?? 0)} karung`,
|
|
seriesLabel(String(name)),
|
|
]}
|
|
labelFormatter={(label) => `Tanggal: ${label}`}
|
|
/>
|
|
<Legend formatter={(value) => seriesLabel(String(value))} />
|
|
<Bar dataKey="masuk" name="masuk" fill="#2563eb" barSize={8} />
|
|
<Bar dataKey="dituang" name="dituang" fill="#ea580c" barSize={8} />
|
|
<Bar dataKey="keluar" name="keluar" fill="#dc2626" barSize={8} />
|
|
</BarChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default FeedTrendChart;
|