All files / src/pages AdminDashboard.tsx

62.5% Statements 15/24
50% Branches 4/8
50% Functions 4/8
65.21% Lines 15/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118                                                                        2x 6x 6x 6x 6x 6x     6x 6x 6x           6x 6x 6x 6x             6x     6x                                                                                                        
/**
 * @file AdminDashboard.tsx
 * @description
 * Administrative dashboard for inventory management and analytics.
 *
 * **Features:**
 * - Total stock value display
 * - Low-stock products monitoring
 * - Bar chart visualization of low-stock products
 * - Inventory action sidebar
 * - Multi-language support
 * - Help modal with guidance
 *
 * **Data Displayed:**
 * - Total stock value (sum of all products)
 * - Low-stock products list (quantity-based alerts)
 * - Chart showing value distribution of low-stock items
 *
 * @component
 */
 
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import DashboardLogic from '../logic/DashboardLogic';
import Header from '../components/Header';
import HelpModal from '../components/HelpModal';
import Footer from '../components/Footer';
import Sidebar from '../components/Sidebar';
import { useTranslation } from 'react-i18next';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
 
/**
 * Admin dashboard component
 * @component
 * @returns {JSX.Element} Dashboard with inventory analytics and controls
 */
const AdminDashboard: React.FC = () => {
  const { t, i18n } = useTranslation(['translation', 'help']);
  const [stockValue, setStockValue] = useState<number>(0);
  const [lowStockProducts, setLowStockProducts] = useState<{ id: number; name: string; quantity: number; price: number }[]>([]);
  const navigate = useNavigate();
  const [isHelpOpen, setIsHelpOpen] = useState(false);
 
  // Effect to ensure the selected language persists across sessions
  useEffect(() => {
    const savedLanguage = localStorage.getItem('language') || 'en';
    Iif (i18n.language !== savedLanguage) {
      i18n.changeLanguage(savedLanguage);
    }
  }, [i18n]);
 
  // Fetch dashboard data from backend and update states
  useEffect(() => {
    const fetchDashboardData = async () => {
      try {
        const response = await DashboardLogic.fetchDashboardData();
        setStockValue(response.stockValue);
        setLowStockProducts(response.lowStock || []);
      } catch (err) {
        console.error('Error fetching dashboard data:', err);
      }
    };
    fetchDashboardData();
  }, [t]);
 
  return (
    <div className="flex flex-col min-h-screen bg-gray-100 relative">
      {/* Header with Logout Button */}
      <Header isLoggedIn={true} onLogout={() => { localStorage.clear(); navigate('/login'); }} />
 
      {/* Help Button Positioned at the Top Center */}
      <div className="absolute top-4 left-1/2 transform -translate-x-1/2 z-50">
        <button onClick={() => setIsHelpOpen(true)} className="dashboard-button button-help" key={i18n.language}>
          {t('button', { ns: 'help' })}
        </button>
      </div>
 
      {/* Help Modal - Displays Help Content */}
      {isHelpOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50">
          <HelpModal isOpen={isHelpOpen} onClose={() => setIsHelpOpen(false)} pageKey="adminDashboard" />
        </div>
      )}
 
      {/* Main Content Layout: Sidebar + Graph */}
      <div className="flex flex-row p-6 space-x-6">
        {/* Sidebar with Stock Information and Controls */}
        <Sidebar stockValue={stockValue} lowStockProducts={lowStockProducts} />
        
        {/* Main Graph Displaying Contribution of Low-Stock Products to Total Stock Value */}
        <div className="flex-1 bg-white shadow p-6 rounded min-h-[500px] flex flex-col">
          <h3 className="text-lg font-semibold">{t('adminDashboard.lowStockContribution')}</h3>
          <div className="flex-grow">
            <ResponsiveContainer width="100%" height="100%">
              <BarChart data={lowStockProducts.map(product => ({
                name: product.name,
                value: ((product.price * product.quantity) / stockValue) * 100, // Percentage of total stock value
              }))}>
                <CartesianGrid strokeDasharray="3 3" />
                <XAxis dataKey="name" />
                <YAxis unit="%" />
                <Tooltip />
                <Legend />
                <Bar dataKey="value" fill="#82ca9d" />
              </BarChart>
            </ResponsiveContainer>
          </div>
        </div>
      </div>
      
      {/* Footer Section */}
      <Footer />
    </div>
  );
};
 
export default AdminDashboard;