import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:file_picker/file_picker.dart'; import 'package:trainhub_flutter/core/theme/app_colors.dart'; import 'package:trainhub_flutter/core/constants/ui_constants.dart'; import 'package:trainhub_flutter/presentation/analysis/analysis_controller.dart'; import 'package:trainhub_flutter/presentation/analysis/widgets/analysis_session_list.dart'; import 'package:trainhub_flutter/presentation/analysis/widgets/analysis_viewer.dart'; import 'package:trainhub_flutter/presentation/common/widgets/app_empty_state.dart'; @RoutePage() class AnalysisPage extends ConsumerWidget { const AnalysisPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final state = ref.watch(analysisControllerProvider); final controller = ref.read(analysisControllerProvider.notifier); return state.when( data: (data) { if (data.activeSession != null) { return AnalysisViewer( session: data.activeSession!, annotations: data.annotations, onClose: () { ref.invalidate(analysisControllerProvider); }, ); } return Column( children: [ // Header toolbar Container( padding: const EdgeInsets.symmetric( horizontal: UIConstants.spacing24, vertical: UIConstants.spacing16, ), decoration: const BoxDecoration( color: AppColors.surfaceContainer, border: Border( bottom: BorderSide(color: AppColors.border), ), ), child: Row( children: [ Container( width: 36, height: 36, decoration: BoxDecoration( color: AppColors.purpleMuted, borderRadius: BorderRadius.circular(8), ), child: const Icon( Icons.video_library, color: AppColors.purple, size: 20, ), ), const SizedBox(width: UIConstants.spacing12), const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Video Analysis', style: TextStyle( color: AppColors.textPrimary, fontSize: 18, fontWeight: FontWeight.w600, ), ), Text( 'Analyze and annotate your training videos', style: TextStyle( color: AppColors.textMuted, fontSize: 12, ), ), ], ), const Spacer(), FilledButton.icon( onPressed: () => _showAddSessionDialog(context, controller), icon: const Icon(Icons.add, size: 18), label: const Text('New Session'), ), ], ), ), // Session list Expanded( child: data.sessions.isEmpty ? AppEmptyState( icon: Icons.video_library_outlined, title: 'No analysis sessions yet', subtitle: 'Create a session to analyze your training videos', actionLabel: 'Create Session', onAction: () => _showAddSessionDialog(context, controller), ) : AnalysisSessionList( sessions: data.sessions, onSessionSelected: (session) => controller.loadSession(session.id), onDeleteSession: (session) => controller.deleteSession(session.id), ), ), ], ); }, error: (e, s) => Center( child: Text( 'Error: $e', style: const TextStyle(color: AppColors.destructive), ), ), loading: () => const Center(child: CircularProgressIndicator()), ); } void _showAddSessionDialog( BuildContext context, AnalysisController controller, ) { final textController = TextEditingController(); String? selectedVideoPath; showDialog( context: context, builder: (context) => StatefulBuilder( builder: (context, setState) => AlertDialog( title: const Text('New Analysis Session'), content: SizedBox( width: UIConstants.dialogWidth, child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: textController, decoration: const InputDecoration( labelText: 'Session Name', hintText: 'e.g. Squat Form Check', ), autofocus: true, ), const SizedBox(height: UIConstants.spacing16), Container( padding: const EdgeInsets.all(UIConstants.spacing12), decoration: BoxDecoration( color: AppColors.surface, borderRadius: UIConstants.smallCardBorderRadius, border: Border.all(color: AppColors.border), ), child: Row( children: [ Icon( selectedVideoPath != null ? Icons.videocam : Icons.videocam_off_outlined, color: selectedVideoPath != null ? AppColors.success : AppColors.textMuted, size: 20, ), const SizedBox(width: UIConstants.spacing12), Expanded( child: Text( selectedVideoPath != null ? selectedVideoPath! .split(RegExp(r'[\\/]')) .last : 'No video selected', style: TextStyle( color: selectedVideoPath != null ? AppColors.textPrimary : AppColors.textMuted, fontSize: 13, ), overflow: TextOverflow.ellipsis, ), ), const SizedBox(width: UIConstants.spacing8), OutlinedButton.icon( onPressed: () async { final result = await FilePicker.platform.pickFiles( type: FileType.video, allowMultiple: false, ); if (result != null && result.files.single.path != null) { setState(() { selectedVideoPath = result.files.single.path; }); } }, icon: const Icon(Icons.folder_open, size: 16), label: const Text('Browse'), ), ], ), ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Cancel'), ), FilledButton( onPressed: () { if (textController.text.isNotEmpty && selectedVideoPath != null) { controller.createSession( textController.text, selectedVideoPath!, ); Navigator.pop(context); } }, child: const Text('Create'), ), ], ), ), ); } }