757 lines
30 KiB
Dart
757 lines
30 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:firebase_database/firebase_database.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:jago/services/db_helper.dart';
|
|
import 'package:jago/services/notification_service.dart'; // Import layanan notifikasi
|
|
import 'package:excel/excel.dart' as excel;
|
|
import 'dart:io';
|
|
import 'dart:async';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
|
|
class NotificationPage extends StatefulWidget {
|
|
@override
|
|
_NotificationPageState createState() => _NotificationPageState();
|
|
}
|
|
|
|
class _NotificationPageState extends State<NotificationPage> {
|
|
List<Map<String, dynamic>> notifications = [];
|
|
List<Map<String, dynamic>> filteredNotifications = [];
|
|
late DatabaseHelper dbHelper;
|
|
DateTime? selectedDate;
|
|
int ageInWeeks = 2;
|
|
late DatabaseReference ageRef;
|
|
int selectedAge = 0; // 0 untuk umur saat ini, 1-4 untuk umur spesifik
|
|
|
|
// Tambahkan variabel untuk row pages
|
|
int _rowsPerPage = 10;
|
|
List<int> _rowsPerPageOptions = [5, 10, 20, 50, 100];
|
|
int _currentPage = 0;
|
|
|
|
// Inisialisasi notifikasi lokal
|
|
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
|
|
|
// Daftar subscription untuk dibersihkan saat dispose
|
|
final List<StreamSubscription> _subscriptions = [];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
dbHelper = DatabaseHelper();
|
|
ageRef = FirebaseDatabase.instance.ref("chicken_age");
|
|
|
|
// Periksa tabel notifications
|
|
dbHelper.checkTables().then((_) {
|
|
_fetchAgeFromFirebase();
|
|
_loadNotificationsFromDB();
|
|
});
|
|
|
|
// Pastikan NotificationService sudah diinisialisasi
|
|
NotificationService().initialize();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
// Membersihkan semua subscription untuk mencegah memory leak
|
|
for (var subscription in _subscriptions) {
|
|
subscription.cancel();
|
|
}
|
|
super.dispose();
|
|
}
|
|
|
|
void _fetchAgeFromFirebase() {
|
|
final subscription = ageRef.onValue.listen((event) {
|
|
final data = event.snapshot.value;
|
|
if (data != null) {
|
|
int newAge = int.parse(data.toString());
|
|
if (newAge != ageInWeeks) {
|
|
print("🐔 Umur ayam berubah dari $ageInWeeks ke $newAge");
|
|
setState(() {
|
|
ageInWeeks = newAge;
|
|
});
|
|
// Muat ulang notifikasi saat umur berubah
|
|
_loadNotificationsFromDB();
|
|
}
|
|
}
|
|
});
|
|
_subscriptions.add(subscription);
|
|
}
|
|
|
|
Future<void> _loadNotificationsFromDB() async {
|
|
List<Map<String, dynamic>> dbData = await dbHelper.getNotifications();
|
|
print("🔍 Total notifikasi dari database: ${dbData.length}");
|
|
|
|
setState(() {
|
|
notifications = _filterUniqueNotifications(dbData);
|
|
_applyFilter();
|
|
});
|
|
print("✅ Berhasil memuat ${notifications.length} notifikasi dari database");
|
|
}
|
|
|
|
Future<void> _refreshNotifications() async {
|
|
await _loadNotificationsFromDB();
|
|
}
|
|
|
|
List<Map<String, dynamic>> _filterUniqueNotifications(List<Map<String, dynamic>> data) {
|
|
List<Map<String, dynamic>> uniqueData = [];
|
|
Map<String, dynamic>? lastEntry;
|
|
|
|
for (var entry in data) {
|
|
if (lastEntry == null || lastEntry['event'] != entry['event']) {
|
|
uniqueData.add(entry);
|
|
lastEntry = entry;
|
|
}
|
|
}
|
|
return uniqueData;
|
|
}
|
|
|
|
void _applyFilter() {
|
|
setState(() {
|
|
// Filter berdasarkan tanggal jika dipilih
|
|
List<Map<String, dynamic>> dateFiltered;
|
|
if (selectedDate == null) {
|
|
dateFiltered = List.from(notifications);
|
|
} else {
|
|
String selectedDateString = DateFormat('yyyy-MM-dd').format(selectedDate!);
|
|
dateFiltered = notifications.where((notif) {
|
|
DateTime dateTime = DateTime.parse(notif['timestamp']);
|
|
return DateFormat('yyyy-MM-dd').format(dateTime) == selectedDateString;
|
|
}).toList();
|
|
}
|
|
|
|
// Filter berdasarkan umur ayam yang dipilih
|
|
filteredNotifications = dateFiltered.where((notif) {
|
|
// Ekstrak umur dari pesan notifikasi jika ada
|
|
String eventText = notif['event'] ?? '';
|
|
|
|
// Cek apakah notifikasi berisi informasi umur
|
|
if (eventText.contains("[Umur:")) {
|
|
// Ekstrak umur dari notifikasi
|
|
RegExp regExp = RegExp(r"\[Umur: (\d+) minggu\]");
|
|
Match? match = regExp.firstMatch(eventText);
|
|
|
|
if (match != null && match.groupCount >= 1) {
|
|
int notifAge = int.parse(match.group(1)!);
|
|
|
|
// Jika selectedAge adalah 0, gunakan umur ayam saat ini
|
|
// Jika tidak, gunakan umur yang dipilih
|
|
if (selectedAge == 0) {
|
|
return notifAge == ageInWeeks;
|
|
} else {
|
|
return notifAge == selectedAge;
|
|
}
|
|
}
|
|
return false;
|
|
} else {
|
|
// Untuk notifikasi lama yang tidak memiliki tag umur, tampilkan di umur 2 minggu
|
|
if (selectedAge == 0) {
|
|
// Jika memilih "umur saat ini", tampilkan data lama jika umur saat ini adalah 2
|
|
return ageInWeeks == 2;
|
|
} else {
|
|
// Jika memilih umur spesifik, tampilkan data lama hanya jika memilih umur 2
|
|
return selectedAge == 2;
|
|
}
|
|
}
|
|
}).toList();
|
|
|
|
// Reset halaman saat filter berubah
|
|
_currentPage = 0;
|
|
});
|
|
}
|
|
|
|
Future<void> _pickDate(BuildContext context) async {
|
|
DateTime? pickedDate = await showDatePicker(
|
|
context: context,
|
|
initialDate: selectedDate ?? DateTime.now(),
|
|
firstDate: DateTime(2024),
|
|
lastDate: DateTime(2030),
|
|
builder: (context, child) {
|
|
return Theme(
|
|
data: Theme.of(context).copyWith(
|
|
colorScheme: ColorScheme.light(
|
|
primary: Color(0xFFA82429),
|
|
onPrimary: Colors.white,
|
|
),
|
|
),
|
|
child: child!,
|
|
);
|
|
},
|
|
);
|
|
|
|
if (pickedDate != null) {
|
|
setState(() {
|
|
selectedDate = pickedDate;
|
|
_applyFilter();
|
|
});
|
|
}
|
|
}
|
|
|
|
void _downloadNotificationsAsExcel() async {
|
|
// Filter notifikasi sesuai umur yang dipilih
|
|
List<Map<String, dynamic>> ageFilteredData = notifications.where((notif) {
|
|
String eventText = notif['event'] ?? '';
|
|
|
|
if (eventText.contains("[Umur:")) {
|
|
RegExp regExp = RegExp(r"\[Umur: (\d+) minggu\]");
|
|
Match? match = regExp.firstMatch(eventText);
|
|
|
|
if (match != null && match.groupCount >= 1) {
|
|
int notifAge = int.parse(match.group(1)!);
|
|
|
|
// Jika selectedAge adalah 0, gunakan umur ayam saat ini
|
|
// Jika tidak, gunakan umur yang dipilih
|
|
if (selectedAge == 0) {
|
|
return notifAge == ageInWeeks;
|
|
} else {
|
|
return notifAge == selectedAge;
|
|
}
|
|
}
|
|
return false;
|
|
} else {
|
|
// Untuk notifikasi lama yang tidak memiliki tag umur, tampilkan di umur 2 minggu
|
|
if (selectedAge == 0) {
|
|
// Jika memilih "umur saat ini", tampilkan data lama jika umur saat ini adalah 2
|
|
return ageInWeeks == 2;
|
|
} else {
|
|
// Jika memilih umur spesifik, tampilkan data lama hanya jika memilih umur 2
|
|
return selectedAge == 2;
|
|
}
|
|
}
|
|
}).toList();
|
|
|
|
var excelFile = excel.Excel.createExcel();
|
|
var sheet = excelFile['Sheet1'];
|
|
sheet.appendRow(['Timestamp', 'Event', 'Umur Ayam']);
|
|
|
|
for (var notif in ageFilteredData) {
|
|
String eventText = notif['event'] ?? '';
|
|
|
|
// Ekstrak umur dari teks event jika ada
|
|
int eventAge = 2; // Default umur untuk data lama tanpa tag
|
|
if (eventText.contains("[Umur:")) {
|
|
RegExp regExp = RegExp(r"\[Umur: (\d+) minggu\]");
|
|
Match? match = regExp.firstMatch(eventText);
|
|
|
|
if (match != null && match.groupCount >= 1) {
|
|
eventAge = int.parse(match.group(1)!);
|
|
}
|
|
|
|
// Hapus tag umur dari tampilan
|
|
eventText = eventText.replaceAll(regExp, "").trim();
|
|
}
|
|
|
|
sheet.appendRow([notif['timestamp'], eventText, eventAge]);
|
|
}
|
|
|
|
// Tentukan nama file berdasarkan mode filter umur
|
|
int exportAge = selectedAge == 0 ? ageInWeeks : selectedAge;
|
|
|
|
final directory = Directory('/storage/emulated/0/Documents/Data Notifikasi');
|
|
if (!(await directory.exists())) {
|
|
await directory.create(recursive: true);
|
|
}
|
|
String filePath = '${directory.path}/Notifikasi_${DateFormat('yyyyMMdd').format(DateTime.now())}_Umur${exportAge}minggu.xlsx';
|
|
File(filePath)..writeAsBytesSync(excelFile.encode()!);
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('Data notifikasi berhasil diunduh sebagai Excel'),
|
|
backgroundColor: Color(0xFFA82429),
|
|
behavior: SnackBarBehavior.floating,
|
|
action: SnackBarAction(
|
|
label: 'OK',
|
|
textColor: Colors.white,
|
|
onPressed: () {},
|
|
),
|
|
)
|
|
);
|
|
}
|
|
|
|
// Tambahkan method untuk paginasi
|
|
List<Map<String, dynamic>> _getPaginatedData() {
|
|
if (filteredNotifications.isEmpty) return [];
|
|
|
|
int startIndex = _currentPage * _rowsPerPage;
|
|
int endIndex = startIndex + _rowsPerPage;
|
|
|
|
if (startIndex >= filteredNotifications.length) {
|
|
_currentPage = 0;
|
|
startIndex = 0;
|
|
endIndex = _rowsPerPage;
|
|
}
|
|
|
|
if (endIndex > filteredNotifications.length) {
|
|
endIndex = filteredNotifications.length;
|
|
}
|
|
|
|
return filteredNotifications.sublist(startIndex, endIndex);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Dapatkan data yang sudah dipaginasi
|
|
final paginatedData = _getPaginatedData();
|
|
final int totalPages = (filteredNotifications.length / _rowsPerPage).ceil();
|
|
|
|
// Tentukan judul AppBar berdasarkan mode filter umur
|
|
String appBarTitle = selectedAge == 0
|
|
? 'Notifikasi (Umur: $ageInWeeks minggu)'
|
|
: 'Notifikasi (Umur: $selectedAge minggu)';
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
backgroundColor: Color(0xFFA82429),
|
|
elevation: 0,
|
|
leading: IconButton(
|
|
icon: Icon(Icons.arrow_back, color: Colors.white),
|
|
onPressed: () => Navigator.pop(context),
|
|
),
|
|
title: Text(
|
|
appBarTitle,
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
)
|
|
),
|
|
),
|
|
body: Column(
|
|
children: [
|
|
// Header section with curved background
|
|
Container(
|
|
padding: EdgeInsets.fromLTRB(16, 0, 16, 20),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFA82429),
|
|
borderRadius: BorderRadius.only(
|
|
bottomLeft: Radius.circular(30),
|
|
bottomRight: Radius.circular(30),
|
|
),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.grey.withOpacity(0.5),
|
|
spreadRadius: 2,
|
|
blurRadius: 5,
|
|
offset: Offset(0, 3),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(10),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 4,
|
|
offset: Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(
|
|
Icons.calendar_today,
|
|
color: Color(0xFFA82429),
|
|
size: 20,
|
|
),
|
|
SizedBox(width: 8),
|
|
Expanded(
|
|
child: Text(
|
|
selectedDate == null
|
|
? 'Semua Tanggal'
|
|
: DateFormat('dd/MM/yyyy').format(selectedDate!),
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
),
|
|
TextButton(
|
|
onPressed: () => _pickDate(context),
|
|
child: Text(
|
|
'Pilih',
|
|
style: TextStyle(
|
|
color: Color(0xFFA82429),
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
style: TextButton.styleFrom(
|
|
minimumSize: Size(0, 0),
|
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 12),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(10),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 4,
|
|
offset: Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: DropdownButtonHideUnderline(
|
|
child: DropdownButton<int>(
|
|
value: selectedAge,
|
|
isExpanded: true,
|
|
icon: Icon(Icons.filter_list, color: Color(0xFFA82429)),
|
|
items: [
|
|
DropdownMenuItem<int>(
|
|
value: 0,
|
|
child: Text('Umur Saat Ini (${ageInWeeks} minggu)'),
|
|
),
|
|
DropdownMenuItem<int>(
|
|
value: 1,
|
|
child: Text('Umur 1 minggu'),
|
|
),
|
|
DropdownMenuItem<int>(
|
|
value: 2,
|
|
child: Text('Umur 2 minggu'),
|
|
),
|
|
DropdownMenuItem<int>(
|
|
value: 3,
|
|
child: Text('Umur 3 minggu'),
|
|
),
|
|
DropdownMenuItem<int>(
|
|
value: 4,
|
|
child: Text('Umur 4 minggu'),
|
|
),
|
|
],
|
|
onChanged: (int? newValue) {
|
|
if (newValue != null) {
|
|
setState(() {
|
|
selectedAge = newValue;
|
|
_applyFilter();
|
|
});
|
|
}
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(width: 10),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(10),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 4,
|
|
offset: Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: IconButton(
|
|
icon: Icon(Icons.file_download, color: Color(0xFFA82429)),
|
|
onPressed: _downloadNotificationsAsExcel,
|
|
tooltip: 'Unduh Data Excel',
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Paginasi controls
|
|
Padding(
|
|
padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Text(
|
|
'Baris per halaman: ',
|
|
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
|
|
),
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 0),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Colors.grey.shade300),
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
child: DropdownButtonHideUnderline(
|
|
child: DropdownButton<int>(
|
|
value: _rowsPerPage,
|
|
isDense: true,
|
|
items: _rowsPerPageOptions.map((int value) {
|
|
return DropdownMenuItem<int>(
|
|
value: value,
|
|
child: Text(value.toString()),
|
|
);
|
|
}).toList(),
|
|
onChanged: (newValue) {
|
|
if (newValue != null) {
|
|
setState(() {
|
|
_rowsPerPage = newValue;
|
|
_currentPage = 0; // Reset ke halaman pertama
|
|
});
|
|
}
|
|
},
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
if (totalPages > 0)
|
|
Row(
|
|
children: [
|
|
IconButton(
|
|
icon: Icon(Icons.arrow_back_ios, size: 16),
|
|
color: _currentPage > 0 ? Color(0xFFA82429) : Colors.grey,
|
|
onPressed: _currentPage > 0
|
|
? () {
|
|
setState(() {
|
|
_currentPage--;
|
|
});
|
|
}
|
|
: null,
|
|
),
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFA82429),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Text(
|
|
'${_currentPage + 1} / $totalPages',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: Icon(Icons.arrow_forward_ios, size: 16),
|
|
color: _currentPage < totalPages - 1 ? Color(0xFFA82429) : Colors.grey,
|
|
onPressed: _currentPage < totalPages - 1
|
|
? () {
|
|
setState(() {
|
|
_currentPage++;
|
|
});
|
|
}
|
|
: null,
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// List of notifications
|
|
Expanded(
|
|
child: RefreshIndicator(
|
|
onRefresh: _refreshNotifications,
|
|
color: Color(0xFFA82429),
|
|
child: paginatedData.isEmpty
|
|
? Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
Icons.notifications_off,
|
|
size: 64,
|
|
color: Colors.grey,
|
|
),
|
|
SizedBox(height: 16),
|
|
Text(
|
|
selectedAge == 0
|
|
? 'Tidak ada notifikasi untuk umur ayam $ageInWeeks minggu'
|
|
: 'Tidak ada notifikasi untuk umur ayam $selectedAge minggu',
|
|
style: TextStyle(
|
|
color: Colors.grey[600],
|
|
fontSize: 16,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
],
|
|
),
|
|
)
|
|
: ListView.builder(
|
|
padding: EdgeInsets.symmetric(horizontal: 16),
|
|
itemCount: paginatedData.length,
|
|
itemBuilder: (context, index) {
|
|
final notif = paginatedData[index];
|
|
final DateTime dateTime = DateTime.parse(notif['timestamp']);
|
|
String eventText = notif['event'] ?? 'Data tidak tersedia';
|
|
|
|
// Ekstrak umur dari teks event jika ada
|
|
int eventAge = 2; // Default untuk data lama tanpa tag
|
|
if (eventText.contains("[Umur:")) {
|
|
RegExp regExp = RegExp(r"\[Umur: (\d+) minggu\]");
|
|
Match? match = regExp.firstMatch(eventText);
|
|
|
|
if (match != null && match.groupCount >= 1) {
|
|
eventAge = int.parse(match.group(1)!);
|
|
}
|
|
|
|
// Hapus tag umur dari tampilan
|
|
eventText = eventText.replaceAll(regExp, "").trim();
|
|
}
|
|
|
|
// Tentukan warna berdasarkan jenis notifikasi
|
|
Color cardColor;
|
|
Color timeColor;
|
|
IconData iconData;
|
|
|
|
if (eventText.contains('Kritis') ||
|
|
eventText.contains('Sangat Tinggi') ||
|
|
eventText.contains('Sangat Rendah') ||
|
|
eventText.contains('darurat')) {
|
|
cardColor = Colors.red;
|
|
timeColor = Colors.red[200]!;
|
|
// Use temperature or humidity specific icons when relevant
|
|
if (eventText.contains('Suhu')) {
|
|
iconData = Icons.thermostat;
|
|
} else if (eventText.contains('Kelembapan')) {
|
|
iconData = Icons.water_drop;
|
|
} else {
|
|
iconData = Icons.warning;
|
|
}
|
|
} else if (eventText.contains('tinggi') || eventText.contains('rendah')) {
|
|
cardColor = Colors.orange;
|
|
timeColor = Colors.orange[200]!;
|
|
// Use temperature or humidity specific icons when relevant
|
|
if (eventText.contains('Suhu')) {
|
|
iconData = Icons.thermostat;
|
|
} else if (eventText.contains('Kelembapan')) {
|
|
iconData = Icons.water_drop;
|
|
} else {
|
|
iconData = Icons.warning_amber;
|
|
}
|
|
} else if (eventText.contains('Fuzzy')) {
|
|
cardColor = Colors.blue;
|
|
timeColor = Colors.blue[200]!;
|
|
// Use temperature or humidity specific icons for Fuzzy notifications
|
|
if (eventText.contains('Suhu')) {
|
|
iconData = Icons.thermostat;
|
|
} else if (eventText.contains('Kelembapan')) {
|
|
iconData = Icons.water_drop;
|
|
} else {
|
|
iconData = Icons.auto_graph;
|
|
}
|
|
} else if (eventText.contains('Status')) {
|
|
cardColor = Colors.purple;
|
|
timeColor = Colors.purple[200]!;
|
|
// Use temperature or humidity specific icons for Status notifications
|
|
if (eventText.contains('Suhu')) {
|
|
iconData = Icons.thermostat;
|
|
} else if (eventText.contains('Kelembapan')) {
|
|
iconData = Icons.water_drop;
|
|
} else {
|
|
iconData = Icons.info;
|
|
}
|
|
} else if (eventText.contains('normal') ||
|
|
eventText.contains('Normal') ||
|
|
eventText.contains('Optimal')) {
|
|
cardColor = Colors.green;
|
|
timeColor = Colors.green[200]!;
|
|
// Use temperature or humidity specific icons for normal notifications
|
|
if (eventText.contains('Suhu')) {
|
|
iconData = Icons.thermostat;
|
|
} else if (eventText.contains('Kelembapan')) {
|
|
iconData = Icons.water_drop;
|
|
} else {
|
|
iconData = Icons.check_circle;
|
|
}
|
|
} else {
|
|
cardColor = Colors.blueGrey;
|
|
timeColor = Colors.blueGrey[200]!;
|
|
iconData = Icons.notifications;
|
|
}
|
|
|
|
return Card(
|
|
elevation: 3,
|
|
margin: EdgeInsets.only(bottom: 12),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
),
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadius.circular(16),
|
|
child: Column(
|
|
children: [
|
|
// Colored header
|
|
Container(
|
|
color: cardColor,
|
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
child: Row(
|
|
children: [
|
|
Icon(
|
|
iconData,
|
|
color: Colors.white,
|
|
size: 20,
|
|
),
|
|
SizedBox(width: 8),
|
|
Expanded(
|
|
child: Text(
|
|
DateFormat('dd/MM/yyyy HH:mm').format(dateTime),
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: timeColor,
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Text(
|
|
'Umur: $eventAge minggu',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.bold,
|
|
color: cardColor,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// Message body
|
|
Container(
|
|
width: double.infinity,
|
|
padding: EdgeInsets.all(16),
|
|
child: Text(
|
|
eventText,
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|