298 lines
10 KiB
Dart
298 lines
10 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'alert_screen2.dart';
|
|
import 'family_screen.dart';
|
|
import 'package:firebase_database/firebase_database.dart';
|
|
import 'package:firebase_database/ui/firebase_animated_list.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'danger_status_manager.dart';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
|
|
|
|
final databaseReference = FirebaseDatabase.instance.reference();
|
|
|
|
class HomeSatpam extends StatefulWidget {
|
|
@override
|
|
_HomeSatpamState createState() => _HomeSatpamState();
|
|
}
|
|
|
|
class _HomeSatpamState extends State<HomeSatpam> {
|
|
int _selectedIndex = 0;
|
|
|
|
void _onItemTapped(int index) {
|
|
if (index == 2) {
|
|
Navigator.pushReplacementNamed(context, '/login');
|
|
return;
|
|
}
|
|
setState(() {
|
|
_selectedIndex = index;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final widgetOptions = [
|
|
HomeSatpamBody(),
|
|
FamilyScreen(),
|
|
];
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
automaticallyImplyLeading: false,
|
|
backgroundColor: Colors.black,
|
|
title: Row(
|
|
children: [
|
|
SizedBox(width: 8),
|
|
Text(
|
|
"SATPAM",
|
|
style: TextStyle(fontSize: 20),
|
|
),
|
|
],
|
|
),
|
|
actions: <Widget>[
|
|
IconButton(
|
|
icon: Icon(Icons.warning),
|
|
onPressed: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(builder: (context) => AlertScreen2()),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
body: widgetOptions.elementAt(_selectedIndex),
|
|
bottomNavigationBar: BottomNavigationBar(
|
|
backgroundColor: Colors.black,
|
|
items: [
|
|
BottomNavigationBarItem(
|
|
icon: Icon(Icons.home, color: Colors.white),
|
|
label: 'Home',
|
|
),
|
|
BottomNavigationBarItem(
|
|
icon: Icon(Icons.group, color: Colors.white),
|
|
label: 'Penghuni',
|
|
),
|
|
BottomNavigationBarItem(
|
|
icon: Icon(Icons.logout, color: Colors.white),
|
|
label: 'Log Out',
|
|
),
|
|
],
|
|
currentIndex: _selectedIndex,
|
|
selectedItemColor: Colors.blueAccent,
|
|
unselectedItemColor: Colors.white,
|
|
onTap: _onItemTapped,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class HomeSatpamBody extends StatelessWidget {
|
|
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
|
|
|
HomeSatpamBody() {
|
|
final initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
final initializationSettings = InitializationSettings(
|
|
android: initializationSettingsAndroid,
|
|
);
|
|
flutterLocalNotificationsPlugin.initialize(initializationSettings);
|
|
}
|
|
|
|
Future<void> showNotification() async {
|
|
const AndroidNotificationDetails androidPlatformChannelSpecifics =
|
|
AndroidNotificationDetails('your_channel_id', 'your_channel_name',
|
|
channelDescription: 'your_channel_description',
|
|
importance: Importance.max,
|
|
priority: Priority.high,
|
|
ticker: 'ticker');
|
|
const NotificationDetails platformChannelSpecifics =
|
|
NotificationDetails(android: androidPlatformChannelSpecifics);
|
|
await flutterLocalNotificationsPlugin.show(
|
|
0,
|
|
'Peringatan',
|
|
'Ada indikasi kebakaran',
|
|
platformChannelSpecifics,
|
|
payload: 'item x',
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final dangerStatusManager = Provider.of<DangerStatusManager>(context);
|
|
|
|
return Scaffold(
|
|
backgroundColor: Colors.blue[900],
|
|
body: Container(
|
|
padding: EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(height: 20),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
"Status Terkini",
|
|
style: TextStyle(fontSize: 24, color: Colors.white, fontWeight: FontWeight.bold),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 20),
|
|
Expanded(
|
|
child: FirebaseAnimatedList(
|
|
query: databaseReference,
|
|
itemBuilder: (context, snapshot, animation, index) {
|
|
String deviceId = snapshot.key ?? '';
|
|
int flameStatus = int.tryParse(snapshot.child("flameStatus").value.toString()) ?? 0;
|
|
int smokeStatus = int.tryParse(snapshot.child("smokeDetected").value.toString()) ?? 0;
|
|
bool isFlameDanger = flameStatus == 2;
|
|
bool isSmokeDanger = smokeStatus == 2;
|
|
|
|
// Update status outside of the build method to avoid issues
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (isFlameDanger) {
|
|
dangerStatusManager.setFlameStatus(deviceId, true);
|
|
showNotification();
|
|
}
|
|
if (isSmokeDanger) {
|
|
dangerStatusManager.setSmokeStatus(deviceId, true);
|
|
showNotification();
|
|
}
|
|
});
|
|
|
|
bool isFlameBlinking = dangerStatusManager.isFlameBlinking(deviceId);
|
|
bool isSmokeBlinking = dangerStatusManager.isSmokeBlinking(deviceId);
|
|
|
|
return Container(
|
|
margin: EdgeInsets.only(bottom: 16),
|
|
padding: EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
spreadRadius: 2,
|
|
blurRadius: 6,
|
|
offset: Offset(0, 3),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"No Rumah: ${snapshot.child("nomorRumah").value.toString()}",
|
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black),
|
|
),
|
|
SizedBox(height: 8),
|
|
Text(
|
|
"Client ip: ${snapshot.child("clientIP").value.toString()}",
|
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black),
|
|
),
|
|
SizedBox(height: 8),
|
|
Text(
|
|
"Serial Esp: ${snapshot.child("espSerial").value.toString()}",
|
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black),
|
|
),
|
|
SizedBox(height: 8),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
BlinkingIcon(
|
|
icon: Icons.cloud,
|
|
color: dangerStatusManager.isSmokeDanger(deviceId) ? Colors.red : Colors.green,
|
|
isBlinking: isSmokeBlinking,
|
|
),
|
|
SizedBox(width: 16), // Menambahkan jarak di antara ikon-ikon
|
|
BlinkingIcon(
|
|
icon: Icons.local_fire_department,
|
|
color: dangerStatusManager.isFlameDanger(deviceId) ? Colors.red : Colors.green,
|
|
isBlinking: isFlameBlinking,
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 8),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
onPressed: () {
|
|
dangerStatusManager.resetStatus(deviceId);
|
|
},
|
|
child: Text('Reset'),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class BlinkingIcon extends StatefulWidget {
|
|
final IconData icon;
|
|
final Color color;
|
|
final bool isBlinking;
|
|
|
|
BlinkingIcon({required this.icon, required this.color, required this.isBlinking});
|
|
|
|
@override
|
|
_BlinkingIconState createState() => _BlinkingIconState();
|
|
}
|
|
|
|
class _BlinkingIconState extends State<BlinkingIcon> with SingleTickerProviderStateMixin {
|
|
late AnimationController _controller;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = AnimationController(
|
|
duration: const Duration(milliseconds: 500),
|
|
vsync: this,
|
|
)..repeat(reverse: true);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
padding: EdgeInsets.all(8.0),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
spreadRadius: 2,
|
|
blurRadius: 6,
|
|
offset: Offset(0, 3),
|
|
),
|
|
],
|
|
),
|
|
child: widget.isBlinking
|
|
? FadeTransition(
|
|
opacity: _controller,
|
|
child: Icon(widget.icon, color: widget.color, size: 32),
|
|
)
|
|
: Icon(widget.icon, color: widget.color, size: 32),
|
|
);
|
|
}
|
|
}
|