import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'dart:developer' as dev; import '../../core/app_colors.dart'; import '../../di/service_locator.dart'; import '../components/custom_app_bar.dart'; import '../components/gradient_button.dart'; import '../event/news_event.dart'; import '../state/news_state.dart'; import '../viewmodel/news_bloc.dart'; import 'news_detail_screen.dart'; class NewsScreen extends StatelessWidget { const NewsScreen({super.key}); @override Widget build(BuildContext context) { return BlocProvider( create: (context) { return getIt()..add(const NewsFetchRequested()); }, child: const NewsView(), ); } } class NewsView extends StatelessWidget { const NewsView({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: const BoxDecoration(gradient: AppColors.phoneScreenBg), child: SafeArea( child: Column( children: [ const SizedBox(height: 16), const Padding( padding: EdgeInsets.symmetric(horizontal: 20), child: CustomAppBar(title: 'Новости'), ), const SizedBox(height: 32), Expanded( child: BlocBuilder( builder: (context, state) { if (state.status == NewsStatus.initial || state.status == NewsStatus.loading) { return const Center( child: CircularProgressIndicator(color: Colors.white), ); } if (state.status == NewsStatus.failure) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'Ошибка загрузки новостей', style: TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 16), Padding( padding: const EdgeInsets.symmetric(horizontal: 40), child: Text( state.errorMessage ?? '', style: TextStyle( color: Colors.white.withOpacity(0.6), fontSize: 14, ), textAlign: TextAlign.center, ), ), const SizedBox(height: 24), ElevatedButton( onPressed: () { context.read().add(const NewsFetchRequested()); }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.smsDigit, ), child: const Text('Повторить'), ), ], ), ); } if (state.news.isEmpty) { return const _EmptyState(); } return ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 20), itemCount: state.news.length, itemBuilder: (context, index) { return _NewsCard(news: state.news[index]); }, ); }, ), ), const SizedBox(height: 20), ], ), ), ), ); } } class _EmptyState extends StatelessWidget { const _EmptyState(); @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset( 'assets/news_empty.png', width: 280, height: 280, fit: BoxFit.contain, errorBuilder: (context, error, stackTrace) { return const Icon( Icons.newspaper_outlined, size: 120, color: Colors.white38, ); }, ), const SizedBox(height: 32), const Padding( padding: EdgeInsets.symmetric(horizontal: 40), child: Text( 'Следите за нашими последними новостями и акциями! Сейчас их нет, но скоро они появятся.', textAlign: TextAlign.center, style: TextStyle( color: Colors.white70, fontSize: 16, height: 1.5, ), ), ), ], ); } } class _NewsCard extends StatelessWidget { final dynamic news; const _NewsCard({required this.news}); @override Widget build(BuildContext context) { final date = _formatDate(news.publishedAt); return Container( margin: const EdgeInsets.only(bottom: 16), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: const Color(0xFF0A0F2E).withOpacity(0.7), borderRadius: BorderRadius.circular(16), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( date, style: const TextStyle( color: AppColors.white70, fontSize: 12, ), ), const SizedBox(height: 8), Text( news.title, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Container( width: double.infinity, height: 80, decoration: BoxDecoration( image: DecorationImage( image: AssetImage('assets/news_def.png'), fit: BoxFit.cover, ), borderRadius: BorderRadius.circular(8), ), ), const SizedBox(height: 16), Text( news.previewText, style: const TextStyle( color: Colors.white70, fontSize: 14, height: 1.4, ), ), const SizedBox(height: 16), Align( alignment: Alignment.centerRight, child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 150), child: GradientButton( text: 'Подробнее', onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => NewsDetailScreen( newsId: news.id, title: news.title, ), ), ); }, showArrows: true, fontSize: 14, height: 40, width: double.infinity, ), ), ), ], ), ); } String _formatDate(DateTime date) { final now = DateTime.now(); final difference = now.difference(date); if (difference.inDays == 0) { return 'Сегодня, ${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}'; } else if (difference.inDays == 1) { return 'Вчера, ${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}'; } else { return '${date.day.toString().padLeft(2, '0')}.${date.month.toString().padLeft(2, '0')}.${date.year}, ${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}'; } } }