159 lines
6.4 KiB
Dart
159 lines
6.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:mobile_monitoring/core/constants/constants.dart';
|
|
import 'package:mobile_monitoring/data/services/flow_service.dart';
|
|
import 'package:mobile_monitoring/logic/controllers/controllers.dart';
|
|
import 'package:mobile_monitoring/ui/shared/monitoring_card.dart';
|
|
import 'package:mobile_monitoring/ui/shared/monitoring_recap_table.dart';
|
|
import 'package:mobile_monitoring/ui/shared/tips_card.dart';
|
|
|
|
class FlowPage extends StatefulWidget {
|
|
final String? userId;
|
|
|
|
const FlowPage({super.key, this.userId});
|
|
|
|
@override
|
|
State<FlowPage> createState() => _FlowPageState();
|
|
}
|
|
|
|
class _FlowPageState extends State<FlowPage> {
|
|
final _controller = FlowController();
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final userId = _controller.resolveUserId(widget.userId);
|
|
|
|
return Scaffold(
|
|
backgroundColor: AppColors.pageBackground,
|
|
appBar: AppBar(
|
|
title: const Text(AppStrings.monitoring),
|
|
backgroundColor: AppColors.primary,
|
|
elevation: 0,
|
|
centerTitle: true,
|
|
foregroundColor: AppColors.white,
|
|
),
|
|
body: SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(AppSettings.defaultPadding),
|
|
child: Column(
|
|
children: [
|
|
StreamBuilder<Map<String, dynamic>?>(
|
|
stream: _controller.latestDataStream(userId),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return const SizedBox(
|
|
height: 250,
|
|
child: Center(child: CircularProgressIndicator()),
|
|
);
|
|
}
|
|
|
|
final data = snapshot.data;
|
|
final monitoringData = data != null
|
|
? (_controller.parseMonitoringData(data).data ??
|
|
FlowMonitoringData(
|
|
ph: 0.0,
|
|
tds: 0.0,
|
|
phStatus: 'Menunggu Data',
|
|
tdsStatus: 'Menunggu Data',
|
|
phColor: AppColors.primary,
|
|
tdsColor: AppColors.primary,
|
|
pumpPhUp: false,
|
|
pumpPhDown: false,
|
|
pumpNutrient: false,
|
|
pumpWater: false,
|
|
))
|
|
: FlowMonitoringData(
|
|
ph: 0.0,
|
|
tds: 0.0,
|
|
phStatus: 'Menunggu Data',
|
|
tdsStatus: 'Menunggu Data',
|
|
phColor: AppColors.primary,
|
|
tdsColor: AppColors.primary,
|
|
pumpPhUp: false,
|
|
pumpPhDown: false,
|
|
pumpNutrient: false,
|
|
pumpWater: false,
|
|
);
|
|
return Column(
|
|
children: [
|
|
MonitoringCard(
|
|
title: 'PH Level',
|
|
value: monitoringData.ph.toStringAsFixed(2),
|
|
unit: '',
|
|
status: monitoringData.phStatus,
|
|
statusColor: monitoringData.phColor,
|
|
description: 'Jaga pH larutan antara 4.0 - 6.0',
|
|
userId: userId,
|
|
switch1Value: monitoringData.pumpPhUp,
|
|
switch2Value: monitoringData.pumpPhDown,
|
|
switch1Label: 'PH Up',
|
|
switch2Label: 'PH Down',
|
|
onSwitch1Changed: (_) => setState(() {}),
|
|
onSwitch2Changed: (_) => setState(() {}),
|
|
),
|
|
const SizedBox(height: 4),
|
|
MonitoringCard(
|
|
title: 'Nutrient Level',
|
|
value: monitoringData.tds.toStringAsFixed(0),
|
|
unit: 'ppm',
|
|
status: monitoringData.tdsStatus,
|
|
statusColor: monitoringData.tdsColor,
|
|
description: 'Pastikan TDS/PPM sesuai fase',
|
|
userId: userId,
|
|
switch1Value: monitoringData.pumpNutrient,
|
|
switch2Value: monitoringData.pumpWater,
|
|
switch1Label: 'Nutrisi',
|
|
switch2Label: 'Air Baku',
|
|
onSwitch1Changed: (_) => setState(() {}),
|
|
onSwitch2Changed: (_) => setState(() {}),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
StreamBuilder<Map<String, dynamic>?>(
|
|
stream: _controller.activeCycleStream(userId ?? ''),
|
|
builder: (context, cycleSnapshot) {
|
|
final startDate = _controller.extractStartDate(cycleSnapshot.data).data;
|
|
return StreamBuilder<List<Map<String, dynamic>>>(
|
|
stream: _controller.historyStream(limit: 500, userId: userId),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return const SizedBox(
|
|
height: 200,
|
|
child: Center(child: CircularProgressIndicator()),
|
|
);
|
|
}
|
|
|
|
final docs = snapshot.data ?? [];
|
|
if (docs.isEmpty) {
|
|
return const MonitoringRecapTable(data: []);
|
|
}
|
|
|
|
final recapResult = _controller.generateRecapRows(docs, startDate);
|
|
if (!recapResult.success || recapResult.data == null) {
|
|
return const MonitoringRecapTable(data: []);
|
|
}
|
|
|
|
final rowsAsMap = recapResult.data!.map((row) => row.toMap()).toList();
|
|
return MonitoringRecapTable(data: rowsAsMap, startDate: startDate);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
const TipsCard(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|