Skip to content

Commit

Permalink
feat: add pagination logic support using bloc pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
brunogabriel committed Oct 18, 2024
1 parent 509b6bb commit 6e94e2c
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 0 deletions.
6 changes: 6 additions & 0 deletions pokedex/lib/common/events/events_transformations.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import 'package:bloc_concurrency/bloc_concurrency.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:stream_transform/stream_transform.dart';

EventTransformer<E> throttleDroppable<E>(Duration duration) =>
(events, mapper) => droppable<E>().call(events.throttle(duration), mapper);
31 changes: 31 additions & 0 deletions pokedex/lib/design/widgets/pokemon_information.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:flutter/material.dart';

class PokemonInformation extends StatelessWidget {
const PokemonInformation({super.key});

@override
Widget build(BuildContext context) {
// TODO: Create spacing
return const Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('# 6'),
SizedBox(height: 10.0),
Text('Charmander'),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text('Fire')],
)
],
),
);
}
}
55 changes: 55 additions & 0 deletions pokedex/lib/features/pokemon_list/bloc/pokemon_list_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import 'package:pokedex/common/events/events_transformations.dart';
import './../domain/boundary/pokemon_list_repository.dart';
import './../domain/model/pokemon.dart';
part 'pokemon_list_event.dart';
part 'pokemon_list_state.dart';

@injectable
class PokemonListBloc extends Bloc<PokemonListEvent, PokemonListState> {
PokemonListBloc(this._repository) : super(const PokemonListState()) {
on<PokemonListEventRequest>(
_onRequestPokemons,
transformer: throttleDroppable(
const Duration(milliseconds: 100),
),
);
}

final PokemonListRepository _repository;

Future<void> _onRequestPokemons(
PokemonListEventRequest event,
Emitter<PokemonListState> emit,
) async {
if (state.pageStatus == PageStatus.finished &&
state.pageStatus != PageStatus.failure &&
state.pageStatus != PageStatus.loading) {
return;
}

emit(state.copyWith(pageStatus: PageStatus.loading));

try {
final response = await _repository.getPokemons(
limit: event.limit,
offset: state.result.length,
);
emit(
state.copyWith(
result: response.pokemons,
pageStatus:
response.hasNext ? PageStatus.success : PageStatus.finished,
),
);
} catch (error) {
emit(
state.copyWith(
pageStatus: PageStatus.failure,
),
);
}
}
}
19 changes: 19 additions & 0 deletions pokedex/lib/features/pokemon_list/bloc/pokemon_list_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
part of 'pokemon_list_bloc.dart';

sealed class PokemonListEvent extends Equatable {
const PokemonListEvent();

@override
List<Object?> get props => [];
}

class PokemonListEventRequest extends PokemonListEvent {
const PokemonListEventRequest({
this.limit = 100,
});

final int limit;

@override
List<Object> get props => [limit];
}
30 changes: 30 additions & 0 deletions pokedex/lib/features/pokemon_list/bloc/pokemon_list_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
part of 'pokemon_list_bloc.dart';

enum PageStatus { initial, loading, success, failure, finished }

class PokemonListState extends Equatable {
const PokemonListState({
this.pageStatus = PageStatus.initial,
this.result = const <Pokemon>[],
});

final PageStatus pageStatus;
final List<Pokemon> result;

PokemonListState copyWith({
PageStatus? pageStatus,
List<Pokemon>? result,
}) =>
PokemonListState(
pageStatus: pageStatus ?? this.pageStatus,
result: this.result + (result ?? []),
);

bool get firstPage => result.isEmpty;

@override
List<Object> get props => [
pageStatus,
result,
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:flutter/material.dart';
import 'package:pokedex/design/widgets/pokemon_information.dart';

class PokemonCard extends StatelessWidget {
const PokemonCard({super.key});

@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
// TODO: add tap action
},
child: const SizedBox(
height: 140.0,
child: Stack(
children: [PokemonInformation()],
),
),
);
}
}

0 comments on commit 6e94e2c

Please sign in to comment.