import 'package:flutter/material.dart'; import '../models/sensor_data_model.dart'; import '../services/realtime_database_service.dart'; import '../services/auth_service.dart'; import '../utils/app_colors.dart'; import '../widgets/sensor_card.dart'; import '../widgets/custom_button.dart'; import 'login_screen.dart'; class DashboardScreen extends StatefulWidget { const DashboardScreen({Key? key}) : super(key: key); @override State createState() => _DashboardScreenState(); } class _DashboardScreenState extends State { final RealtimeDatabaseService _dbService = RealtimeDatabaseService(); final AuthService _authService = AuthService(); bool _isLoading = false; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Dashboard Deteksi Kebakaran'), backgroundColor: AppColors.primaryRed, foregroundColor: AppColors.textLight, elevation: 0, actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: () { setState(() {}); }, ), PopupMenuButton( onSelected: (value) { if (value == 'logout') { _handleLogout(); } }, itemBuilder: (BuildContext context) => [ PopupMenuItem( value: 'logout', child: Row( children: [ Icon(Icons.logout, color: AppColors.textError), const SizedBox(width: 8), Text('Logout'), ], ), ), ], ), ], ), body: StreamBuilder( stream: _dbService.sensorDataStream, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(AppColors.primaryRed), ), ); } if (snapshot.hasError) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.error_outline, size: 64, color: AppColors.textError, ), const SizedBox(height: 16), Text( 'Gagal memuat data sensor', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: AppColors.textError, ), ), const SizedBox(height: 8), Text( 'Periksa koneksi internet Anda', style: TextStyle( fontSize: 14, color: AppColors.textSecondary, ), ), const SizedBox(height: 16), ElevatedButton( onPressed: () { setState(() {}); }, child: const Text('Coba Lagi'), ), ], ), ); } final sensorData = snapshot.data!; return RefreshIndicator( onRefresh: () async { setState(() {}); }, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Status Overview _buildStatusOverview(sensorData), const SizedBox(height: 24), // Sensor Data Section _buildSectionTitle('Data Sensor'), _buildSensorCards(sensorData), const SizedBox(height: 24), // Control Section // _buildSectionTitle('Kontrol Sistem'), // _buildControlCards(sensorData), const SizedBox(height: 24), // Emergency Actions // _buildEmergencyActions(), ], ), ), ); }, ), ); } Widget _buildStatusOverview(SensorData sensorData) { Color statusColor; String statusText; IconData statusIcon; if (sensorData.isFireDetected) { statusColor = AppColors.textError; statusText = 'BAHAYA - API TERDETEKSI'; statusIcon = Icons.local_fire_department; } else if (sensorData.isWarning) { statusColor = AppColors.primaryOrange; statusText = 'WASPADA - KONDISI ABNORMAL'; statusIcon = Icons.warning; } else { statusColor = AppColors.accentGreen; statusText = 'AMAN - KONDISI NORMAL'; statusIcon = Icons.check_circle; } return Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [statusColor, statusColor.withOpacity(0.8)], ), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: statusColor.withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: Column( children: [ Icon(statusIcon, size: 48, color: AppColors.textLight), const SizedBox(height: 12), Text( statusText, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: AppColors.textLight, ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( 'Terakhir Update: ${DateTime.now().toString().substring(0, 19)}', style: TextStyle( fontSize: 12, color: AppColors.textLight.withOpacity(0.8), ), ), ], ), ); } Widget _buildSectionTitle(String title) { return Padding( padding: const EdgeInsets.only(bottom: 16), child: Text( title, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: AppColors.textPrimary, ), ), ); } Widget _buildSensorCards(SensorData sensorData) { return Column( children: [ SensorCard( title: 'Suhu', value: sensorData.suhu.toStringAsFixed(1), unit: '°C', icon: Icons.thermostat, statusColor: sensorData.suhu > 35 ? AppColors.textError : sensorData.suhu > 25 ? AppColors.accentGreen : AppColors.primaryBlue, status: sensorData.statusSuhu, ), SensorCard( title: 'Kelembapan', value: sensorData.kelembapan.toString(), unit: '%', icon: Icons.water_drop, statusColor: sensorData.kelembapan > 70 ? AppColors.primaryBlue : sensorData.kelembapan > 40 ? AppColors.accentGreen : AppColors.primaryOrange, status: sensorData.statusKelembapan, ), SensorCard( title: 'Gas', value: sensorData.gasValue.toString(), unit: 'ppm', icon: Icons.air, statusColor: sensorData.gasValue > 300 ? AppColors.textError : sensorData.gasValue > 150 ? AppColors.primaryOrange : AppColors.accentGreen, status: sensorData.statusGas, ), SensorCard( title: 'Deteksi Api', value: sensorData.apiTerdeteksi ? 'TERDETEKSI' : 'AMAN', unit: '', icon: Icons.local_fire_department, statusColor: sensorData.apiTerdeteksi ? AppColors.textError : AppColors.accentGreen, status: sensorData.statusApi, ), ], ); } Widget _buildControlCards(SensorData sensorData) { return Column( children: [ ControlCard( title: 'Buzzer', description: 'Alarm suara peringatan', icon: Icons.volume_up, isActive: sensorData.buzzerActive, activeColor: AppColors.primaryOrange, onToggle: () => _toggleControl('buzzer', !sensorData.buzzerActive), ), ControlCard( title: 'Exhaust Fan', description: 'Kipas pembuangan asap', icon: Icons.air, isActive: sensorData.exhaustActive, activeColor: AppColors.primaryBlue, onToggle: () => _toggleControl('exhaust', !sensorData.exhaustActive), ), ControlCard( title: 'Water Pump', description: 'Pompa air pemadam', icon: Icons.water, isActive: sensorData.pumpActive, activeColor: AppColors.accentGreen, onToggle: () => _toggleControl('pump', !sensorData.pumpActive), ), ], ); } Widget _buildEmergencyActions() { return Column( children: [ const SizedBox(height: 16), // Mode Darurat Button CustomButton( text: 'Mode Darurat', onPressed: _activateEmergencyMode, backgroundColor: AppColors.textError, icon: Icons.emergency, isLoading: _isLoading, width: double.infinity, ), const SizedBox(height: 8), // Reset Semua Button CustomButton( text: 'Reset Semua', onPressed: _resetAllControls, backgroundColor: AppColors.secondaryGray, icon: Icons.refresh, isLoading: _isLoading, width: double.infinity, ), ], ); } Future _toggleControl(String controlType, bool value) async { setState(() { _isLoading = true; }); try { switch (controlType) { case 'buzzer': await _dbService.updateControl(buzzerActive: value); break; case 'exhaust': await _dbService.updateControl(exhaustActive: value); break; case 'pump': await _dbService.updateControl(pumpActive: value); break; } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Kontrol $controlType berhasil diupdate'), backgroundColor: AppColors.accentGreen, ), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toString()), backgroundColor: AppColors.textError, ), ); } finally { setState(() { _isLoading = false; }); } } Future _activateEmergencyMode() async { setState(() { _isLoading = true; }); try { await _dbService.activateEmergencyMode(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Mode darurat diaktifkan!'), backgroundColor: AppColors.textError, ), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toString()), backgroundColor: AppColors.textError, ), ); } finally { setState(() { _isLoading = false; }); } } Future _resetAllControls() async { setState(() { _isLoading = true; }); try { await _dbService.resetAllControls(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Semua kontrol berhasil direset'), backgroundColor: AppColors.accentGreen, ), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toString()), backgroundColor: AppColors.textError, ), ); } finally { setState(() { _isLoading = false; }); } } Future _handleLogout() async { try { await _authService.signOut(); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => const LoginScreen()), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toString()), backgroundColor: AppColors.textError, ), ); } } }