112 lines
3.2 KiB
Dart
112 lines
3.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:mobile_monitoring/data/services/planting_cycles_service.dart';
|
|
import 'package:mobile_monitoring/core/utils/phase_display_utils.dart';
|
|
|
|
class MonitoringStatusData {
|
|
final String status;
|
|
final Color color;
|
|
final String description;
|
|
|
|
const MonitoringStatusData({
|
|
required this.status,
|
|
required this.color,
|
|
required this.description,
|
|
});
|
|
}
|
|
|
|
class MonitoringCardService {
|
|
final PlantingCyclesService _cyclesService;
|
|
|
|
static const double _phMin = 4.0;
|
|
static const double _phMax = 6.0;
|
|
|
|
MonitoringCardService({PlantingCyclesService? cyclesService})
|
|
: _cyclesService = cyclesService ?? PlantingCyclesService();
|
|
|
|
Stream<PhaseDisplayConfig> growthPhaseStream(String? userId) {
|
|
if (userId == null || userId.isEmpty) {
|
|
return Stream.value(PhaseDisplayUtils.vegetatif);
|
|
}
|
|
|
|
return _cyclesService
|
|
.getActiveCycleStream(userId: userId)
|
|
.map((data) => _parsePhase(data?['growth_phase'] as String?));
|
|
}
|
|
|
|
PhaseDisplayConfig parsePhase(String? phase) => _parsePhase(phase);
|
|
|
|
// Get phase display name
|
|
String getPhaseName(PhaseDisplayConfig phase) {
|
|
return phase.name;
|
|
}
|
|
|
|
// Get phase color
|
|
Color getPhaseColor(PhaseDisplayConfig phase) {
|
|
return phase.color;
|
|
}
|
|
|
|
// Get TDS/nutrient target range for phase
|
|
String getTdsRange(PhaseDisplayConfig phase) {
|
|
return 'Target: ${phase.nutrientMin}-${phase.nutrientMax} ppm';
|
|
}
|
|
|
|
// Determine status (normal/abnormal) based on measurement and phase
|
|
MonitoringStatusData determineStatus({
|
|
required String title,
|
|
required String value,
|
|
required PhaseDisplayConfig phase,
|
|
required String fallbackStatus,
|
|
required Color fallbackColor,
|
|
required String fallbackDescription,
|
|
}) {
|
|
final titleLower = title.toLowerCase();
|
|
final numValue =
|
|
double.tryParse(value.replaceAll(RegExp(r'[^0-9\.]'), '')) ?? 0.0;
|
|
|
|
if (titleLower.contains('ph')) {
|
|
if (numValue >= _phMin && numValue <= _phMax) {
|
|
return const MonitoringStatusData(
|
|
status: 'Normal',
|
|
color: Color(0xFF4CAF50),
|
|
description: 'pH berada dalam rentang ideal',
|
|
);
|
|
} else {
|
|
return const MonitoringStatusData(
|
|
status: 'Abnormal',
|
|
color: Color(0xFFF44336),
|
|
description: 'pH di luar rentang ideal',
|
|
);
|
|
}
|
|
}
|
|
|
|
if (titleLower.contains('nutrient') || titleLower.contains('tds')) {
|
|
final min = phase.nutrientMin;
|
|
final max = phase.nutrientMax;
|
|
|
|
if (numValue >= min && numValue <= max) {
|
|
return MonitoringStatusData(
|
|
status: 'Normal',
|
|
color: const Color(0xFF4CAF50),
|
|
description: 'Kadar nutrisi optimal untuk fase ${phase.name}',
|
|
);
|
|
} else {
|
|
return const MonitoringStatusData(
|
|
status: 'Abnormal',
|
|
color: Color(0xFFF44336),
|
|
description: 'Kadar nutrisi di luar rentang ideal',
|
|
);
|
|
}
|
|
}
|
|
|
|
return MonitoringStatusData(
|
|
status: fallbackStatus,
|
|
color: fallbackColor,
|
|
description: fallbackDescription,
|
|
);
|
|
}
|
|
|
|
PhaseDisplayConfig _parsePhase(String? phase) {
|
|
return PhaseDisplayUtils.fromName(phase?.toLowerCase() ?? 'vegetatif');
|
|
}
|
|
}
|