import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:flutter_animate/flutter_animate.dart'; import '../../providers/ideas_provider.dart'; import '../../providers/workspace_provider.dart'; import '../../core/theme/app_theme.dart'; import '../../widgets/loading_indicator.dart'; import '../../widgets/error_display.dart'; import '../../widgets/empty_state.dart'; import '../../widgets/funnel_status_badge.dart'; import '../../models/idea.dart'; import '../../core/constants/app_constants.dart'; import '../ideas/widgets/funnel_kanban.dart'; class DashboardScreen extends ConsumerWidget { const DashboardScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final ideasState = ref.watch(ideasProvider); final wsState = ref.watch(workspaceProvider); final ideasNotifier = ref.read(ideasProvider.notifier); return Scaffold( appBar: AppBar( title: Text(wsState.selectedWorkspace?.name ?? 'VoIdea'), actions: [ IconButton( icon: Icon(ideasState.viewMode == 'list' ? Icons.view_kanban : Icons.view_list), onPressed: () { ideasNotifier.setViewMode( ideasState.viewMode == 'list' ? 'kanban' : 'list'); }, ), IconButton( icon: const Icon(Icons.add), onPressed: () => context.push('/ideas/create'), ), ], ), body: RefreshIndicator( onRefresh: () => ideasNotifier.loadIdeas(), child: _buildBody(context, ref, ideasState), ), ); } Widget _buildBody(BuildContext context, WidgetRef ref, IdeasState state) { if (state.isLoading && state.ideas.isEmpty) { return const ShimmerList(); } if (state.error != null && state.ideas.isEmpty) { return ErrorDisplay( message: state.error!, onRetry: () => ref.read(ideasProvider.notifier).loadIdeas(), ); } if (state.ideas.isEmpty) { return EmptyState( icon: Icons.lightbulb_outline, title: 'Пока нет идей', subtitle: 'Создайте первую идею', actionLabel: 'Создать идею', onAction: () => context.push('/ideas/create'), ); } if (state.viewMode == 'kanban') { return IdeaFunnelKanban(ideas: state.ideas); } return ListView.builder( padding: const EdgeInsets.all(16), itemCount: state.ideas.length, itemBuilder: (context, index) { final idea = state.ideas[index]; return _IdeaCard(idea: idea).animate().fadeIn( duration: 300.ms, delay: (index * 50).ms, ); }, ); } } class _IdeaCard extends StatelessWidget { final Idea idea; const _IdeaCard({required this.idea}); @override Widget build(BuildContext context) { return Card( margin: const EdgeInsets.only(bottom: 12), child: InkWell( borderRadius: BorderRadius.circular(12), onTap: () => context.push('/ideas/${idea.id}'), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( idea.title, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.w600, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), if (idea.funnelStatus != null) FunnelStatusBadge(status: idea.funnelStatus), ], ), const SizedBox(height: 8), if (idea.description.isNotEmpty) Text( idea.description, maxLines: 2, overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: VoIdeaColors.muted, ), ), const SizedBox(height: 12), Row( children: [ Icon(Icons.thumb_up_outlined, size: 14, color: VoIdeaColors.muted), const SizedBox(width: 4), Text(idea.upvotes.toString(), style: const TextStyle( color: VoIdeaColors.muted, fontSize: 12)), const SizedBox(width: 16), Icon(Icons.thumb_down_outlined, size: 14, color: VoIdeaColors.muted), const SizedBox(width: 4), Text(idea.downvotes.toString(), style: const TextStyle( color: VoIdeaColors.muted, fontSize: 12)), const SizedBox(width: 16), Icon(Icons.comment_outlined, size: 14, color: VoIdeaColors.muted), const SizedBox(width: 4), Text(idea.commentCount.toString(), style: const TextStyle( color: VoIdeaColors.muted, fontSize: 12)), ], ), ], ), ), ), ); } }