106 lines
4.1 KiB
TypeScript
106 lines
4.1 KiB
TypeScript
import React, { useState } from 'react';
|
|
import type { View } from './types/common.ts';
|
|
import { useFarm } from './context/FarmContext.tsx';
|
|
import Sidebar from './components/Sidebar.tsx';
|
|
import Header from './components/Header.tsx';
|
|
import CycleTimeline from './components/CycleTimeline.tsx';
|
|
import Dashboard from './components/Dashboard.tsx';
|
|
import DataManagementPage from './components/counting/DataManagementPage.tsx';
|
|
import WeightMonitoringPage from './components/WeightMonitoringPage.tsx';
|
|
import WeightStandardPage from './components/WeightStandardPage.tsx';
|
|
import FeedSackCountingPage from './components/FeedSackCountingPage.tsx';
|
|
import CobbStandardPage from './components/CobbStandardPage.tsx';
|
|
import IotPanelPage from './components/IotPanelPage.tsx';
|
|
import FcrDashboardPage from './components/FcrDashboardPage.tsx';
|
|
import EefDashboardPage from './components/EefDashboardPage.tsx';
|
|
import SettingsPage from './components/SettingsPage.tsx';
|
|
import { Banner } from './components/ui/Feedback.tsx';
|
|
|
|
const AppContent: React.FC = () => {
|
|
const { error, loading } = useFarm();
|
|
const [view, setView] = useState<View>('dashboard');
|
|
const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
|
|
const [isTimelineVisible, setIsTimelineVisible] = useState(false);
|
|
const goSettings = () => setView('kandangSettings');
|
|
|
|
const renderView = () => {
|
|
switch (view) {
|
|
case 'dashboard':
|
|
return <Dashboard setView={setView} />;
|
|
case 'dataManagement':
|
|
return <DataManagementPage onSettings={goSettings} />;
|
|
case 'weightMonitoring':
|
|
return <WeightMonitoringPage onSettings={goSettings} />;
|
|
case 'weightStandard':
|
|
return <WeightStandardPage />;
|
|
case 'feedSackCounting':
|
|
return <FeedSackCountingPage onSettings={goSettings} />;
|
|
case 'cobbStandard':
|
|
return <CobbStandardPage />;
|
|
case 'iotPanel':
|
|
return <IotPanelPage onSettings={goSettings} />;
|
|
case 'fcrDashboard':
|
|
return <FcrDashboardPage onSettings={goSettings} />;
|
|
case 'eefDashboard':
|
|
return <EefDashboardPage onSettings={goSettings} />;
|
|
case 'kandangSettings':
|
|
return <SettingsPage />;
|
|
default:
|
|
return <Dashboard setView={setView} />;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex h-screen bg-gray-100">
|
|
<Sidebar
|
|
isCollapsed={isSidebarCollapsed}
|
|
view={view}
|
|
setView={setView}
|
|
onToggleCollapse={() => setIsSidebarCollapsed((v) => !v)}
|
|
/>
|
|
<div className="flex-1 flex flex-col overflow-hidden">
|
|
<Header
|
|
onToggleSidebar={() => setIsSidebarCollapsed((v) => !v)}
|
|
isTimelineVisible={isTimelineVisible}
|
|
onToggleTimeline={() => setIsTimelineVisible((v) => !v)}
|
|
/>
|
|
<div className="flex-1 overflow-x-hidden overflow-y-auto">
|
|
{isTimelineVisible && (
|
|
<div className="px-4 sm:px-6 lg:px-8 pt-4 sm:pt-6 lg:pt-8">
|
|
<CycleTimeline />
|
|
</div>
|
|
)}
|
|
<div
|
|
className={
|
|
isTimelineVisible
|
|
? 'px-4 sm:px-6 lg:px-8 pb-8'
|
|
: 'px-4 sm:px-6 lg:px-8 pt-4 sm:pt-6 lg:pt-8 pb-8'
|
|
}
|
|
>
|
|
{error && (
|
|
<div className="mb-4">
|
|
<Banner kind="error">{error}</Banner>
|
|
</div>
|
|
)}
|
|
{renderView()}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{loading && (
|
|
<div className="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50">
|
|
<div className="bg-white rounded-lg p-8 shadow-2xl flex flex-col items-center">
|
|
<div className="relative w-16 h-16 mb-4">
|
|
<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;
|