tugasKASIR/kasir_admin/src/components/dashboard/Hero.tsx

164 lines
5.5 KiB
TypeScript

import { useState, useEffect } from 'react';
import axios from 'axios';
interface DashboardStats {
permintaanHariIni: number;
menungguPersetujuan: number;
totalBarang: number;
penggunaAktif: number;
stokHampirHabis: number;
}
export default function Hero() {
// 1. Ambil data profil dari LocalStorage hasil login sebelumnya
const userName = localStorage.getItem('user_name') || 'User';
const userRole = localStorage.getItem('user_role') || 'Siswa';
// State untuk menampung angka statistik dari database
const [stats, setStats] = useState<DashboardStats>({
permintaanHariIni: 0,
menungguPersetujuan: 0,
totalBarang: 0,
penggunaAktif: 0,
stokHampirHabis: 0
});
// 2. Fungsi membuat inisial nama (Contoh: "Bu Sari" -> "BS", "Admin" -> "AD")
const dapatkanInisial = (nama: string) => {
const kata = nama.split(' ');
if (kata.length >= 2) {
return (kata[0][0] + kata[1][0]).toUpperCase();
}
return nama.substring(0, 2).toUpperCase();
};
// 3. Efek untuk mengambil data counter statistik dari backend pas halaman dibuka
useEffect(() => {
const ambilStatistikDashboard = async () => {
try {
// Silahkan buat rute /api/dashboard-stats di backend jika ingin memisahkan kueri count-nya
// Sebagai alternatif awal, kita ambil total barang & total bast dari rute yang sudah ada
const resBarang = await axios.get('http://localhost:5000/api/barang');
const resBast = await axios.get('http://localhost:5000/api/bast');
const resUser = await axios.get('http://localhost:5000/api/users');
// Hitung total data berdasarkan respon database
const totalBarang = resBarang.data.success ? resBarang.data.data.length : 0;
const listBast = resBast.data.success ? resBast.data.data : [];
const totalUser = resUser.data.success ? resUser.data.data.length : 0;
// Filter data untuk counter spesifik dokumen BAST
const menunggu = listBast.filter((b: any) => b.status_serah === 'Menunggu' || b.status_terima === 'Menunggu').length;
// Simulasi hitung permintaan hari ini dari tanggal dibuat_pada (UKK basic)
const hariIniFormat = new Date().toISOString().split('T')[0];
const hariIni = listBast.filter((b: any) => b.dibuat_pada && b.dibuat_pada.startsWith(hariIniFormat)).length;
// Hitung barang dengan stok kritis (di bawah 5 buah)
const kritis = resBarang.data.success
? resBarang.data.data.filter((brg: any) => brg.stok <= 3).length
: 0;
setStats({
permintaanHariIni: hariIni,
menungguPersetujuan: menunggu,
totalBarang: totalBarang,
penggunaAktif: totalUser,
stokHampirHabis: kritis
});
} catch (error) {
console.error("Gagal memuat statistik dashboard:", error);
}
};
ambilStatistikDashboard();
}, []);
return (
<div className="bg-blue-50 rounded-3xl p-8 shadow-sm border border-blue-100 mb-8">
{/* HEADER */}
<div className="flex justify-between items-start mb-8">
<div>
<p className="text-gray-500 text-lg">
Selamat datang kembali 👋
</p>
<h1 className="text-5xl font-extrabold text-blue-700 mt-2">
Dashboard
</h1>
</div>
{/* PROFILE */}
<div className="flex items-center gap-3 bg-white rounded-full px-4 py-2 shadow border">
<div className="w-12 h-12 bg-blue-500 rounded-full flex items-center justify-center text-white font-bold">
{dapatkanInisial(userName)}
</div>
<div>
<h3 className="font-semibold text-black">
{userName}
</h3>
<p className="text-gray-500 text-sm capitalize">
{userRole}
</p>
</div>
</div>
</div>
{/* STAT CARDS */}
<div className="grid grid-cols-4 gap-6">
{/* CARD 1 */}
<div className="bg-white rounded-2xl p-6 shadow border">
<p className="text-gray-500 mb-2">
Permintaan Hari Ini
</p>
<h2 className="text-4xl font-bold text-blue-700">
{stats.permintaanHariIni}
</h2>
<p className="text-green-600 mt-2 text-sm">
Dokumen baru masuk
</p>
</div>
{/* CARD 2 */}
<div className="bg-white rounded-2xl p-6 shadow border">
<p className="text-gray-500 mb-2">
Menunggu Persetujuan
</p>
<h2 className="text-4xl font-bold text-blue-700">
{stats.menungguPersetujuan}
</h2>
<p className="text-yellow-600 mt-2 text-sm">
Perlu tindakan segera
</p>
</div>
{/* CARD 3 */}
<div className="bg-white rounded-2xl p-6 shadow border">
<p className="text-gray-500 mb-2">
Total Ragam Barang
</p>
<h2 className="text-4xl font-bold text-blue-700">
{stats.totalBarang}
</h2>
<p className="text-red-500 mt-2 text-sm">
{stats.stokHampirHabis} stok hampir habis
</p>
</div>
{/* CARD 4 */}
<div className="bg-white rounded-2xl p-6 shadow border">
<p className="text-gray-500 mb-2">
Total Terdaftar
</p>
<h2 className="text-4xl font-bold text-blue-700">
{stats.penggunaAktif}
</h2>
<p className="text-green-600 mt-2 text-sm">
Siswa & petugas aktif
</p>
</div>
</div>
</div>
);
}