Files
dashboard-cpsp/components/feedSack/FeedSaldoCard.tsx
T

121 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useMemo } from 'react';
import type { Karung } from '../../types/api.ts';
import { formatNumber } from '../../utils/format.ts';
interface FeedSaldoCardProps {
latest: Karung | null;
feedInitialBalance: number;
cycleStartDate: string;
displayDate: string;
}
const FeedSaldoCard: React.FC<FeedSaldoCardProps> = ({
latest,
feedInitialBalance,
cycleStartDate,
displayDate,
}) => {
const saldoData = useMemo(() => {
const inbound = (latest?.in_total ?? 0) + feedInitialBalance;
const feedUse = latest?.feed_use_total ?? 0;
const keluar = latest?.out_total ?? 0;
const saldo = inbound - feedUse - keluar;
return { inbound, feedUse, keluar, saldo };
}, [latest, feedInitialBalance]);
const formatDateRange = useMemo(() => {
const formatDate = (iso: string) =>
new Intl.DateTimeFormat('id-ID', {
day: 'numeric',
month: 'long',
year: 'numeric',
}).format(new Date(`${iso}T00:00:00`));
return `${formatDate(cycleStartDate)} - ${formatDate(displayDate)}`;
}, [cycleStartDate, displayDate]);
const getSaldoStatusColor = (saldo: number) => {
if (saldo > 0) return 'text-green-600';
if (saldo < 0) return 'text-red-600';
return 'text-gray-600';
};
return (
<div className="bg-gradient-to-br from-blue-50 to-indigo-50 p-6 rounded-xl shadow-sm border-2 border-blue-200">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3">
<div className="bg-blue-500 text-white p-3 rounded-lg">
<i className="fa-solid fa-scale-balanced text-2xl"></i>
</div>
<div>
<h2 className="text-xl font-bold text-gray-800">Saldo Karung IOT</h2>
<p className="text-sm text-gray-600">{formatDateRange}</p>
</div>
</div>
</div>
{/* Saldo Display */}
<div className="bg-white rounded-lg p-6 border border-blue-200">
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
{/* Karung Masuk */}
<div className="text-center">
<div className="flex items-center justify-center gap-2 mb-2">
<i className="fa-solid fa-arrow-down text-green-600"></i>
<p className="text-sm font-semibold text-gray-700">Karung Masuk</p>
</div>
<p className="text-3xl font-bold text-green-600">{formatNumber(saldoData.inbound)}</p>
<p className="text-xs text-gray-400 mt-1">karung</p>
</div>
{/* Karung Dituang (feed use) */}
<div className="text-center">
<div className="flex items-center justify-center gap-2 mb-2">
<i className="fa-solid fa-arrow-up text-orange-600"></i>
<p className="text-sm font-semibold text-gray-700">Karung Dituang</p>
</div>
<p className="text-3xl font-bold text-orange-600">{formatNumber(saldoData.feedUse)}</p>
<p className="text-xs text-gray-400 mt-1">karung</p>
</div>
{/* Karung Keluar */}
<div className="text-center">
<div className="flex items-center justify-center gap-2 mb-2">
<i className="fa-solid fa-arrow-right text-red-600"></i>
<p className="text-sm font-semibold text-gray-700">Karung Keluar</p>
</div>
<p className="text-3xl font-bold text-red-600">{formatNumber(saldoData.keluar)}</p>
<p className="text-xs text-gray-400 mt-1">karung</p>
</div>
{/* Saldo */}
<div className="text-center lg:border-l-2 lg:border-blue-200 lg:pl-6">
<div className="flex items-center justify-center gap-2 mb-2">
<i className="fa-solid fa-scale-balanced text-blue-600"></i>
<p className="text-sm font-semibold text-gray-700">Saldo</p>
</div>
<p className={`text-4xl font-bold ${getSaldoStatusColor(saldoData.saldo)}`}>
{formatNumber(saldoData.saldo)}
</p>
<p className="text-xs text-gray-400 mt-1">karung</p>
</div>
</div>
<p className="text-xs text-gray-400 mt-4 text-center">
Saldo = karung masuk − karung dituang − karung keluar.
</p>
</div>
{/* Warning for negative saldo */}
{saldoData.saldo < 0 && (
<div className="mt-4 bg-yellow-50 border border-yellow-200 rounded-lg p-3 flex items-start gap-2">
<i className="fa-solid fa-triangle-exclamation text-yellow-600 mt-0.5"></i>
<p className="text-xs text-yellow-800">
<strong>Peringatan:</strong> Saldo negatif menunjukkan karung dituang lebih banyak dari
karung masuk. Periksa kembali data sinkronisasi karung-web-admin.
</p>
</div>
)}
</div>
);
};
export default FeedSaldoCard;