/opt/canhelp/apps/mobile/lib/screens/favorites
Edit: /opt/canhelp/apps/mobile/lib/screens/favorites/favorites_screen.dart (6621B)
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import '../../providers/auth_provider.dart';
import '../../providers/favorites_provider.dart';
import '../../providers/locale_provider.dart';
import '../../theme/app_theme.dart';
class FavoritesScreen extends StatefulWidget {
const FavoritesScreen({super.key});
@override
State
createState() => _FavoritesScreenState();
}
class _FavoritesScreenState extends State {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read().load();
});
}
@override
Widget build(BuildContext context) {
final favorites = context.watch();
final locale = context.watch();
final auth = context.watch();
final theme = Theme.of(context);
if (!auth.isAuthenticated) {
return Scaffold(
appBar: AppBar(
backgroundColor: AppTheme.background,
elevation: 0,
scrolledUnderElevation: 0,
foregroundColor: AppTheme.textPrimary,
leading: IconButton(
icon: const Icon(
Icons.arrow_back_ios_new_rounded,
size: 20,
color: AppTheme.textPrimary,
),
onPressed: () => context.canPop() ? context.pop() : context.go('/'),
),
title: Text(
locale.t('nav.favorites'),
style: const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 18,
color: AppTheme.textPrimary,
),
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.favorite_outline, size: 64, color: Colors.grey),
const SizedBox(height: 16),
Text(
locale.t('auth.loginRequired'),
style: theme.textTheme.bodyLarge,
),
const SizedBox(height: 16),
FilledButton(
onPressed: () => context.push('/login'),
child: Text(locale.t('auth.login')),
),
],
),
),
);
}
return Scaffold(
appBar: AppBar(
backgroundColor: AppTheme.background,
elevation: 0,
scrolledUnderElevation: 0,
foregroundColor: AppTheme.textPrimary,
leading: IconButton(
icon: const Icon(
Icons.arrow_back_ios_new_rounded,
size: 20,
color: AppTheme.textPrimary,
),
onPressed: () => context.canPop() ? context.pop() : context.go('/'),
),
title: Text(
locale.t('nav.favorites'),
style: const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 18,
color: AppTheme.textPrimary,
),
),
),
body: RefreshIndicator(
onRefresh: () => favorites.load(),
child: favorites.isLoading && favorites.favorites.isEmpty
? const Center(child: CircularProgressIndicator())
: favorites.favorites.isEmpty
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.favorite_outline,
size: 64,
color: theme.colorScheme.onSurfaceVariant.withValues(
alpha: 0.4,
),
),
const SizedBox(height: 16),
Text(
locale.t('favorites.empty'),
style: theme.textTheme.bodyLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
OutlinedButton(
onPressed: () => context.push('/specialists'),
child: Text(locale.t('favorites.browse')),
),
],
),
)
: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: favorites.favorites.length,
itemBuilder: (_, i) {
final user = favorites.favorites[i];
return Card(
margin: const EdgeInsets.only(bottom: 12),
child: ListTile(
contentPadding: const EdgeInsets.all(12),
leading: CircleAvatar(
radius: 24,
backgroundImage: user.avatar != null
? NetworkImage(user.avatar!)
: null,
backgroundColor: AppTheme.primaryContainer,
child: user.avatar == null
? Text(
user.fullName.isNotEmpty
? user.fullName[0].toUpperCase()
: '?',
style: const TextStyle(color: AppTheme.primary),
)
: null,
),
title: Text(
user.fullName,
style: theme.textTheme.titleSmall,
),
subtitle: Row(
children: [
const Icon(
Icons.star,
size: 14,
color: AppTheme.amber,
),
const SizedBox(width: 2),
Text(
user.rating.toStringAsFixed(1),
style: theme.textTheme.labelSmall,
),
],
),
trailing: IconButton(
icon: const Icon(
Icons.favorite,
color: AppTheme.danger,
),
onPressed: () => favorites.toggle(user.id, user),
),
onTap: () => context.push('/specialists/${user.id}'),
),
);
},
),
),
);
}
}