import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../bloc/book_bloc.dart'; import '../bloc/navigation_bloc.dart'; import '../models/models.dart'; import '../widgets/book_card.dart'; import '../theme/app_spacing.dart'; class LibraryScreen extends StatefulWidget { const LibraryScreen({super.key}); @override State createState() => _LibraryScreenState(); } class _LibraryScreenState extends State { String _search = ''; int _tabIndex = 0; @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final textTheme = Theme.of(context).textTheme; return BlocBuilder( builder: (context, state) { final filtered = state.books.where((b) { final q = _search.toLowerCase(); return b.title.toLowerCase().contains(q) || b.author.toLowerCase().contains(q); }).toList(); return SafeArea( child: Column( children: [ // Header Padding( padding: const EdgeInsets.fromLTRB( AppSpacing.lg, AppSpacing.md, AppSpacing.lg, 0, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Книжная полка', style: textTheme.displayMedium), IconButton( icon: const Icon(Icons.notifications_outlined), onPressed: () {}, ), ], ), ), // Search Padding( padding: const EdgeInsets.fromLTRB( AppSpacing.lg, AppSpacing.md, AppSpacing.lg, 0, ), child: TextField( onChanged: (v) => setState(() => _search = v), decoration: InputDecoration( hintText: 'Поиск книг...', prefixIcon: Icon(Icons.search, color: colorScheme.primary), ), ), ), // Tabs Padding( padding: const EdgeInsets.fromLTRB( AppSpacing.lg, AppSpacing.md, AppSpacing.lg, 0, ), child: Row( children: [ _tab('Все книги', 0), const SizedBox(width: AppSpacing.sm), _tab('Категории', 1), ], ), ), const SizedBox(height: AppSpacing.md), // Grid Expanded( child: _tabIndex == 0 ? GridView.builder( padding: const EdgeInsets.fromLTRB( AppSpacing.lg, 0, AppSpacing.lg, 100, ), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.55, crossAxisSpacing: AppSpacing.md, mainAxisSpacing: AppSpacing.md, ), itemCount: filtered.length, itemBuilder: (context, i) => BookCard( book: filtered[i], onTap: () { context.read().add( NavigateTo( AppScreen.details, selectedBook: filtered[i], ), ); }, ), ) : ListView( padding: const EdgeInsets.fromLTRB( AppSpacing.lg, 0, AppSpacing.lg, 100, ), children: [ for (final genre in filtered.map((b) => b.genre).toSet()) Container( margin: const EdgeInsets.only( bottom: AppSpacing.sm, ), decoration: BoxDecoration( color: colorScheme.surface, border: Border.all(color: colorScheme.outline), borderRadius: BorderRadius.circular( AppSpacing.radiusMedium, ), ), child: ListTile( title: Text( genre, style: textTheme.titleMedium, ), trailing: Text( '${filtered.where((b) => b.genre == genre).length}', style: textTheme.bodyMedium?.copyWith( color: colorScheme.onSurface.withValues( alpha: 0.6, ), ), ), ), ), ], ), ), ], ), ); }, ); } Widget _tab(String label, int index) { final selected = _tabIndex == index; final colorScheme = Theme.of(context).colorScheme; final textTheme = Theme.of(context).textTheme; final disableAnimations = MediaQuery.of(context).disableAnimations; return GestureDetector( onTap: () => setState(() => _tabIndex = index), child: AnimatedContainer( duration: disableAnimations ? Duration.zero : const Duration(milliseconds: 200), padding: const EdgeInsets.symmetric( horizontal: AppSpacing.md, vertical: AppSpacing.sm, ), decoration: BoxDecoration( color: selected ? colorScheme.primary : colorScheme.surfaceContainerHighest, border: Border.all( color: selected ? colorScheme.primary : colorScheme.outline, ), borderRadius: BorderRadius.circular(AppSpacing.radiusPill), ), child: Text( label, style: textTheme.labelMedium?.copyWith( color: selected ? Colors.white : colorScheme.onSurface.withValues(alpha: 0.7), ), ), ), ); } }