TKK_E32220332/lib/screens/analytics_screen.dart

158 lines
5.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart';
import '../services/supabase_service.dart';
class AnalyticsScreen extends StatefulWidget {
const AnalyticsScreen({super.key});
@override
State<AnalyticsScreen> createState() => _AnalyticsScreenState();
}
class _AnalyticsScreenState extends State<AnalyticsScreen> {
List<Map<String, dynamic>> _logs = [];
bool _isLoading = true;
@override
void initState() {
super.initState();
_fetchLogs();
}
Future<void> _fetchLogs() async {
try {
final data = await SupabaseService().getSensorLogs();
setState(() {
_logs = data;
_isLoading = false;
});
} catch (e) {
debugPrint('Error fetching logs: $e');
setState(() => _isLoading = false);
}
}
@override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;
final String title = args['title'];
final Color color = args['color'];
final String sensorKey = title.contains('Suhu') ? 'suhu' : title.contains('Kelembaban') ? 'kelembapan' : 'intensitas';
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.black,
title: Text(title, style: const TextStyle(color: Colors.white)),
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.grey),
onPressed: () => Navigator.pop(context),
),
),
body: _isLoading
? const Center(child: CircularProgressIndicator(color: Colors.green))
: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
_buildChartCard(title, color, _logs, sensorKey),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Riwayat Data', style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)),
IconButton(icon: const Icon(Icons.refresh, color: Colors.green), onPressed: _fetchLogs),
],
),
const SizedBox(height: 10),
Expanded(
child: Container(
decoration: BoxDecoration(
color: const Color(0xFF1A1A1A),
borderRadius: BorderRadius.circular(20),
),
child: ListView.separated(
padding: const EdgeInsets.all(15),
itemCount: _logs.length,
separatorBuilder: (context, index) => const Divider(color: Colors.grey),
itemBuilder: (context, index) {
final log = _logs[index];
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(log['timestamp'] ?? '', style: const TextStyle(color: Colors.grey, fontSize: 10)),
Text('Fans: ${log['kipas1']}/${log['kipas2']}', style: const TextStyle(color: Colors.green, fontSize: 10)),
],
),
Text('${log[sensorKey]}', style: TextStyle(color: color, fontWeight: FontWeight.bold)),
],
),
);
},
),
),
),
],
),
),
);
}
Widget _buildChartCard(String title, Color color, List<Map<String, dynamic>> logs, String key) {
List<FlSpot> spots = [];
if (logs.isNotEmpty) {
final reversedLogs = logs.reversed.toList();
for (int i = 0; i < reversedLogs.length; i++) {
spots.add(FlSpot(i.toDouble(), double.tryParse(reversedLogs[i][key].toString()) ?? 0));
}
}
return Container(
height: 250,
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: const Color(0xFF1A1A1A),
borderRadius: BorderRadius.circular(20),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
const SizedBox(height: 20),
Expanded(
child: LineChart(
LineChartData(
gridData: FlGridData(show: false),
titlesData: FlTitlesData(show: false),
borderData: FlBorderData(show: false),
lineBarsData: [
LineChartBarData(
spots: spots.isEmpty ? [const FlSpot(0, 0)] : spots,
isCurved: true,
color: color,
barWidth: 4,
dotData: FlDotData(show: false),
belowBarData: BarAreaData(show: true, color: color.withOpacity(0.1)),
),
],
),
),
),
Align(
alignment: Alignment.bottomRight,
child: Text(
'Terakhir: ${logs.isNotEmpty ? logs.first[key] : "-"}',
style: TextStyle(color: color, fontSize: 12)
),
),
],
),
);
}
}