import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/providers.dart'; import '../widgets/group_card.dart'; import 'homes_screen.dart'; import 'group_edit_screen.dart'; import 'schedules_screen.dart'; import 'stats_screen.dart'; import 'event_log_screen.dart'; import 'api_keys_screen.dart'; /// Основной экран пульта управления. /// Показывает группы текущего дома с управлением. class RemoteScreen extends ConsumerStatefulWidget { const RemoteScreen({super.key}); @override ConsumerState createState() => _RemoteScreenState(); } class _RemoteScreenState extends ConsumerState { bool _loading = true; @override void initState() { super.initState(); _bootstrap(); } Future _bootstrap() async { await ref.read(groupsProvider.notifier).initAndRefresh(); await ref.read(authInfoProvider.notifier).load(); if (mounted) setState(() => _loading = false); } @override Widget build(BuildContext context) { final groups = ref.watch(groupsProvider); final currentHome = ref.watch(currentHomeProvider); final authInfo = ref.watch(authInfoProvider); final isAdmin = authInfo?['is_admin'] == true; return Scaffold( appBar: AppBar( title: Text(currentHome?.name ?? 'IGNIS'), leading: IconButton( icon: const Icon(Icons.home), tooltip: 'Дома', onPressed: () => Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (_) => const HomesScreen()), ), ), actions: [ // Кнопка добавления группы IconButton( icon: const Icon(Icons.add_circle_outline), tooltip: 'Создать группу', onPressed: () => Navigator.of(context).push( MaterialPageRoute(builder: (_) => const GroupEditScreen()), ), ), // Меню PopupMenuButton( icon: const Icon(Icons.more_vert), onSelected: (value) { switch (value) { case 'schedules': Navigator.of(context).push( MaterialPageRoute(builder: (_) => const SchedulesScreen()), ); break; case 'stats': Navigator.of(context).push( MaterialPageRoute(builder: (_) => const StatsScreen()), ); break; case 'log': Navigator.of(context).push( MaterialPageRoute(builder: (_) => const EventLogScreen()), ); break; case 'api_keys': Navigator.of(context).push( MaterialPageRoute(builder: (_) => const ApiKeysScreen()), ); break; } }, itemBuilder: (context) => [ const PopupMenuItem( value: 'schedules', child: ListTile( leading: Icon(Icons.schedule), title: Text('Расписания'), contentPadding: EdgeInsets.zero, ), ), const PopupMenuItem( value: 'stats', child: ListTile( leading: Icon(Icons.bar_chart), title: Text('Статистика'), contentPadding: EdgeInsets.zero, ), ), const PopupMenuItem( value: 'log', child: ListTile( leading: Icon(Icons.list_alt), title: Text('Лог событий'), contentPadding: EdgeInsets.zero, ), ), if (isAdmin) const PopupMenuItem( value: 'api_keys', child: ListTile( leading: Icon(Icons.vpn_key), title: Text('API-ключи'), contentPadding: EdgeInsets.zero, ), ), ], ), ], ), body: _loading ? const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator(color: Colors.deepOrange), SizedBox(height: 20), Text( "Опрос ламп (это долго)...", style: TextStyle(color: Colors.white54), ), ], ), ) : groups.isEmpty ? Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.lightbulb_outline, size: 64, color: Colors.white24), const SizedBox(height: 16), const Text( 'Нет групп', style: TextStyle(color: Colors.white54, fontSize: 16), ), const SizedBox(height: 8), TextButton.icon( icon: const Icon(Icons.add), label: const Text('Создать группу'), onPressed: () => Navigator.of(context).push( MaterialPageRoute( builder: (_) => const GroupEditScreen()), ), ), ], ), ) : RefreshIndicator( color: Colors.deepOrange, onRefresh: () => ref.read(groupsProvider.notifier).refresh(), child: ListView.builder( padding: const EdgeInsets.only(top: 8, bottom: 80), itemCount: groups.length, itemBuilder: (context, index) { final g = Map.from(groups[index]); return Dismissible( key: Key(g['id'].toString()), direction: DismissDirection.endToStart, background: Container( alignment: Alignment.centerRight, padding: const EdgeInsets.only(right: 20), margin: const EdgeInsets.symmetric( horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.redAccent.withOpacity(0.3), borderRadius: BorderRadius.circular(16), ), child: const Icon(Icons.delete, color: Colors.redAccent), ), confirmDismiss: (_) => _confirmDeleteGroup(context, g), onDismissed: (_) => _deleteGroup(g['id'].toString()), child: GroupCard(group: g), ); }, ), ), ); } /// Подтверждение удаления группы свайпом Future _confirmDeleteGroup( BuildContext context, Map g) async { return await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('Удалить группу?'), content: Text('Удалить "${g['name']}"?'), actions: [ TextButton( onPressed: () => Navigator.of(ctx).pop(false), child: const Text('Отмена'), ), TextButton( onPressed: () => Navigator.of(ctx).pop(true), child: const Text('Удалить', style: TextStyle(color: Colors.redAccent)), ), ], ), ) ?? false; } Future _deleteGroup(String id) async { try { await ref.read(apiProvider).deleteGroup(id); await ref.read(groupsProvider.notifier).refresh(); } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Ошибка удаления: $e')), ); } } } }