341 lines
12 KiB
Dart
341 lines
12 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:tugasakhir/models/history_model.dart';
|
|
import 'package:fl_chart/fl_chart.dart';
|
|
|
|
class HistoryScreen extends StatefulWidget {
|
|
const HistoryScreen({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
_HistoryScreenState createState() => _HistoryScreenState();
|
|
}
|
|
|
|
class _HistoryScreenState extends State<HistoryScreen> {
|
|
List<History> historyList = [];
|
|
String selectedUser = '';
|
|
List<String> userNames = [];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
fetchHistoryData();
|
|
fetchUserData();
|
|
}
|
|
|
|
void fetchHistoryData() async {
|
|
try {
|
|
FirebaseFirestore.instance
|
|
.collection('history_timbangan')
|
|
.orderBy('timestamp')
|
|
.snapshots()
|
|
.listen((event) {
|
|
List<History> fetchedHistory = [];
|
|
for (var doc in event.docs) {
|
|
fetchedHistory.add(History(
|
|
tanggal: (doc['timestamp'] as Timestamp).toDate(),
|
|
berat: doc['berat'].toDouble(),
|
|
tinggi: doc['tinggi'].toDouble(),
|
|
bmi: doc['bmi'].toDouble(),
|
|
user: doc['user'],
|
|
));
|
|
}
|
|
setState(() {
|
|
historyList = fetchedHistory;
|
|
});
|
|
});
|
|
} catch (e) {
|
|
print("Error fetching data: $e");
|
|
}
|
|
}
|
|
|
|
void fetchUserData() async {
|
|
try {
|
|
FirebaseFirestore.instance
|
|
.collection('users')
|
|
.get()
|
|
.then((QuerySnapshot querySnapshot) {
|
|
List<String> users = [];
|
|
querySnapshot.docs.forEach((doc) {
|
|
users.add(doc['nama']);
|
|
});
|
|
setState(() {
|
|
userNames = users;
|
|
if (userNames.isNotEmpty) {
|
|
selectedUser = userNames[0];
|
|
}
|
|
});
|
|
});
|
|
} catch (e) {
|
|
print("Error fetching user data: $e");
|
|
}
|
|
}
|
|
|
|
Future<void> deleteUserData() async {
|
|
try {
|
|
var collection = FirebaseFirestore.instance.collection('history_timbangan');
|
|
var snapshots = await collection
|
|
.where('user', isEqualTo: selectedUser) // Filter by selected user
|
|
.get();
|
|
for (var doc in snapshots.docs) {
|
|
await doc.reference.delete();
|
|
}
|
|
print('Data pengguna $selectedUser telah dihapus');
|
|
setState(() {
|
|
historyList.removeWhere((history) => history.user == selectedUser);
|
|
});
|
|
} catch (e) {
|
|
print("Error deleting data: $e");
|
|
}
|
|
}
|
|
|
|
Future<void> deleteUserAndHistoryData() async {
|
|
try {
|
|
var collection = FirebaseFirestore.instance.collection('history_timbangan');
|
|
var snapshots = await collection
|
|
.where('user', isEqualTo: selectedUser) // Filter by selected user
|
|
.get();
|
|
for (var doc in snapshots.docs) {
|
|
await doc.reference.delete();
|
|
}
|
|
|
|
// Now delete the user from the 'users' collection
|
|
var userDoc = await FirebaseFirestore.instance
|
|
.collection('users')
|
|
.where('nama', isEqualTo: selectedUser)
|
|
.get();
|
|
if (userDoc.docs.isNotEmpty) {
|
|
await userDoc.docs.first.reference.delete(); // Delete the user's document from 'users' collection
|
|
}
|
|
|
|
print('Data pengguna $selectedUser dan data historinya telah dihapus');
|
|
setState(() {
|
|
historyList.removeWhere((history) => history.user == selectedUser);
|
|
userNames.remove(selectedUser); // Remove the deleted user from the list
|
|
if (userNames.isNotEmpty) {
|
|
selectedUser = userNames[0]; // Set the first user as default
|
|
}
|
|
});
|
|
} catch (e) {
|
|
print("Error deleting user and history data: $e");
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
List<History> filteredHistoryList = historyList
|
|
.where((history) => history.user == selectedUser)
|
|
.toList()
|
|
.take(8)
|
|
.toList();
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
backgroundColor: const Color(0xFF59A4EB),
|
|
elevation: 0,
|
|
title: Row(
|
|
children: [
|
|
const Icon(Icons.history, size: 36, color: Colors.white),
|
|
const SizedBox(width: 10),
|
|
Text(
|
|
'History Pengukuran',
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
const Spacer(),
|
|
],
|
|
),
|
|
),
|
|
body: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0),
|
|
child: ListView(
|
|
children: [
|
|
const Text('Pilih User untuk Menampilkan Data Pengukuran',
|
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xFF638BF7))),
|
|
const SizedBox(height: 12),
|
|
|
|
DropdownButton<String>(
|
|
value: selectedUser.isEmpty ? null : selectedUser,
|
|
onChanged: (String? newValue) {
|
|
setState(() {
|
|
selectedUser = newValue!;
|
|
});
|
|
},
|
|
items: userNames
|
|
.map<DropdownMenuItem<String>>((String value) {
|
|
return DropdownMenuItem<String>(
|
|
value: value,
|
|
child: Text(value),
|
|
);
|
|
}).toList(),
|
|
),
|
|
|
|
const SizedBox(height: 12),
|
|
|
|
filteredHistoryList.isEmpty
|
|
? const Center(
|
|
child: Text(
|
|
'Tidak ada data',
|
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.grey),
|
|
),
|
|
)
|
|
: Column(
|
|
children: [
|
|
SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
child: DataTable(
|
|
columnSpacing: 16.0,
|
|
columns: const [
|
|
DataColumn(label: Text('Tanggal')),
|
|
DataColumn(label: Text('User')),
|
|
DataColumn(label: Text('Berat (kg)')),
|
|
DataColumn(label: Text('Tinggi (cm)')),
|
|
DataColumn(label: Text('BMI')),
|
|
],
|
|
rows: filteredHistoryList
|
|
.map(
|
|
(history) => DataRow(cells: [
|
|
DataCell(Text(
|
|
"${history.tanggal.day}/${history.tanggal.month}/${history.tanggal.year}")),
|
|
DataCell(Text(history.user)),
|
|
DataCell(Text(history.berat.toStringAsFixed(1))),
|
|
DataCell(Text(history.tinggi.toStringAsFixed(1))),
|
|
DataCell(Text(history.bmi.toStringAsFixed(2))),
|
|
]),
|
|
)
|
|
.toList(),
|
|
),
|
|
),
|
|
const SizedBox(height: 24),
|
|
|
|
const Text(
|
|
'Grafik Perubahan Pengukuran',
|
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF638BF7)),
|
|
),
|
|
const SizedBox(height: 12),
|
|
|
|
_buildChart('Grafik Berat (kg)', Colors.blue, filteredHistoryList, (history) => history.berat),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
_buildChart('Grafik Tinggi (cm)', Colors.green, filteredHistoryList, (history) => history.tinggi),
|
|
|
|
const SizedBox(height: 12),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertDialog(
|
|
title: const Text('Konfirmasi Penghapusan'),
|
|
content: const Text('Apakah Anda yakin ingin menghapus data pengguna ini?'),
|
|
actions: <Widget>[
|
|
TextButton(
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
},
|
|
child: const Text('Batal'),
|
|
),
|
|
TextButton(
|
|
onPressed: () {
|
|
deleteUserData();
|
|
Navigator.of(context).pop();
|
|
},
|
|
child: const Text('Hapus Data'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
},
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.red,
|
|
),
|
|
child: const Text('Hapus Data Pengguna Ini'),
|
|
),
|
|
const SizedBox(height: 24),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertDialog(
|
|
title: const Text('Konfirmasi Penghapusan Semua Data'),
|
|
content: const Text('Apakah Anda yakin ingin menghapus semua data pengguna dan data historinya?'),
|
|
actions: <Widget>[
|
|
TextButton(
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
},
|
|
child: const Text('Batal'),
|
|
),
|
|
TextButton(
|
|
onPressed: () {
|
|
deleteUserAndHistoryData();
|
|
Navigator.of(context).pop();
|
|
},
|
|
child: const Text('Hapus Semua Data'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
},
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.red,
|
|
),
|
|
child: const Text('Hapus Semua Data Pengguna dan Histori'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildChart(String title, Color color, List<History> filteredHistoryList, double Function(History) dataExtractor) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
title,
|
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: Colors.black),
|
|
),
|
|
const SizedBox(height: 12),
|
|
SizedBox(
|
|
height: 300,
|
|
child: LineChart(
|
|
LineChartData(
|
|
gridData: FlGridData(show: true),
|
|
titlesData: FlTitlesData(show: true),
|
|
borderData: FlBorderData(show: true),
|
|
minX: 0,
|
|
maxX: filteredHistoryList.length.toDouble(),
|
|
minY: 0,
|
|
maxY: 100,
|
|
lineBarsData: [
|
|
LineChartBarData(
|
|
spots: filteredHistoryList
|
|
.asMap()
|
|
.map((index, history) => MapEntry(index, FlSpot(index.toDouble(), dataExtractor(history))))
|
|
.values
|
|
.toList(),
|
|
isCurved: true,
|
|
color: color,
|
|
barWidth: 4,
|
|
isStrokeCapRound: true,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|