HydroNutrify_Ari_e41221567/lib/ui/widgets/growth_phase_service.dart

189 lines
5.5 KiB
Dart

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:mobile_monitoring/data/services/planting_cycles_service.dart';
import 'package:mobile_monitoring/data/models/service_result.dart';
import 'package:mobile_monitoring/core/utils/cycle_phase_utils.dart';
import 'package:mobile_monitoring/core/utils/phase_display_utils.dart';
class GrowthPhaseService {
final PlantingCyclesService _cyclesService;
final FirebaseFirestore _firestore;
final FirebaseAuth _auth;
GrowthPhaseService({
PlantingCyclesService? cyclesService,
FirebaseFirestore? firestore,
FirebaseAuth? auth,
}) : _cyclesService = cyclesService ?? PlantingCyclesService(),
_firestore = firestore ?? FirebaseFirestore.instance,
_auth = auth ?? FirebaseAuth.instance;
String getCurrentUserId() => _auth.currentUser?.uid ?? '';
User? getCurrentUser() => _auth.currentUser;
Stream<Map<String, dynamic>?> activeCycleStream(String userId) {
if (userId.isEmpty) {
return Stream.value(null);
}
return _cyclesService.getActiveCycleStream(userId: userId);
}
DateTime? extractStartDate(Map<String, dynamic>? cycleData) {
return CyclePhaseUtils.extractStartDate(cycleData);
}
// Calculate phase name based on days since planting
String calculateCurrentPhase(int days) {
return CyclePhaseUtils.calculateDisplayPhase(days);
}
// Get phase color
Color getPhaseColor(String phase) {
return PhaseDisplayUtils.fromName(phase).color;
}
// Apply alpha to a color
Color applyAlpha(Color color, double opacity) {
return color.withValues(alpha: (color.a * opacity).clamp(0.0, 1.0));
}
// Format date for display (e.g., "5 Mei 2024")
String formatDate(DateTime date) {
return CyclePhaseUtils.formatIndonesianDate(date);
}
// Get phase data (duration, progress) for a given days count
Map<String, dynamic> getPhaseData(int daysSincePlanting) {
final progressData = PhaseDisplayUtils.progressData(daysSincePlanting);
return {
'day': progressData.dayInPhase,
'duration': progressData.phaseDuration,
'progress': progressData.progress,
};
}
Future<ServiceResult<void>> savePlantingDate({
required String userId,
required DateTime plantingDate,
}) async {
if (userId.isEmpty) {
return ServiceResult.failure(
message: 'User tidak terautentikasi',
errorCode: 'unauthenticated',
);
}
try {
final days = DateTime.now().difference(plantingDate).inDays;
final phase = calculateCurrentPhase(days);
await _cyclesService.addCycle(userId: userId, startDate: plantingDate);
await _createPhaseSnapshot(
userId: userId,
phase: phase,
daysSincePlanting: days,
);
return ServiceResult.success(message: 'Tanggal tanam disimpan');
} catch (e) {
return ServiceResult.failure(
message: 'Gagal menyimpan tanggal tanam: $e',
errorCode: 'save_cycle_failed',
);
}
}
Future<ServiceResult<void>> resetCycle(String userId) async {
if (userId.isEmpty) {
return ServiceResult.failure(
message: 'User tidak terautentikasi',
errorCode: 'unauthenticated',
);
}
try {
await _cyclesService.deleteCycle(userId: userId);
return ServiceResult.success(message: 'Siklus direset');
} catch (e) {
return ServiceResult.failure(
message: 'Gagal reset siklus: $e',
errorCode: 'reset_failed',
);
}
}
Future<ServiceResult<void>> markHarvest(String userId) async {
if (userId.isEmpty) {
return ServiceResult.failure(
message: 'User tidak terautentikasi',
errorCode: 'unauthenticated',
);
}
try {
// Hitung total hari siklus sebelum menghapus
final daysSincePlanting = await _cyclesService
.calculateCycleDaysBeforeDelete(userId: userId);
// Catat snapshot panen untuk historikal
await _createPhaseSnapshot(
userId: userId,
phase: 'Panen',
daysSincePlanting: daysSincePlanting,
);
// Hapus siklus aktif setelah panen dicatat
await _cyclesService.deleteCycle(userId: userId);
return ServiceResult.success(message: 'Panen dicatat, siklus selesai');
} catch (e) {
return ServiceResult.failure(
message: 'Gagal mencatat panen: $e',
errorCode: 'harvest_failed',
);
}
}
Future<void> updatePhaseIfChanged({
required String userId,
required String currentPhaseInDb,
required String calculatedPhase,
required int days,
required DateTime startDate,
}) async {
if (currentPhaseInDb == calculatedPhase) return;
await _cyclesService.updateCycleProgress(
userId: userId,
startDate: startDate,
);
await _createPhaseSnapshot(
userId: userId,
phase: calculatedPhase,
daysSincePlanting: days,
);
}
Future<void> _createPhaseSnapshot({
required String userId,
required String phase,
int? daysSincePlanting,
}) async {
await _firestore.collection('hidroponik_data').add({
'user_id': userId,
'growth_phase': phase,
if (daysSincePlanting != null) 'days_since_planting': daysSincePlanting,
'pH_value': 0.0,
'nutrient_level': 0.0,
'pump_ph_up_status': false,
'pump_ph_down_status': false,
'pump_nutrient_status': false,
'pump_water_status': false,
'timestamp': FieldValue.serverTimestamp(),
});
}
}