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

# Movies Providers

> Riverpod providers that manage paginated movie lists for now playing, popular, upcoming, top rated, and Mexican movies.

The movies providers expose paginated `List<Movie>` state using Riverpod's `NotifierProvider`. Every list-based provider shares the same `MoviesNotifier` class and differs only in which repository method it calls.

## Provider overview

| Provider                   | Type               | State         | Repository method                        |
| -------------------------- | ------------------ | ------------- | ---------------------------------------- |
| `nowPlayingMoviesProvider` | `NotifierProvider` | `List<Movie>` | `getNowPlaying`                          |
| `popularMoviesProvider`    | `NotifierProvider` | `List<Movie>` | `getPopular`                             |
| `upcomingMoviesProvider`   | `NotifierProvider` | `List<Movie>` | `getUpcoming`                            |
| `topratedMoviesProvider`   | `NotifierProvider` | `List<Movie>` | `getTopRated`                            |
| `mexicanMoviesProvider`    | `NotifierProvider` | `List<Movie>` | `getMexicanMovies`                       |
| `movieSlideShowProvider`   | `Provider`         | `List<Movie>` | Derived — first 6 now-playing movies     |
| `intialLoadingProvider`    | `Provider`         | `bool`        | Derived — `true` while any list is empty |

***

## List providers

Each of the five list providers is declared with `NotifierProvider` and created with a `MoviesNotifier` that captures its specific fetch callback.

```dart movies_providers.dart theme={null}
// Type alias for any paginated movie fetch function
typedef MovieCallback = Future<List<Movie>> Function({int page});

final nowPlayingMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier((ref) => ref.watch(movieRepositoryProvider).getNowPlaying),
);

final popularMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier((ref) => ref.watch(movieRepositoryProvider).getPopular),
);

final upcomingMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier((ref) => ref.watch(movieRepositoryProvider).getUpcoming),
);

final topratedMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier((ref) => ref.watch(movieRepositoryProvider).getTopRated),
);

final mexicanMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier(
    (ref) => ref.watch(movieRepositoryProvider).getMexicanMovies,
  ),
);
```

***

## Derived providers

### `movieSlideShowProvider`

A read-only `Provider<List<Movie>>` that derives its value from `nowPlayingMoviesProvider`. It returns an empty list while now-playing movies are loading, otherwise it returns the first six entries for use in a hero slideshow.

```dart movie_slideshow_provider.dart theme={null}
final movieSlideShowProvider = Provider<List<Movie>>((ref) {
  final nowPlayingMovies = ref.watch(nowPlayingMoviesProvider);
  if (nowPlayingMovies.isEmpty) return [];
  return nowPlayingMovies.sublist(0, 6);
});
```

### `intialLoadingProvider`

A read-only `Provider<bool>` that returns `true` as long as any of the five movie lists is still empty. Widgets use this to show a full-screen loading indicator before the first page of data arrives.

```dart initialLoading_provider.dart theme={null}
final intialLoadingProvider = Provider<bool>((ref) {
  final step1 = ref.watch(nowPlayingMoviesProvider).isEmpty;
  final step2 = ref.watch(upcomingMoviesProvider).isEmpty;
  final step3 = ref.watch(popularMoviesProvider).isEmpty;
  final step4 = ref.watch(topratedMoviesProvider).isEmpty;
  final step5 = ref.watch(mexicanMoviesProvider).isEmpty;

  if (step1 || step2 || step3 || step4 || step5) return true;
  return false;
});
```

***

## `MoviesNotifier`

`MoviesNotifier` extends Riverpod's `Notifier<List<Movie>>`. It accumulates pages of movies into its state list and guards against concurrent fetches with the `isLoading` flag.

```dart movies_providers.dart theme={null}
class MoviesNotifier extends Notifier<List<Movie>> {
  final MovieCallback Function(Ref ref) _callbackBuilder;
  late final MovieCallback fetchMoreMovies;

  MoviesNotifier(this._callbackBuilder);

  int currentPage = 0;
  bool isLoading = false;

  @override
  List<Movie> build() {
    fetchMoreMovies = _callbackBuilder(ref);
    return [];
  }

  Future<void> loadNextPage() async {
    if (isLoading) return;
    isLoading = true;

    currentPage++;
    final movies = await fetchMoreMovies(page: currentPage);

    state = [...state, ...movies];

    isLoading = false;
  }
}
```

### Fields

<ParamField path="currentPage" type="int" default="0">
  Tracks the last page number that was successfully fetched. Incremented before each API call inside `loadNextPage()`.
</ParamField>

<ParamField path="isLoading" type="bool" default="false">
  Guard flag that prevents duplicate in-flight requests. Set to `true` at the start of `loadNextPage()` and back to `false` once the fetch completes.
</ParamField>

### Methods

#### `build()`

Called once by Riverpod when the notifier is first read. Resolves the `fetchMoreMovies` callback from the `_callbackBuilder` closure (which has access to `ref`) and returns an empty list as the initial state.

#### `loadNextPage()`

Appends the next page of movies to `state`. If a fetch is already in progress (`isLoading == true`), the call returns immediately. Otherwise it increments `currentPage`, awaits the API call, and spreads the results onto the existing state list.

***

## Usage in a widget

Call `loadNextPage()` once on first build (or when the user scrolls to the bottom) by reading the notifier from `ref`.

```dart home_screen.dart theme={null}
// _HomeView is a ConsumerStatefulWidget defined inside home_screen.dart
class _HomeViewState extends ConsumerState<_HomeView> {
  @override
  void initState() {
    super.initState();
    // Load the first page of each category
    ref.read(nowPlayingMoviesProvider.notifier).loadNextPage();
    ref.read(popularMoviesProvider.notifier).loadNextPage();
    ref.read(topratedMoviesProvider.notifier).loadNextPage();
    ref.read(upcomingMoviesProvider.notifier).loadNextPage();
    ref.read(mexicanMoviesProvider.notifier).loadNextPage();
  }

  @override
  Widget build(BuildContext context) {
    // Show a loader until all lists have at least one page
    final initialLoading = ref.watch(intialLoadingProvider);
    if (initialLoading) return const FullscreenLoader();

    final nowPlayingMovies = ref.watch(nowPlayingMoviesProvider);
    final slideShowMovies  = ref.watch(movieSlideShowProvider);

    return CustomScrollView(
      slivers: [
        const SliverAppBar(floating: true, title: CustomAppbar()),
        SliverList(
          delegate: SliverChildBuilderDelegate(
            (context, index) {
              if (index > 0) return null;
              return Column(
                children: [
                  MovieSlideshow(movies: slideShowMovies),
                  MovieHorizontalListview(
                    movies: nowPlayingMovies,
                    title: 'En cines',
                    subTitle: 'Lunes 27 de Octubre',
                    loadNextPage: () =>
                        ref.read(nowPlayingMoviesProvider.notifier).loadNextPage(),
                  ),
                ],
              );
            },
            childCount: 1,
          ),
        ),
      ],
    );
  }
}
```

<Note>
  All providers are exported from `lib/presentation/providers/providers.dart`. Import that barrel file instead of individual provider files.
</Note>
