Files
dashboard/components/AppContent.tsx
T

236 lines
8.3 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import Sidebar from './Sidebar.tsx';
import Header from './Header.tsx';
import Dashboard from './Dashboard.tsx';
import SrsDocument from './SrsDocument.tsx';
import AuthPage from './auth/AuthPage.tsx';
import MobileAppPage from './MobileAppPage.tsx';
import LocationManagementPage from './LocationManagementPage.tsx';
import CameraManagementPage from './CameraManagementPage.tsx';
import ChickenCountingPage from './ChickenCountingPage.tsx';
import DataManagementPage from './counting/DataManagementPage.tsx';
import FeedSackCountingPage from './FeedSackCountingPage.tsx';
import BehaviorAnalysisPage from './BehaviorAnalysisPage.tsx';
import WeightMonitoringPageRevamped from './WeightMonitoringPageRevamped.tsx';
import IotDeviceManagementPage from './IotDeviceManagementPage.tsx';
import NetworkManagementPage from './NetworkManagementPage.tsx';
import BatchProcessPage from './BatchProcessPage.tsx';
import UserManagementPage from './UserManagementPage.tsx';
import ProfilePage from './ProfilePage.tsx';
import MultiCoopWeightPage from './MultiCoopWeightPage.tsx';
import FeedWastagePage from './FeedWastagePage.tsx';
import FeedSchedulingPage from './FeedSchedulingPage.tsx';
import FcrDashboardPage from './FcrDashboardPage.tsx';
import EefDashboardPage from './EefDashboardPage.tsx';
import PrdDocument from './PrdDocument.tsx';
import TodoDocument from './TodoDocument.tsx';
import ErpIntegrationPage from './ErpIntegrationPage.tsx';
import VetVisitPage from './VetVisitPage.tsx';
import OcrProcessingPage from './OcrProcessingPage.tsx';
import CycleTimeline from './CycleTimeline.tsx';
import WeightStandardPage from './WeightStandardPage.tsx';
import CobbStandardPage from './CobbStandardPage.tsx';
import SlidesPage from './SlidesPage.tsx';
import IotPanelPage from './IotPanelPage.tsx';
import SettingsPage from './SettingsPage.tsx';
import { useAppContext } from '../context/AppContext.tsx';
import { View } from '../types.ts';
import { Kandang } from '../types/counting.ts';
import { apiClient } from '../services/apiService.ts';
interface AppContentProps {
selectedKandangId: number | null;
setSelectedKandangId: (id: number | null) => void;
selectedArea: string;
setSelectedArea: (area: string) => void;
kandangs: Kandang[];
setKandangs: (kandangs: Kandang[]) => void;
}
const AppContent: React.FC<AppContentProps> = ({
selectedKandangId,
setSelectedKandangId,
selectedArea,
setSelectedArea,
kandangs,
setKandangs,
}) => {
const { currentUser, kpis, isLoadingData, cycleData } = useAppContext();
const [view, setView] = useState<View>('dashboard');
const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
const [isTimelineVisible, setIsTimelineVisible] = useState(false);
const toggleSidebar = () => {
setIsSidebarCollapsed(!isSidebarCollapsed);
};
const toggleTimelineVisibility = () => {
setIsTimelineVisible((prev) => !prev);
};
// Fetch kandangs when cycle changes OR when view changes (to pick up updates)
useEffect(() => {
const loadKandangs = async () => {
if (!cycleData?.id) return;
try {
const data = await apiClient.getKandangsByCycle(cycleData.id);
setKandangs(data);
} catch (error) {
console.error('Failed to load kandangs:', error);
}
};
loadKandangs();
}, [cycleData?.id, view, setKandangs]); // Added 'view' dependency to reload when navigating
// Auto-select first kandang when kandangs load
useEffect(() => {
const firstKandang = kandangs[0];
if (firstKandang && selectedKandangId === null) {
setSelectedKandangId(firstKandang.id);
}
}, [kandangs, selectedKandangId, setSelectedKandangId]);
if (!currentUser) {
return <AuthPage />;
}
const renderView = () => {
switch (view) {
case 'dashboard':
return (
<Dashboard
kpis={kpis}
setView={setView}
selectedArea={selectedArea}
onAreaChange={setSelectedArea}
selectedKandangId={selectedKandangId}
onKandangChange={setSelectedKandangId}
kandangs={kandangs}
/>
);
case 'srs':
return <SrsDocument />;
case 'prd':
return <PrdDocument />;
case 'todo':
return <TodoDocument />;
case 'mobileApp':
return <MobileAppPage />;
case 'locationManagement':
return <LocationManagementPage />;
case 'cameraManagement':
return <CameraManagementPage />;
case 'chickenCounting':
return <ChickenCountingPage />;
case 'dataManagement':
return <DataManagementPage selectedKandangId={selectedKandangId} kandangs={kandangs} />;
case 'feedSackCounting':
return <FeedSackCountingPage setView={setView} />;
case 'behaviorAnalysis':
return <BehaviorAnalysisPage />;
case 'weightMonitoring':
return <WeightMonitoringPageRevamped />;
case 'weightStandard':
return <WeightStandardPage />;
case 'cobbStandard':
return <CobbStandardPage />;
case 'iotDeviceManagement':
return <IotDeviceManagementPage />;
case 'iotPanel':
return <IotPanelPage />;
case 'kandangSettings':
return <SettingsPage />;
case 'networkManagement':
return <NetworkManagementPage />;
case 'batchProcess':
return <BatchProcessPage />;
case 'userManagement':
return <UserManagementPage />;
case 'profile':
return <ProfilePage />;
case 'multiCoopWeight':
return <MultiCoopWeightPage />;
case 'feedWastage':
return <FeedWastagePage />;
case 'feedScheduling':
return <FeedSchedulingPage />;
case 'fcrDashboard':
return <FcrDashboardPage />;
case 'eefDashboard':
return <EefDashboardPage />;
case 'erpIntegration':
return <ErpIntegrationPage />;
case 'vetVisit':
return <VetVisitPage />;
case 'ocrProcessing':
return <OcrProcessingPage />;
case 'slides':
return <SlidesPage />;
default:
return (
<Dashboard
kpis={kpis}
setView={setView}
selectedArea={selectedArea}
onAreaChange={setSelectedArea}
selectedKandangId={selectedKandangId}
onKandangChange={setSelectedKandangId}
kandangs={kandangs}
/>
);
}
};
return (
<div className="flex h-screen bg-gray-100">
<Sidebar
isCollapsed={isSidebarCollapsed}
view={view}
setView={setView}
onToggleCollapse={toggleSidebar}
/>
<div className="flex-1 flex flex-col overflow-hidden">
<Header
onToggleSidebar={toggleSidebar}
setView={setView}
isTimelineVisible={isTimelineVisible}
onToggleTimeline={toggleTimelineVisibility}
selectedArea={selectedArea}
onAreaChange={setSelectedArea}
selectedKandangId={selectedKandangId}
onKandangChange={setSelectedKandangId}
kandangs={kandangs}
/>
<div className="flex-1 overflow-x-hidden overflow-y-auto">
{isTimelineVisible && view !== 'slides' && (
<div className="px-4 sm:px-6 lg:px-8 pt-4 sm:pt-6 lg:pt-8">
<CycleTimeline />
</div>
)}
<div className={isTimelineVisible && view !== 'slides' ? '' : 'pt-4 sm:pt-6 lg:pt-8'}>
{renderView()}
</div>
</div>
</div>
{/* Global Loading Overlay */}
{isLoadingData && (
<div className="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50 transition-opacity duration-300">
<div className="bg-white rounded-lg p-8 shadow-2xl flex flex-col items-center">
<div className="relative w-16 h-16 mb-4">
{/* Spinning loader */}
<div className="absolute inset-0 border-4 border-gray-200 rounded-full"></div>
<div className="absolute inset-0 border-4 border-red-600 rounded-full border-t-transparent animate-spin"></div>
</div>
<p className="text-gray-700 font-semibold text-lg">Memuat Data...</p>
<p className="text-gray-500 text-sm mt-2">Mohon tunggu sebentar</p>
</div>
</div>
)}
</div>
);
};
export default AppContent;