import 'package:flutter/material.dart'; import 'package:flutter_echarts/flutter_echarts.dart'; import 'package:firebase_database/firebase_database.dart'; import 'package:intl/intl.dart'; import 'main.dart'; class HistoriDataPage extends StatefulWidget { final String title; const HistoriDataPage({Key? key, required this.title}) : super(key: key); @override _HistoriDataPageState createState() => _HistoriDataPageState(); } class _HistoriDataPageState extends State with RouteAware { final DatabaseReference _databaseReference = FirebaseDatabase.instance.reference().child('sensor_data'); List> _dataHistori = []; DateTime? _startDate; DateTime? _endDate; @override void initState() { super.initState(); _fetchData(); } @override void didChangeDependencies() { super.didChangeDependencies(); final route = ModalRoute.of(context); if (route is PageRoute) { routeObserver.subscribe(this, route); } } @override void dispose() { routeObserver.unsubscribe(this); super.dispose(); } @override void didPopNext() { _fetchData(); } Future _fetchData() async { DataSnapshot snapshot = await _databaseReference.get(); if (snapshot.value != null) { Map data = Map.from(snapshot.value as Map); List> dataList = data.entries.map((entry) { Map value = Map.from(entry.value as Map); return { 'date': entry.key, 'soil': double.tryParse(value['soil'].toString()) ?? 0.0, 'humidity': double.tryParse(value['humidity'].toString()) ?? 0.0, 'temperature': double.tryParse(value['temperature'].toString()) ?? 0.0, 'intensity': double.tryParse(value['intensity'].toString()) ?? 0.0, 'battery': double.tryParse(value['battery'].toString()) ?? 0.0, 'timestamp': value['timestamp'], }; }).toList(); dataList.sort((a, b) { DateTime dateA = DateTime.parse(a['timestamp']); DateTime dateB = DateTime.parse(b['timestamp']); return dateB.compareTo(dateA); }); setState(() { _dataHistori = dataList; }); } } String _formatDate(String timestamp) { final DateTime dateTime = DateTime.parse(timestamp); final DateFormat dateFormatter = DateFormat('dd-MM-yyyy'); return dateFormatter.format(dateTime); } String _formatTime(String timestamp) { final DateTime dateTime = DateTime.parse(timestamp); final DateFormat timeFormatter = DateFormat('HH:mm'); return timeFormatter.format(dateTime); } Future _selectDateRange(BuildContext context) async { final DateTimeRange? picked = await showDateRangePicker( context: context, initialDateRange: _startDate != null && _endDate != null ? DateTimeRange(start: _startDate!, end: _endDate!) : null, firstDate: DateTime(2020), lastDate: DateTime.now(), ); if (picked != null) { setState(() { _startDate = picked.start; _endDate = picked.end; }); } } List> _filterDataByDateRange() { if (_startDate == null || _endDate == null) { return _dataHistori; } return _dataHistori.where((data) { DateTime date = DateTime.parse(data['timestamp']); return date.isAfter(_startDate!.subtract(Duration(days: 1))) && date.isBefore(_endDate!.add(Duration(days: 1))); }).toList(); } @override Widget build(BuildContext context) { List> filteredData = _filterDataByDateRange(); List dates = filteredData.map((data) { return _formatDate(data['timestamp']); }).toList(); List soilData = filteredData.map((data) { return data['soil'] as double; }).toList(); List humidityData = filteredData.map((data) { return data['humidity'] as double; }).toList(); List temperatureData = filteredData.map((data) { return data['temperature'] as double; }).toList(); List intensityData = filteredData.map((data) { return data['intensity'] as double; }).toList(); List batteryData = filteredData.map((data) { return data['battery'] as double; }).toList(); return Scaffold( appBar: AppBar( leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { Navigator.pushReplacementNamed(context, '/home'); }, ), backgroundColor: Colors.brown, title: Text( widget.title, style: TextStyle( fontFamily: 'Quicksand', fontWeight: FontWeight.bold, ), ), actions: [ IconButton( icon: Icon(Icons.calendar_today), onPressed: () => _selectDateRange(context), ), ], ), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( height: 300, child: Echarts( option: ''' { title: { text: 'Soil', left: 'center', }, xAxis: { type: 'category', data: ${dates.map((e) => '"$e"').toList()}, }, yAxis: { type: 'value' }, series: [{ data: $soilData, type: 'line', lineStyle: { color: '#FF0000' } }] } ''', ), ), Container( height: 300, child: Echarts( option: ''' { title: { text: 'Humidity', left: 'center', }, xAxis: { type: 'category', data: ${dates.map((e) => '"$e"').toList()}, }, yAxis: { type: 'value' }, series: [{ data: $humidityData, type: 'line', lineStyle: { color: '#00FF00' } }] } ''', ), ), Container( height: 300, child: Echarts( option: ''' { title: { text: 'Temperature', left: 'center', }, xAxis: { type: 'category', data: ${dates.map((e) => '"$e"').toList()}, }, yAxis: { type: 'value' }, series: [{ data: $temperatureData, type: 'line', lineStyle: { color: '#0000FF' } }] } ''', ), ), Container( height: 300, child: Echarts( option: ''' { title: { text: 'Cahaya', left: 'center', }, xAxis: { type: 'category', data: ${dates.map((e) => '"$e"').toList()}, }, yAxis: { type: 'value' }, series: [{ data: $intensityData, type: 'line', lineStyle: { color: '#FFFF00' } }] } ''', ), ), Container( height: 300, child: Echarts( option: ''' { title: { text: 'Battery', left: 'center', }, xAxis: { type: 'category', data: ${dates.map((e) => '"$e"').toList()}, }, yAxis: { type: 'value' }, series: [{ data: $batteryData, type: 'line', lineStyle: { color: '#FF00FF' } }] } ''', ), ), ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), itemCount: filteredData.length, itemBuilder: (context, index) { final data = filteredData[index]; return Card( margin: EdgeInsets.symmetric(vertical: 8.0), child: Padding( padding: EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( _formatDate(data['timestamp']), style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold), ), Text( _formatTime(data['timestamp']), style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold), ), ], ), SizedBox(height: 8.0), Divider(), SizedBox(height: 8.0), _buildDataRow('Soil', '${data['soil']} %'), _buildDataRow('Humidity', '${data['humidity']} %'), _buildDataRow( 'Temperature', '${data['temperature']} °C'), _buildDataRow('Cahaya', '${data['intensity']} lux'), _buildDataRow('Battery', '${data['battery']} %'), ], ), ), ); }, ), ], ), ), ), ); } Widget _buildDataRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( label, style: TextStyle(fontSize: 16), ), Text( value, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ], ), ); } }