import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../domain/entities/alarm_state.dart'; import '../blocs/alarm/alarm_bloc.dart'; import '../blocs/alarm/alarm_event.dart'; import '../blocs/alarm/alarm_state.dart'; class AlarmPanel extends StatelessWidget { final int maxDisplayed; const AlarmPanel({super.key, this.maxDisplayed = 5}); @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { final alarms = state.activeAlarms.take(maxDisplayed).toList(); final hasMore = state.activeAlarms.length > maxDisplayed; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( 'ACTIVE ALARMS', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(width: 8), if (state.blockingAlarmCount > 0) Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: Colors.red, borderRadius: BorderRadius.circular(12), ), child: Text( '${state.blockingAlarmCount}', style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold, ), ), ), const Spacer(), if (state.isLoading) const SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ) else IconButton( icon: const Icon(Icons.refresh, size: 20), onPressed: () => context.read().add(const RefreshAlarms()), tooltip: 'Refresh alarms', padding: EdgeInsets.zero, constraints: const BoxConstraints(), ), ], ), const SizedBox(height: 8), if (alarms.isEmpty) Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Icon( Icons.check_circle, color: Colors.green.shade600, ), const SizedBox(width: 8), Text( 'No active alarms', style: Theme.of(context).textTheme.bodyMedium, ), ], ), ) else Container( decoration: BoxDecoration( border: Border.all( color: Colors.red.shade200, width: 1, ), borderRadius: BorderRadius.circular(8), ), child: Column( children: [ ...alarms.asMap().entries.map((entry) { final index = entry.key; final alarm = entry.value; return _AlarmTile( alarm: alarm, isLast: index == alarms.length - 1 && !hasMore, ); }), if (hasMore) Container( padding: const EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( color: Theme.of(context) .colorScheme .surfaceContainerHighest, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(7), bottomRight: Radius.circular(7), ), ), child: Center( child: Text( '+${state.activeAlarms.length - maxDisplayed} more alarms', style: Theme.of(context).textTheme.bodySmall, ), ), ), ], ), ), if (state.error != null) Padding( padding: const EdgeInsets.only(top: 4), child: Text( state.error!, style: TextStyle( color: Theme.of(context).colorScheme.error, fontSize: 12, ), ), ), if (state.lastSync != null) Padding( padding: const EdgeInsets.only(top: 4), child: Text( 'Last sync: ${_formatTime(state.lastSync!)}', style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context) .colorScheme .onSurface .withValues(alpha: 0.6), ), ), ), ], ); }, ); } String _formatTime(DateTime time) { return '${time.hour.toString().padLeft(2, '0')}:' '${time.minute.toString().padLeft(2, '0')}:' '${time.second.toString().padLeft(2, '0')}'; } } class _AlarmTile extends StatelessWidget { final AlarmState alarm; final bool isLast; const _AlarmTile({ required this.alarm, required this.isLast, }); @override Widget build(BuildContext context) { final isBlocking = alarm.blocksMonitor; return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: isBlocking ? Colors.red.shade50 : null, border: isLast ? null : Border( bottom: BorderSide( color: Colors.red.shade200, width: 1, ), ), ), child: Row( children: [ Icon( isBlocking ? Icons.warning : Icons.info_outline, color: isBlocking ? Colors.red : Colors.orange, size: 20, ), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( alarm.eventName.isNotEmpty ? alarm.eventName : 'Event ${alarm.eventId}', style: TextStyle( fontWeight: isBlocking ? FontWeight.bold : FontWeight.normal, ), ), if (alarm.foreignKey > 0) Text( 'Camera/Contact: ${alarm.foreignKey}', style: Theme.of(context).textTheme.bodySmall, ), ], ), ), Text( _formatTime(alarm.startedAt), style: Theme.of(context).textTheme.bodySmall, ), if (alarm.associatedMonitor != null) ...[ const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: Theme.of(context).colorScheme.primaryContainer, borderRadius: BorderRadius.circular(4), ), child: Text( 'M${alarm.associatedMonitor}', style: TextStyle( fontSize: 10, color: Theme.of(context).colorScheme.onPrimaryContainer, ), ), ), ], ], ), ); } String _formatTime(DateTime time) { return '${time.hour.toString().padLeft(2, '0')}:' '${time.minute.toString().padLeft(2, '0')}:' '${time.second.toString().padLeft(2, '0')}'; } }