commit
32a36cceff
444 files changed
+67186
No files matched your search
@@ -0,0 +1,109 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import {
|
||||
BarChart,
|
||||
Bar,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
Legend,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts';
|
||||
import { FeedSackLogEntry, FeedSackColumnConfig } from '../../types/counting.ts';
|
||||
|
||||
interface FeedTrendChartProps {
|
||||
data: FeedSackLogEntry[];
|
||||
cycleStartDate: Date;
|
||||
currentDay: number;
|
||||
columnConfig: FeedSackColumnConfig[];
|
||||
}
|
||||
|
||||
const FeedTrendChart: React.FC<FeedTrendChartProps> = ({
|
||||
data,
|
||||
cycleStartDate,
|
||||
currentDay,
|
||||
columnConfig,
|
||||
}) => {
|
||||
const cameraNames = useMemo(() => columnConfig.map((c) => c.cameraName), [columnConfig]);
|
||||
|
||||
const chartData = useMemo(() => {
|
||||
const cycleStart = new Date(cycleStartDate);
|
||||
cycleStart.setHours(0, 0, 0, 0);
|
||||
|
||||
const now = new Date();
|
||||
now.setHours(0, 0, 0, 0);
|
||||
|
||||
// Initialize daily buckets
|
||||
const dailyData: { [key: number]: Record<string, any> } = {};
|
||||
for (let d = 0; d <= currentDay; d++) {
|
||||
const date = new Date(cycleStart);
|
||||
date.setDate(cycleStart.getDate() + d);
|
||||
const formattedDate = date.toLocaleDateString('id-ID', { day: '2-digit', month: 'short' });
|
||||
|
||||
const entry: Record<string, any> = { day: `H${d}`, date: formattedDate };
|
||||
cameraNames.forEach((name) => {
|
||||
entry[name] = 0;
|
||||
});
|
||||
dailyData[d] = entry;
|
||||
}
|
||||
|
||||
// Aggregate data by day
|
||||
data.forEach((log) => {
|
||||
if (log.timestamp >= cycleStart && log.timestamp <= now) {
|
||||
const diffTime = log.timestamp.getTime() - cycleStart.getTime();
|
||||
const dayNumber = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (dayNumber >= 0 && dayNumber <= currentDay && dailyData[dayNumber]) {
|
||||
if (log.cameraName && cameraNames.includes(log.cameraName)) {
|
||||
dailyData[dayNumber][log.cameraName] += log.count;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Object.values(dailyData);
|
||||
}, [data, cycleStartDate, currentDay, cameraNames]);
|
||||
|
||||
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 Pakan</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="date"
|
||||
fontSize={11}
|
||||
tick={{ fill: '#6b7280' }}
|
||||
angle={-45}
|
||||
textAnchor="end"
|
||||
height={70}
|
||||
/>
|
||||
<YAxis fontSize={12} tick={{ fill: '#6b7280' }} />
|
||||
<Tooltip
|
||||
contentStyle={{
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||
border: '1px solid #ccc',
|
||||
borderRadius: '8px',
|
||||
}}
|
||||
formatter={(value: number) => [`${value} karung`]}
|
||||
labelFormatter={(label) => `Tanggal: ${label}`}
|
||||
/>
|
||||
<Legend />
|
||||
{columnConfig.map((col) => (
|
||||
<Bar
|
||||
key={col.id}
|
||||
dataKey={col.cameraName}
|
||||
name={col.label}
|
||||
fill={col.color}
|
||||
barSize={8}
|
||||
/>
|
||||
))}
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FeedTrendChart;
|
||||
Reference in new issue
Block a user