import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../home/home_provider.dart'; import '../scan/dish_result_screen.dart'; import 'recognition_service.dart'; /// Full-screen page showing all of today's unlinked dish recognition jobs. class RecognitionHistoryScreen extends ConsumerWidget { const RecognitionHistoryScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final jobsState = ref.watch(todayJobsProvider); return Scaffold( appBar: AppBar( title: const Text('История распознавания'), ), body: jobsState.when( loading: () => const Center(child: CircularProgressIndicator()), error: (recognitionError, _) => Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text('Не удалось загрузить историю'), const SizedBox(height: 12), FilledButton( onPressed: () => ref.invalidate(todayJobsProvider), child: const Text('Повторить'), ), ], ), ), data: (jobs) { if (jobs.isEmpty) { return const Center( child: Text('Нет распознаваний за сегодня'), ); } return ListView.separated( padding: const EdgeInsets.all(16), itemCount: jobs.length, separatorBuilder: (_, __) => const SizedBox(height: 8), itemBuilder: (context, index) => _HistoryJobTile(job: jobs[index]), ); }, ), ); } } class _HistoryJobTile extends ConsumerWidget { final DishJobSummary job; const _HistoryJobTile({required this.job}); @override Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); final isDone = job.status == 'done'; final isFailed = job.status == 'failed'; final isProcessing = job.status == 'processing' || job.status == 'pending'; final IconData statusIcon; final Color statusColor; if (isDone) { statusIcon = Icons.check_circle_outline; statusColor = Colors.green; } else if (isFailed) { statusIcon = Icons.error_outline; statusColor = theme.colorScheme.error; } else { statusIcon = Icons.hourglass_top_outlined; statusColor = theme.colorScheme.primary; } final dishName = job.result?.candidates.isNotEmpty == true ? job.result!.best.dishName : null; final String titleText; if (isDone) { titleText = dishName ?? 'Блюдо распознано'; } else if (isProcessing) { titleText = 'Распознаётся…'; } else { titleText = 'Ошибка распознавания'; } final contextParts = [ if (job.targetMealType != null) job.targetMealType!, if (job.targetDate != null) job.targetDate!, ]; return Card( child: ListTile( leading: Icon(statusIcon, color: statusColor), title: Text(titleText, style: theme.textTheme.bodyMedium), subtitle: contextParts.isNotEmpty ? Text( contextParts.join(' · '), style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onSurfaceVariant, ), ) : null, onTap: isDone && job.result != null ? () { showModalBottomSheet( context: context, isScrollControlled: true, useSafeArea: true, builder: (sheetContext) => DishResultSheet( dish: job.result!, preselectedMealType: job.targetMealType, jobId: job.id, onAdded: () => Navigator.pop(sheetContext), ), ); } : null, ), ); } }