222 lines
7.2 KiB
Dart
222 lines
7.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:mobile_monitoring/core/constants/constants.dart';
|
|
import 'package:mobile_monitoring/data/services/home_service.dart';
|
|
import 'package:mobile_monitoring/logic/controllers/controllers.dart';
|
|
import 'package:mobile_monitoring/ui/pages/flow.dart';
|
|
import 'package:mobile_monitoring/ui/pages/settings.dart';
|
|
import 'package:mobile_monitoring/ui/shared/shared.dart';
|
|
|
|
class HomePage extends StatefulWidget {
|
|
const HomePage({super.key});
|
|
|
|
@override
|
|
State<HomePage> createState() => _HomePageState();
|
|
}
|
|
|
|
class _HomePageState extends State<HomePage> {
|
|
final _controller = HomeController();
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ListenableBuilder(
|
|
listenable: _controller,
|
|
builder: (context, _) {
|
|
final userId = _controller.currentUserId;
|
|
final pages = <Widget>[
|
|
FlowPage(userId: userId),
|
|
_HomeScreenContent(controller: _controller),
|
|
const GraphMenuPage(),
|
|
];
|
|
|
|
return Scaffold(
|
|
body: pages[_controller.selectedIndex],
|
|
bottomNavigationBar: BottomNavbar(
|
|
currentIndex: _controller.selectedIndex,
|
|
onTap: _controller.setSelectedIndex,
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class _HomeScreenContent extends StatelessWidget {
|
|
final HomeController controller;
|
|
|
|
const _HomeScreenContent({required this.controller});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final userId = controller.currentUserId;
|
|
|
|
return SingleChildScrollView(
|
|
child: Container(
|
|
color: AppColors.pageBackground,
|
|
child: Column(
|
|
children: [
|
|
HomeHeader(controller: controller),
|
|
SizedBox(height: MediaQuery.of(context).size.width >= 600 ? 40 : 30),
|
|
_buildSectionTitle(context, AppStrings.growthPhase),
|
|
const GrowthPhaseCard(),
|
|
const SizedBox(height: 24),
|
|
_buildSectionTitle(
|
|
context,
|
|
'${AppStrings.monitoring} & Kontrol',
|
|
onTap: () => Navigator.push(
|
|
context,
|
|
MaterialPageRoute(builder: (_) => FlowPage(userId: userId)),
|
|
),
|
|
),
|
|
Container(
|
|
width: double.infinity,
|
|
color: AppColors.lightGray,
|
|
child: _buildMonitoringCards(userId),
|
|
),
|
|
const SizedBox(height: 24),
|
|
_buildSectionTitle(
|
|
context,
|
|
'${AppStrings.graph} ${AppStrings.monitoring}',
|
|
onTap: () => Navigator.push(
|
|
context,
|
|
MaterialPageRoute(builder: (_) => const GraphMenuPage()),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: MediaQuery.of(context).size.width >= 600 ? 32.0 : 16.0,
|
|
),
|
|
child: GraphWidget(userId: userId),
|
|
),
|
|
SizedBox(height: MediaQuery.of(context).size.width >= 600 ? 140 : 120),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSectionTitle(
|
|
BuildContext context,
|
|
String title, {
|
|
VoidCallback? onTap,
|
|
}) {
|
|
final screenWidth = MediaQuery.of(context).size.width;
|
|
final isTablet = screenWidth >= 600;
|
|
final isSmallScreen = screenWidth < 360;
|
|
|
|
return Padding(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: isTablet ? 32.0 : (isSmallScreen ? 16.0 : 24.0),
|
|
vertical: 8.0,
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
title,
|
|
style: TextStyle(
|
|
fontSize: isTablet ? 24 : (isSmallScreen ? 18 : 20),
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
if (onTap != null)
|
|
GestureDetector(
|
|
onTap: onTap,
|
|
child: Text(
|
|
AppStrings.seeAll,
|
|
style: TextStyle(
|
|
color: AppColors.primaryDark,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: isTablet ? 16 : (isSmallScreen ? 12 : 14),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildMonitoringCards(String? userId) {
|
|
return SizedBox(
|
|
height: 330,
|
|
child: StreamBuilder<Map<String, dynamic>?>(
|
|
stream: controller.latestDataStream(userId),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
|
|
final data = snapshot.data;
|
|
final monitoringData = data != null
|
|
? (controller.parseMonitoringData(data).data ??
|
|
MonitoringData(
|
|
ph: '-',
|
|
nutrisi: '-',
|
|
phStatus: 'Menunggu Data',
|
|
nutrientStatus: 'Menunggu Data',
|
|
pumpPhUp: false,
|
|
pumpPhDown: false,
|
|
pumpNutrient: false,
|
|
pumpWater: false,
|
|
isPhAbnormal: false,
|
|
isNutrientAbnormal: false,
|
|
))
|
|
: MonitoringData(
|
|
ph: '-',
|
|
nutrisi: '-',
|
|
phStatus: 'Menunggu Data',
|
|
nutrientStatus: 'Menunggu Data',
|
|
pumpPhUp: false,
|
|
pumpPhDown: false,
|
|
pumpNutrient: false,
|
|
pumpWater: false,
|
|
isPhAbnormal: false,
|
|
isNutrientAbnormal: false,
|
|
);
|
|
return ListView(
|
|
scrollDirection: Axis.horizontal,
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
children: [
|
|
MonitoringCard(
|
|
title: 'PH Level',
|
|
value: monitoringData.ph,
|
|
unit: '',
|
|
status: monitoringData.phStatus,
|
|
statusColor: monitoringData.isPhAbnormal ? AppColors.warning : AppColors.primary,
|
|
description: 'Jaga pH larutan antara 4.0 - 6.0',
|
|
userId: userId,
|
|
switch1Value: monitoringData.pumpPhUp,
|
|
switch2Value: monitoringData.pumpPhDown,
|
|
switch1Label: 'PH Up',
|
|
switch2Label: 'PH Down',
|
|
onSwitch1Changed: (_) {},
|
|
onSwitch2Changed: (_) {},
|
|
),
|
|
MonitoringCard(
|
|
title: 'Nutrient Level',
|
|
value: monitoringData.nutrisi,
|
|
unit: 'ppm',
|
|
status: monitoringData.nutrientStatus,
|
|
statusColor: monitoringData.isNutrientAbnormal ? AppColors.warning : AppColors.primary,
|
|
description: 'Pastikan TDS/PPM sesuai fase',
|
|
userId: userId,
|
|
switch1Value: monitoringData.pumpNutrient,
|
|
switch2Value: monitoringData.pumpWater,
|
|
switch1Label: 'Nutrisi',
|
|
switch2Label: 'Air Baku',
|
|
onSwitch1Changed: (_) {},
|
|
onSwitch2Changed: (_) {},
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|