Skip to content

Commit

Permalink
passing model from view with values from API in popular and top_rated…
Browse files Browse the repository at this point in the history
…, applying filters and search movies
  • Loading branch information
felipecastrosales committed Sep 19, 2021
1 parent 8d3a787 commit c3dd624
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 93 deletions.
98 changes: 47 additions & 51 deletions lib/application/ui/widgets/movie_card.dart
Original file line number Diff line number Diff line change
@@ -1,72 +1,68 @@
import 'package:app_filmes/application/ui/filmes_app_icons_icons.dart';
import 'package:app_filmes/models/movie_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:intl/intl.dart';

class MovieCard extends StatelessWidget {
const MovieCard({Key? key}) : super(key: key);
final MovieModel movie;
final dateFormat = DateFormat('dd/MM/y');
MovieCard({Key? key, required this.movie}) : super(key: key);

@override
Widget build(BuildContext context) {
return SizedBox(
height: 280,
width: 158,
return Container(
padding: const EdgeInsets.all(10),
height: 305,
width: 170,
child: Stack(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Material(
elevation: 2,
borderRadius: BorderRadius.circular(20),
child: ClipRRect(
clipBehavior: Clip.antiAlias,
borderRadius: BorderRadius.circular(20),
child: Image.network(
'https://m.media-amazon.com/images/M/MV5BNzMyMTM1MjQxNF5BMl5BanBnXkFtZTgwMjY4NTE5NjE@._V1_.jpg',
width: 148,
height: 184,
fit: BoxFit.cover,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Material(
elevation: 2,
borderRadius: BorderRadius.circular(15),
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
clipBehavior: Clip.antiAlias,
child: Image.network(
movie.posterPath,
height: 190,
width: 165,
fit: BoxFit.cover,
),
),
const SizedBox(height: 20),
const Text(
'Cristiano Ronaldo',
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
const Text(
'2015',
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(
fontSize: 11,
color: Colors.grey,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 20),
Text(
movie.title,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600),
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
Text(
dateFormat.format(DateTime.parse(movie.releaseDate)),
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w300,
color: Colors.grey,
),
],
),
),
],
),
Positioned(
bottom: 80,
right: -8,
bottom: 65,
right: -4,
child: Material(
elevation: 5,
shape: const CircleBorder(),
shape: CircleBorder(),
clipBehavior: Clip.antiAlias,
child: SizedBox(
height: 30,
height: 40,
child: IconButton(
iconSize: 13,
icon: const Icon(
FilmesAppIcons.heart,
iconSize: 18,
icon: Icon(
FilmesAppIcons.heartEmpty,
color: Colors.grey,
),
onPressed: () {},
Expand All @@ -78,4 +74,4 @@ class MovieCard extends StatelessWidget {
),
);
}
}
}
3 changes: 1 addition & 2 deletions lib/models/movie_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class MovieModel {
final List<int> genres;
final bool favorite;


Map<String, dynamic> toMap() {
return {
'id': id,
Expand All @@ -34,7 +33,7 @@ class MovieModel {
id: map['id'] ?? 0,
title: map['title'] ?? '',
releaseDate: map['release_date'] ?? '',
posterPath: map['poster_path'] ?? '',
posterPath: 'https://image.tmdb.org/t/p/w200/${map['poster_path']}',
genres: List<int>.from(map['genre_ids'] ?? const []),
favorite: map['favorite'] ?? false,
);
Expand Down
64 changes: 59 additions & 5 deletions lib/modules/movies/movies_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import 'package:app_filmes/services/genres/genres_service.dart';
class MoviesController extends GetxController with MessagesMixin {
final GenresService _genresService;
final MoviesService _moviesService;

final _message = Rxn<MessageModel>();
final genres = <GenreModel>[].obs;

final popularMovies = <MovieModel>[].obs;
final topRatedMovies = <MovieModel>[].obs;

final _popularMoviesOriginal = <MovieModel>[];
final _topRatedMoviesOriginal = <MovieModel>[];
var _popularMoviesOriginal = <MovieModel>[];
var _topRatedMoviesOriginal = <MovieModel>[];
final genreSelected = Rxn<GenreModel>();

MoviesController({
required GenresService genresService,
Expand All @@ -32,24 +32,78 @@ class MoviesController extends GetxController with MessagesMixin {
}

@override
void onReady() async {
Future<void> onReady() async {
super.onReady();
try {
final genresData = await _genresService.getGenres();
genres.assignAll(genresData);

final popularMoviesData = await _moviesService.getPopularMovies();
final topRatedMoviesData = await _moviesService.getTopRatedMovies();

popularMovies.assignAll(popularMoviesData);
_popularMoviesOriginal = popularMoviesData;
topRatedMovies.assignAll(topRatedMoviesData);
_topRatedMoviesOriginal = topRatedMoviesData;
} catch (e, s) {
print(e);
print(s);
_message(
MessageModel.error(
title: 'Erro',
message: 'Erro ao carregar dados da página',
message: 'Erro ao carregar os dados da Página',
),
);
}
}

void filterByName(String title) {
if (title.isNotEmpty) {
var newPopularMovies = _popularMoviesOriginal.where(
(movie) {
return movie.title.toLowerCase().contains(
title.toLowerCase(),
);
},
);
var newTopRatedMovies = _topRatedMoviesOriginal.where(
(movie) {
return movie.title.toLowerCase().contains(
title.toLowerCase(),
);
},
);
popularMovies.assignAll(newPopularMovies);
topRatedMovies.assignAll(newTopRatedMovies);
} else {
popularMovies.assignAll(_popularMoviesOriginal);
topRatedMovies.assignAll(_topRatedMoviesOriginal);
}
}

void filterMoviesByGenre(GenreModel? genreModel) {
if (genreModel?.id == genreSelected.value?.id) {
genreModel = null;
}

genreSelected.value = genreModel;

if (genreModel != null) {
var newPopularMovies = _popularMoviesOriginal.where(
(movie) {
return movie.genres.contains(genreModel?.id);
},
);
var newTopRatedMovies = _topRatedMoviesOriginal.where(
(movie) {
return movie.genres.contains(genreModel?.id);
},
);
popularMovies.assignAll(newPopularMovies);
topRatedMovies.assignAll(newTopRatedMovies);
} else {
popularMovies.assignAll(_popularMoviesOriginal);
topRatedMovies.assignAll(_topRatedMoviesOriginal);
}
}
}
26 changes: 15 additions & 11 deletions lib/modules/movies/movies_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,31 @@ import 'package:flutter/material.dart';

import 'package:get/get.dart';

import 'movies_controller.dart';
import 'widgets/movies_filters.dart';
import 'widgets/movies_group.dart';
import 'widgets/movies_header.dart';
class MoviesPage extends GetView<MoviesController> {
const MoviesPage({Key? key}) : super(key: key);

class MoviesPage extends StatelessWidget {

const MoviesPage({ Key? key }) : super(key: key);

@override
Widget build(BuildContext context) {
return SizedBox(
width: Get.width,
height: Get.height,
child: ListView(
children: const [
MoviesHeader(),
MoviesFilters(),
MoviesGroup(title: 'Mais Populares'),
MoviesGroup(title: 'Top Filmes'),
children: [
const MoviesHeader(),
const MoviesFilters(),
MoviesGroup(
title: 'Mais populares',
movies: controller.popularMovies,
),
MoviesGroup(
title: 'Top Filmes',
movies: controller.topRatedMovies,
),
],
),
);
}
}
}
8 changes: 4 additions & 4 deletions lib/modules/movies/widgets/movies_filters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ class MoviesFilters extends GetView<MoviesController> {
return Row(
children: controller.genres
.map(
(g) => FilterTag(
model: g,
onPressed: () {},
selected: false,
(genre) => FilterTag(
model: genre,
onPressed: () => controller.filterMoviesByGenre(genre),
selected: controller.genreSelected.value?.id == genre.id,
),
)
.toList(),
Expand Down
31 changes: 22 additions & 9 deletions lib/modules/movies/widgets/movies_group.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import 'package:flutter/material.dart';

import 'package:get/get.dart';

import 'package:app_filmes/application/ui/widgets/movie_card.dart';
import 'package:app_filmes/models/movie_model.dart';

class MoviesGroup extends StatelessWidget {
const MoviesGroup({Key? key, required this.title}) : super(key: key);
const MoviesGroup({
Key? key,
required this.title,
required this.movies,
}) : super(key: key);

final String title;
final List<MovieModel> movies;

@override
Widget build(BuildContext context) {
Expand All @@ -23,14 +32,18 @@ class MoviesGroup extends StatelessWidget {
),
SizedBox(
height: 280,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (context, index) {
return const MovieCard();
}
),
child: Obx(() {
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: movies.length,
itemBuilder: (context, index) {
return MovieCard(
movie: movies[index],
);
},
);
}),
),
],
),
Expand Down
5 changes: 4 additions & 1 deletion lib/modules/movies/widgets/movies_header.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import 'package:flutter/material.dart';

import 'package:get/get.dart';

class MoviesHeader extends StatelessWidget {
import 'package:app_filmes/modules/movies/movies_controller.dart';

class MoviesHeader extends GetView<MoviesController> {
const MoviesHeader({Key? key}) : super(key: key);

@override
Expand All @@ -24,6 +26,7 @@ class MoviesHeader extends StatelessWidget {
width: Get.width * .9,
padding: const EdgeInsets.only(bottom: 20),
child: TextField(
onChanged: (value) => controller.filterByName(value),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
Expand Down
Loading

0 comments on commit c3dd624

Please sign in to comment.