Skip to content

Commit

Permalink
feat: using api (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
omartinma authored Apr 18, 2024
1 parent a50af7e commit 94114dc
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 101 deletions.
2 changes: 1 addition & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_basics/sample_app/sample_app_screen.dart';
import 'package:flutter_basics/sample_app/sample_app.dart';

void main() {
runApp(const MainApp());
Expand Down
33 changes: 21 additions & 12 deletions lib/sample_app/bloc/sample_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'dart:async';
import 'dart:convert';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_basics/sample_app/sample_app_screen.dart';
import 'package:flutter_basics/sample_app/sample_app.dart';
import 'package:http/http.dart';
import 'package:meta/meta.dart';

part 'sample_event.dart';
Expand All @@ -14,17 +16,24 @@ class SampleBloc extends Bloc<SampleEvent, SampleState> {
}

FutureOr<void> _fetchData(FetchData event, Emitter<SampleState> emit) async {
await Future<void>.delayed(const Duration(seconds: 1));
final list = <MyItem>[];
for (var i = 0; i < 5; i++) {
list.add(
MyItem(
name: 'Name $i',
description: 'Description $i',
url: 'https://picsum.photos/id/$i/200',
),
);
final httpClient = Client();
const baseUrl = 'rickandmortyapi.com';
const endpoint = 'api/character';
final url = Uri.https(baseUrl, endpoint);
final response = await httpClient.get(url);

if (response.statusCode != 200) {}
emit(SampleError());
try {
final charactersJson = jsonDecode(response.body) as Map<String, dynamic>;
final characters = (charactersJson['results'] as List)
.map(
(dynamic e) => Character.fromJson(e as Map<String, dynamic>),
)
.toList();
emit(SampleSucces(items: characters));
} catch (e) {
emit(SampleError());
}
emit(SampleSucces(items: list));
}
}
4 changes: 3 additions & 1 deletion lib/sample_app/bloc/sample_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ final class SampleInitial extends SampleState {}

final class SampleLoading extends SampleState {}

final class SampleError extends SampleState {}

final class SampleSucces extends SampleState {
SampleSucces({required this.items});

final List<MyItem> items;
final List<Character> items;
}
52 changes: 52 additions & 0 deletions lib/sample_app/models/character.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import 'package:json_annotation/json_annotation.dart';

part 'character.g.dart';

@JsonSerializable()

/// [Character] is a character entity fetched from rick and morty api
class Character {
/// Default constructor
const Character({
required this.id,
required this.name,
required this.image,
required this.species,
required this.status,
});

/// Json deserialize
factory Character.fromJson(Map<String, dynamic> json) =>
_$CharacterFromJson(json);

/// Id of the character
final int id;

/// Name of the character
final String name;

/// Image of the character
final String image;

/// Species of the character
final String species;

/// Status of the character
final Status status;
}

/// Status of the character
enum Status {
@JsonValue('Alive')

/// alive
alive,
@JsonValue('Dead')

/// dead
dead,
@JsonValue('unknown')

/// unknown
unknown,
}
58 changes: 58 additions & 0 deletions lib/sample_app/models/character.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lib/sample_app/models/models.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'character.dart';
3 changes: 3 additions & 0 deletions lib/sample_app/sample_app.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'bloc/sample_bloc.dart';
export 'models/models.dart';
export 'view/view.dart';
87 changes: 0 additions & 87 deletions lib/sample_app/sample_app_screen.dart

This file was deleted.

72 changes: 72 additions & 0 deletions lib/sample_app/view/character_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import 'package:flutter/material.dart';
import 'package:flutter_basics/sample_app/sample_app.dart';

class CharacterList extends StatelessWidget {
const CharacterList({required this.characters, super.key});

final List<Character> characters;

@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemBuilder: (context, index) => CharacterItemView(
character: characters[index],
),
itemCount: characters.length,
);
}
}

class CharacterItemView extends StatelessWidget {
@visibleForTesting
const CharacterItemView({
required this.character,
super.key,
});

final Character character;

@override
Widget build(BuildContext context) {
return InkWell(
child: Stack(
fit: StackFit.expand,
children: [
Positioned.fill(
child: Hero(
tag: 'image_hero_${character.name}',
child: FittedBox(
fit: BoxFit.fill,
child: Image.network(character.image),
),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
color: Colors.white70,
padding: const EdgeInsets.all(5),
child: Center(
child: Text(
character.name,
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
);
}
}
37 changes: 37 additions & 0 deletions lib/sample_app/view/sample_app_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:flutter_basics/sample_app/bloc/sample_bloc.dart';
import 'package:flutter_basics/sample_app/view/character_list.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

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

@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => SampleBloc()..add(const FetchData()),
child: const SampleAppScreenView(),
);
}
}

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

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('My first app'),
),
body: BlocBuilder<SampleBloc, SampleState>(
builder: (context, state) {
if (state is SampleSucces) {
return CharacterList(characters: state.items);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
1 change: 1 addition & 0 deletions lib/sample_app/view/view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'sample_app_screen.dart';

0 comments on commit 94114dc

Please sign in to comment.