> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/ihfaz297/MND/llms.txt
> Use this file to discover all available pages before exploring further.

# User Favorites

> Save and manage frequently used routes

The favorites feature allows authenticated users to save frequently used routes for quick access.

## FavoriteService

The `FavoriteService` handles all favorites-related API calls.

### Implementation

```dart theme={null}
class FavoriteService {
  final ApiService _api = ApiService();

  Future<List<Favorite>> getFavorites() async {
    final data = await _api.get('/favorites', requireAuth: true);
    return (data['favorites'] as List)
        .map((fav) => Favorite.fromJson(fav))
        .toList();
  }

  Future<Favorite> addFavorite(Favorite favorite) async {
    final data = await _api.post('/favorites', favorite.toJson(), requireAuth: true);
    return Favorite.fromJson(data['favorite']);
  }

  Future<void> deleteFavorite(String id) async {
    await _api.delete('/favorites/$id', requireAuth: true);
  }
}
```

Source: `lib/services/favorite_service.dart`

### Authentication Required

All favorite operations require user authentication (`requireAuth: true`).

## Favorite Model

Favorite data is represented by the `Favorite` model:

```dart theme={null}
class Favorite {
  final String id;
  final String label;
  final String from;
  final String to;
  final String defaultTime;

  Favorite({
    required this.id,
    required this.label,
    required this.from,
    required this.to,
    required this.defaultTime,
  });

  factory Favorite.fromJson(Map<String, dynamic> json) {
    return Favorite(
      id: json['id'],
      label: json['label'],
      from: json['from'],
      to: json['to'],
      defaultTime: json['defaultTime'],
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'label': label,
      'from': from,
      'to': to,
      'defaultTime': defaultTime,
    };
  }
}
```

Source: `lib/models/favorite.dart`

### Model Fields

* `id`: Server-assigned unique identifier
* `label`: User-friendly display name
* `from`: Origin stop name
* `to`: Destination stop name
* `defaultTime`: Preferred departure time

## Adding Favorites

Users can save routes from the route search results:

```dart theme={null}
Future<void> _addFavorite(RouteOption route) async {
  final auth = Provider.of<AuthProvider>(context, listen: false);
  
  // Require authentication
  if (!auth.isLoggedIn) {
    await Navigator.push(
      context,
      MaterialPageRoute(builder: (_) => const LoginScreen()),
    );
    if (!mounted || !auth.isLoggedIn) return;
  }

  try {
    final favorite = Favorite(
      id: 'temp', // Server will assign ID
      label: route.label,
      from: _nodes.firstWhere((n) => n.id == _fromNode).name,
      to: _nodes.firstWhere((n) => n.id == _toNode).name,
      defaultTime: _time,
    );
    
    await _favoriteService.addFavorite(favorite);

    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('Added "${route.label}" to favorites'),
        action: SnackBarAction(
          label: 'View',
          onPressed: () {
            // Navigate to favorites screen
          },
        ),
      ),
    );
  } catch (e) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Failed to add favorite: $e')),
    );
  }
}
```

Source: `lib/screens/home/home_screen.dart:85-125`

## FavoritesScreen

The `FavoritesScreen` displays all saved routes.

### Screen Structure

```dart theme={null}
class FavoritesScreen extends StatefulWidget {
  @override
  _FavoritesScreenState createState() => _FavoritesScreenState();
}

class _FavoritesScreenState extends State<FavoritesScreen> {
  final FavoriteService _favoriteService = FavoriteService();
  List<Favorite> _favorites = [];
  bool _loading = true;
  String? _error;

  @override
  void initState() {
    super.initState();
    _loadFavorites();
  }
}
```

Source: `lib/screens/favorites/favorites_screen.dart:8-23`

### Loading Favorites

```dart theme={null}
Future<void> _loadFavorites() async {
  final auth = Provider.of<AuthProvider>(context, listen: false);
  
  if (!auth.isLoggedIn) {
    setState(() {
      _loading = false;
      _error = 'Please login to see your favorites';
    });
    return;
  }

  setState(() {
    _loading = true;
    _error = null;
  });

  try {
    final favorites = await _favoriteService.getFavorites();
    setState(() {
      _favorites = favorites;
      _loading = false;
    });
  } catch (e) {
    setState(() {
      _error = e.toString();
      _loading = false;
    });
  }
}
```

Source: `lib/screens/favorites/favorites_screen.dart:25-53`

## Deleting Favorites

```dart theme={null}
Future<void> _deleteFavorite(Favorite favorite) async {
  final confirm = await showDialog<bool>(
    context: context,
    builder: (ctx) => AlertDialog(
      title: Text('Delete Favorite?'),
      content: Text('Remove "${favorite.label}" from favorites?'),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(ctx, false),
          child: Text('Cancel'),
        ),
        TextButton(
          onPressed: () => Navigator.pop(ctx, true),
          child: Text('Delete', style: TextStyle(color: Colors.red)),
        ),
      ],
    ),
  );

  if (confirm == true) {
    try {
      await _favoriteService.deleteFavorite(favorite.id);
      _loadFavorites();
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Favorite removed')),
      );
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Failed to delete: $e')),
      );
    }
  }
}
```

Source: `lib/screens/favorites/favorites_screen.dart:55-87`

## Favorites List Display

```dart theme={null}
Widget _buildList() {
  return RefreshIndicator(
    onRefresh: _loadFavorites,
    child: ListView.builder(
      padding: EdgeInsets.all(16),
      itemCount: _favorites.length,
      itemBuilder: (ctx, index) {
        final favorite = _favorites[index];
        return Card(
          margin: EdgeInsets.only(bottom: 12),
          child: ListTile(
            leading: CircleAvatar(
              backgroundColor: Theme.of(context).primaryColor,
              child: Icon(Icons.favorite, color: Colors.white),
            ),
            title: Text(
              favorite.label,
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            subtitle: Text('${favorite.from} → ${favorite.to}'),
            trailing: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  favorite.defaultTime,
                  style: TextStyle(color: Colors.grey),
                ),
                IconButton(
                  icon: Icon(Icons.delete_outline, color: Colors.red),
                  onPressed: () => _deleteFavorite(favorite),
                ),
              ],
            ),
            onTap: () {
              // Navigate to route search with pre-filled from/to
              Navigator.pushNamed(
                context,
                '/route-search',
                arguments: {
                  'from': favorite.from,
                  'to': favorite.to,
                },
              );
            },
          ),
        );
      },
    ),
  );
}
```

Source: `lib/screens/favorites/favorites_screen.dart:190-231`

## Authentication States

### Login Prompt

Show login prompt for unauthenticated users:

```dart theme={null}
Widget _buildLoginPrompt() {
  return Center(
    child: Padding(
      padding: EdgeInsets.all(24),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.favorite_border, size: 80, color: Colors.grey),
          SizedBox(height: 16),
          Text(
            'Login to Save Routes',
            style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
          ),
          SizedBox(height: 8),
          Text(
            'Save your frequent routes for quick access',
            textAlign: TextAlign.center,
            style: TextStyle(color: Colors.grey),
          ),
          SizedBox(height: 24),
          ElevatedButton(
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (_) => LoginScreen()),
              ).then((_) => _loadFavorites());
            },
            child: Text('Login'),
          ),
        ],
      ),
    ),
  );
}
```

Source: `lib/screens/favorites/favorites_screen.dart:115-148`

## Empty State

```dart theme={null}
Widget _buildEmpty() {
  return Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(Icons.favorite_border, size: 80, color: Colors.grey),
        SizedBox(height: 16),
        Text(
          'No Saved Routes',
          style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
        ),
        SizedBox(height: 8),
        Text(
          'Search for routes and tap the heart to save them',
          textAlign: TextAlign.center,
          style: TextStyle(color: Colors.grey),
        ),
      ],
    ),
  );
}
```

Source: `lib/screens/favorites/favorites_screen.dart:168-188`

## Example Usage

```dart theme={null}
class MyFavoritesWidget extends StatefulWidget {
  @override
  _MyFavoritesWidgetState createState() => _MyFavoritesWidgetState();
}

class _MyFavoritesWidgetState extends State<MyFavoritesWidget> {
  final FavoriteService _favoriteService = FavoriteService();
  List<Favorite> _favorites = [];
  
  Future<void> loadFavorites() async {
    try {
      final favorites = await _favoriteService.getFavorites();
      setState(() {
        _favorites = favorites;
      });
    } catch (e) {
      print('Error: $e');
    }
  }
  
  Future<void> addFavorite() async {
    final favorite = Favorite(
      id: '',
      label: 'Campus to Ambarkhana',
      from: 'Campus',
      to: 'Ambarkhana',
      defaultTime: '08:30',
    );
    
    await _favoriteService.addFavorite(favorite);
    await loadFavorites();
  }
  
  Future<void> deleteFavorite(String id) async {
    await _favoriteService.deleteFavorite(id);
    await loadFavorites();
  }
}
```

## Error Handling

```dart theme={null}
try {
  final favorites = await _favoriteService.getFavorites();
  // Success
} catch (e) {
  if (e.toString().contains('Session expired')) {
    // Redirect to login
  } else {
    // Show error message
    setState(() {
      _error = e.toString();
    });
  }
}
```

## Pull to Refresh

Users can refresh favorites by pulling down:

```dart theme={null}
RefreshIndicator(
  onRefresh: _loadFavorites,
  child: ListView.builder(
    // ... favorites list
  ),
)
```

Source: `lib/screens/favorites/favorites_screen.dart:191-193`

## UI Features

* Authentication-gated access
* Pull-to-refresh functionality
* Delete confirmation dialog
* Empty and login states
* Error handling with retry
* Visual feedback (SnackBars)

## Next Steps

* [Route Planning](/mobile/route-planning)
* [State Management](/mobile/state-management)
* [Services Documentation](/mobile/services)
