Untitled
unknown
dart
9 months ago
9.3 kB
6
Indexable
class AlertListPage extends StatefulWidget { const AlertListPage({super.key}); @override State<AlertListPage> createState() => _AlertListPageState(); } class _AlertListPageState extends State<AlertListPage> with WidgetsBindingObserver { final int batchSize = 1; int loadedAlertsCount = 3; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); debugPrint('alerts view initilize'); } @override void dispose() { debugPrint('alerts view disposed'); WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); if (state == AppLifecycleState.detached) {} if (state == AppLifecycleState.hidden) {} } int compareAlertLevels(String level1, String level2) { final priorityOrder = { 'Emergency': 0, 'High': 1, 'Medium': 2, 'Low': 3, 'Resolved': 4 }; final priority1 = priorityOrder[level1] ?? 999; // Default to lowest priority final priority2 = priorityOrder[level2] ?? 999; // Default to lowest priority return priority1.compareTo(priority2); } double haversine(double lat1, double lon1, double lat2, double lon2) { // Convert latitude and longitude from degrees to radians lat1 = _degreesToRadians(lat1); lon1 = _degreesToRadians(lon1); lat2 = _degreesToRadians(lat2); lon2 = _degreesToRadians(lon2); // Haversine formula double dlon = lon2 - lon1; double dlat = lat2 - lat1; double a = math.pow(math.sin(dlat / 2), 2) + math.cos(lat1) * math.cos(lat2) * math.pow(math.sin(dlon / 2), 2); double c = 2 * math.asin(math.sqrt(a)); double r = 6371.0; // Radius of the Earth in kilometers // Calculate the result double distance = c * r; return distance; } double _degreesToRadians(double degrees) { return degrees * math.pi / 180; } List<Alert> sortAlertsBySeverityAndDistance( List<Alert> alerts, double userLatitude, double userLongitude) { alerts.sort((a, b) => compareAlertLevels(a.severity, b.severity)); // Now sort within each severity level by distance alerts.sort((a, b) { final distance1 = haversine( a.latitude ?? 0, a.longitude ?? 0, userLatitude, userLongitude); final distance2 = haversine( b.latitude ?? 0, b.longitude ?? 0, userLatitude, userLongitude); if (distance1 < 0.1 && distance2 >= 0.1) { return -1; // a is closer, should come first } else if (distance1 >= 0.1 && distance2 < 0.1) { return 1; // b is closer, should come first } else { return 0; // distances are either both close or both not close } }); return alerts; } @override Widget build(BuildContext context) { context.read<AlertCubit>().resumeSubscription(); bool? isAdmin = context.read<UserProvider>().user?.isAdmin; return Scaffold( appBar: AppBar( title: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const SizedBox( width: 230, child: Text( 'Detection Alerts', style: TextStyle( color: Colors.black54, fontFamily: Fonts.beautiful_people, fontWeight: FontWeight.w900, fontSize: 25, shadows: [ Shadow( offset: Offset(0, 3), blurRadius: 5, color: Colors.white12, ), ], ), textAlign: TextAlign.center, ), ), const SizedBox(width: 4), SizedBox( child: Image.asset( 'assets/images/projectLogo.png', fit: BoxFit.contain, width: 40, height: 40, ), ), ], ), ), ), body: BlocBuilder<AlertCubit, AlertState>( builder: (context, state) { if (state is AlertStateInitial) { return const Center(child: Text('Initializing...')); } else if (state is AlertStateLoading) { return const Center(child: CircularProgressIndicator()); } else if (state is AlertStateLoaded) { final alerts = state.alertsList; alerts.sort((a, b) => compareAlertLevels(a.severity, b.severity)); //TODO: add here the location of the user.. // + needs to fake locations!! and details... final user = context.read<UserProvider>().user!; List<Alert> userSortedAlerts = sortAlertsBySeverityAndDistance( state.alertsList, user.latitude ?? 23.09, user.longitude ?? 41.121); final displayedAlerts = isAdmin! ? alerts : userSortedAlerts .where((alert) => (alert.isConfirmed || alert.severity == 'Emergency') && alert.severity != 'Resolved') .toList(); final alertsToShow = displayedAlerts.take(loadedAlertsCount).toList(); if (alertsToShow.isEmpty) { return const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.info_outline, color: Colors.blueAccent, size: 50, ), SizedBox(height: 20), Text( 'No alerts found!', style: TextStyle( color: Colors.black54, fontFamily: 'Roboto', fontWeight: FontWeight.w600, fontSize: 20, shadows: [ Shadow( offset: Offset(0, 2), blurRadius: 4, color: Colors.black26, ), ], ), textAlign: TextAlign.center, ), SizedBox(height: 10), Text( 'You are all caught up', style: TextStyle( color: Colors.black45, fontFamily: 'Roboto', fontWeight: FontWeight.w400, fontSize: 16, ), textAlign: TextAlign.center, ), ], ), ); } return Column( children: [ Expanded( child: ListView.builder( itemCount: alertsToShow.length, itemBuilder: (context, index) { final alert = alertsToShow[index]; double lat1 = alert.latitude ?? 31.9803889; double lon1 = alert.longitude ?? 34.8158181; double lat2 = 31.9803889; double lon2 = 34.8130534; double distance = haversine(lat1, lon1, lat2, lon2); return AlertCard( alert: alert, isClose: distance > 1000, ); }, ), ), if (loadedAlertsCount < displayedAlerts.length) ...[ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: loadMoreAlerts, child: const Text('Load More'), ), const SizedBox(width: 16), ElevatedButton( onPressed: () => loadAllAlerts(displayedAlerts.length), child: const Text('Load All'), ), ], ) ] ], ); } else if (state is AlertStateError) { return Center( child: Text('Error: ${state.message}'), ); } else { return const Center( child: CircularProgressIndicator(), ); } }, ), ); } void loadMoreAlerts() { setState(() { loadedAlertsCount = loadedAlertsCount + batchSize; }); } void loadAllAlerts(int totalAlerts) { setState(() { loadedAlertsCount = totalAlerts; }); } }
Editor is loading...
Leave a Comment