Untitled

 avatar
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