import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/providers/insight_provider.dart'; class InsightsScreen extends ConsumerStatefulWidget { const InsightsScreen({super.key}); @override ConsumerState createState() => _InsightsScreenState(); } class _InsightsScreenState extends ConsumerState { @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { ref.read(insightNotifierProvider.notifier).generateInsight(); }); } void _refresh() { ref .read(insightNotifierProvider.notifier) .generateInsight(forceRefresh: true); } @override Widget build(BuildContext context) { final insightAsync = ref.watch(insightNotifierProvider); return Scaffold( appBar: AppBar( title: const Text('Insights'), centerTitle: false, actions: [ IconButton( icon: const Icon(Icons.refresh), tooltip: 'Refresh', onPressed: insightAsync is AsyncLoading ? null : _refresh, ), ], ), body: insightAsync.when( loading: () => const _LoadingView(), error: (e, _) => _ErrorView(onRetry: _refresh), data: (text) => text == null ? const _EmptyView() : _InsightCard(text: text), ), ); } } class _LoadingView extends StatelessWidget { const _LoadingView(); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const CircularProgressIndicator(), const SizedBox(height: 16), Text( 'Analysing your week…', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Theme.of(context).colorScheme.outline, ), ), ], ), ); } } class _EmptyView extends StatelessWidget { const _EmptyView(); @override Widget build(BuildContext context) { return Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.auto_awesome_outlined, size: 48, color: Theme.of(context).colorScheme.outlineVariant, ), const SizedBox(height: 16), Text( 'Not enough data yet', style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 8), Text( 'Log a few more entries and check back soon.', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Theme.of(context).colorScheme.outline, ), textAlign: TextAlign.center, ), ], ), ), ); } } class _ErrorView extends StatelessWidget { const _ErrorView({required this.onRetry}); final VoidCallback onRetry; @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.error_outline, size: 48, color: Theme.of(context).colorScheme.error, ), const SizedBox(height: 16), Text( 'Something went wrong', style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 16), FilledButton.tonal( onPressed: onRetry, child: const Text('Try again'), ), ], ), ); } } class _InsightCard extends StatelessWidget { const _InsightCard({required this.text}); final String text; @override Widget build(BuildContext context) { return ListView( padding: const EdgeInsets.all(16), children: [ Card( child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( Icons.auto_awesome, size: 18, color: Theme.of(context).colorScheme.primary, ), const SizedBox(width: 8), Text( 'This week', style: Theme.of(context).textTheme.labelLarge?.copyWith( color: Theme.of(context).colorScheme.primary, ), ), ], ), const SizedBox(height: 12), Text( text, style: Theme.of(context).textTheme.bodyMedium?.copyWith( height: 1.5, ), ), ], ), ), ), const SizedBox(height: 8), Text( 'Generated on-device. Your data never leaves your phone.', style: Theme.of(context).textTheme.labelSmall?.copyWith( color: Theme.of(context).colorScheme.outlineVariant, ), textAlign: TextAlign.center, ), ], ); } }