236 lines
8.3 KiB
TypeScript
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;
|