diff --git a/modules/legacy/modules/control_panel/lib/src/features/notifications/presentation/notifications_screen.dart b/modules/legacy/modules/control_panel/lib/src/features/notifications/presentation/notifications_screen.dart index 30f21b47..c4337d90 100644 --- a/modules/legacy/modules/control_panel/lib/src/features/notifications/presentation/notifications_screen.dart +++ b/modules/legacy/modules/control_panel/lib/src/features/notifications/presentation/notifications_screen.dart @@ -5,6 +5,7 @@ import 'package:control_panel/src/features/notifications/presentation/widgets/no import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:legacy_theme/legacy_theme.dart'; +import 'package:legacy_ui/legacy_ui.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:sf_shared/sf_shared.dart'; @@ -19,13 +20,14 @@ class NotificationsScreen extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final primaryColor = context.sfColors.legacyPrimary; final selectedType = ref.watch(notificationsFilterProvider); - final feedAsync = ref.watch(notificationsFeedProvider); - ref.listen(notificationsFeedProvider, (prev, next) async { - if (next.hasError && prev?.hasError != true) { - await showErrorDialog(context, I18n.alertsLoadError); - } - }); + if (selectedType != null) { + return _FilteredNotificationsScreen( + type: selectedType, + onBack: () => + ref.read(notificationsFilterProvider.notifier).select(null), + ); + } return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, @@ -53,81 +55,176 @@ class NotificationsScreen extends ConsumerWidget { ), ), ), - body: Column( - children: [ - _FilterChips( - selectedType: selectedType, - onSelected: ref.read(notificationsFilterProvider.notifier).select, - ), - Expanded( - child: feedAsync.when( - loading: () => const Center(child: CircularProgressIndicator()), - error: (_, __) => Center( - child: Text(context.translate(I18n.alertsLoadError)), + body: SingleChildScrollView( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 14, big: 12), + vertical: SizeUtils.getByScreen(small: 12, big: 10), + ), + child: Column( + children: _notificationTypes.map((entry) { + return Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 8, big: 7), ), - data: (feed) => _NotificationsList( - notifications: feed.notifications, - isLoadingMore: feed.isLoadingMore, + child: SectionButton( + onPressed: () => ref + .read(notificationsFilterProvider.notifier) + .select(entry.type), + icon: Icon( + entry.icon, + size: SizeUtils.getByScreen(small: 34, big: 38), + color: primaryColor, + ), + iconPadding: SizeUtils.getByScreen(small: 14, big: 12), + body: Text( + context.translate(entry.labelKey), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 16, big: 17), + fontWeight: FontWeight.w500, + ), + ), ), - ), - ), - ], + ); + }).toList(), + ), ), ); } } -class _FilterChips extends StatelessWidget { - final String? selectedType; - final ValueChanged onSelected; +class _NotificationType { + final String type; + final String labelKey; + final IconData icon; - const _FilterChips({required this.selectedType, required this.onSelected}); + const _NotificationType({ + required this.type, + required this.labelKey, + required this.icon, + }); +} + +const _notificationTypes = [ + _NotificationType( + type: 'sos', + labelKey: I18n.alertTypeSos, + icon: Icons.sos, + ), + _NotificationType( + type: 'falldown', + labelKey: I18n.alertTypeFalldown, + icon: Icons.personal_injury, + ), + _NotificationType( + type: 'lowBattery', + labelKey: I18n.alertTypeLowBattery, + icon: Icons.battery_alert, + ), + _NotificationType( + type: 'disconnect', + labelKey: I18n.alertTypeDisconnect, + icon: Icons.link_off, + ), + _NotificationType( + type: 'geofenceIn', + labelKey: I18n.alertTypeGeofenceIn, + icon: Icons.location_on, + ), + _NotificationType( + type: 'geofenceOut', + labelKey: I18n.alertTypeGeofenceOut, + icon: Icons.location_off, + ), + _NotificationType( + type: 'braceletRemoved', + labelKey: I18n.alertTypeBraceletRemoved, + icon: Icons.watch_off, + ), + _NotificationType( + type: 'abnormalHeartRate', + labelKey: I18n.alertTypeAbnormalHeartRate, + icon: Icons.heart_broken, + ), + _NotificationType( + type: 'standstill', + labelKey: I18n.alertTypeStandstill, + icon: Icons.accessibility_new, + ), + _NotificationType( + type: 'movement', + labelKey: I18n.alertTypeMovement, + icon: Icons.directions_walk, + ), +]; + +class _FilteredNotificationsScreen extends ConsumerWidget { + final String type; + final VoidCallback onBack; + + const _FilteredNotificationsScreen({ + required this.type, + required this.onBack, + }); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final primaryColor = context.sfColors.legacyPrimary; + final feedAsync = ref.watch(notificationsFeedProvider); - final filters = [ - (null, context.translate(I18n.alertsFilterAll)), - ('sos', 'SOS'), - ('falldown', context.translate(I18n.alertTypeFalldown)), - ('lowBattery', context.translate(I18n.alertTypeLowBattery)), - ('disconnect', context.translate(I18n.alertTypeDisconnect)), - ('geofenceIn', context.translate(I18n.alertTypeGeofenceIn)), - ('geofenceOut', context.translate(I18n.alertTypeGeofenceOut)), - ]; + final typeEntry = _notificationTypes + .where((e) => e.type == type) + .firstOrNull; + final title = typeEntry != null + ? context.translate(typeEntry.labelKey) + : type; - return SizedBox( - height: SizeUtils.getByScreen(small: 44, big: 40), - child: ListView.separated( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.symmetric( - horizontal: SizeUtils.getByScreen(small: 16, big: 14), - vertical: SizeUtils.getByScreen(small: 4, big: 3), - ), - itemCount: filters.length, - separatorBuilder: (_, __) => SizedBox( - width: SizeUtils.getByScreen(small: 6, big: 5), - ), - itemBuilder: (context, index) { - final (type, label) = filters[index]; - final isSelected = type == selectedType; + ref.listen(notificationsFeedProvider, (prev, next) async { + if (next.hasError && prev?.hasError != true) { + await showErrorDialog(context, I18n.alertsLoadError); + } + }); - return ChoiceChip( - label: Text(label), - selected: isSelected, - selectedColor: primaryColor, - labelStyle: TextStyle( - fontSize: SizeUtils.getByScreen(small: 12, big: 11), - fontWeight: FontWeight.w600, - color: isSelected ? Colors.white : primaryColor, + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, _) { + if (!didPop) onBack(); + }, + child: Scaffold( + backgroundColor: Theme.of(context).colorScheme.surface, + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.surface, + surfaceTintColor: Colors.transparent, + elevation: 0, + centerTitle: true, + automaticallyImplyLeading: false, + leading: IconButton( + onPressed: onBack, + icon: Icon( + Icons.adaptive.arrow_back, + color: primaryColor, + size: SizeUtils.getByScreen(small: 32, big: 28), ), - side: BorderSide(color: primaryColor), - onSelected: (_) => onSelected(type), - visualDensity: VisualDensity.compact, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - ); - }, + ), + title: Text( + title.toUpperCase(), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + fontWeight: FontWeight.w500, + letterSpacing: 0, + color: primaryColor, + ), + ), + ), + body: feedAsync.when( + loading: () => const Center(child: CircularProgressIndicator()), + error: (_, __) => Center( + child: Text(context.translate(I18n.alertsLoadError)), + ), + data: (feed) => _NotificationsList( + notifications: feed.notifications, + isLoadingMore: feed.isLoadingMore, + ), + ), ), ); }