Skip to content

Commit 6dbc468

Browse files
main screen ui and bloc
1 parent 09a340b commit 6dbc468

21 files changed

+1053
-104
lines changed

lib/core/network/api_constance.dart

+2
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ class ApiConstance {
55
static const apiKey = 'api_key=70c3fb246cbcac46e1e3ba2510c34732';
66
static const topRatedMoviePath = '$baseUrl/movie/top_rated?$apiKey';
77
static const popularMoviePath = '$baseUrl/movie/popular?$apiKey';
8+
static const baseImageUrl = 'https://image.tmdb.org/t/p/w500';
9+
static String imageUrl(String path) => '$baseImageUrl$path';
810
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import 'package:flutter_movie_app/movies/data/data%20source/remote/remote_date_source.dart';
2+
import 'package:flutter_movie_app/movies/data/repo/movie_repo.dart';
3+
import 'package:flutter_movie_app/movies/domain/repo/base_movies_repo.dart';
4+
import 'package:flutter_movie_app/movies/domain/usecases/now_playing.dart';
5+
import 'package:flutter_movie_app/movies/domain/usecases/popular.dart';
6+
import 'package:flutter_movie_app/movies/domain/usecases/top_rated.dart';
7+
import 'package:flutter_movie_app/movies/presentation/controller/movies_bloc.dart';
8+
import 'package:get_it/get_it.dart';
9+
10+
final sl = GetIt.instance;
11+
12+
class ServicesLocator {
13+
void init() {
14+
///Data source
15+
sl.registerLazySingleton<BaseMovieRemoteDataSource>(
16+
() => MovieRemoteDataSource());
17+
18+
/// usecase
19+
sl.registerLazySingleton(() => PopularUsecase(sl()));
20+
sl.registerLazySingleton(() => NowPlayingUsecase(sl()));
21+
sl.registerLazySingleton(() => TopRatedUsecase(sl()));
22+
23+
/// reposiory
24+
25+
sl.registerLazySingleton<BaseMoviesRepository>(
26+
() => MoviesRepository(sl()));
27+
28+
/// bloc
29+
30+
sl.registerFactory(() => MoviesBloc(sl(), sl(), sl()));
31+
}
32+
}

lib/core/utils/dummy.dart

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import '../../movies/domain/entities/movie.dart';
2+
3+
List<Movie> moviesList = [
4+
const Movie(
5+
backdropPath: "/nmGWzTLMXy9x7mKd8NKPLmHtWGa.jpg",
6+
genreIds: [
7+
14,
8+
28,
9+
12,
10+
],
11+
id: 453395,
12+
overView:
13+
"Doctor Strange, with the help of mystical allies both old and new, traverses the mind-bending and dangerous alternate realities of the Multiverse to confront a mysterious new adversary.",
14+
releaseDate: "2022-05-04",
15+
title: "Movie Title",
16+
voteAverage: 5.0,
17+
),
18+
const Movie(
19+
backdropPath: "/nmGWzTLMXy9x7mKd8NKPLmHtWGa.jpg",
20+
genreIds: [
21+
14,
22+
28,
23+
12,
24+
],
25+
id: 453395,
26+
overView:
27+
"Doctor Strange, with the help of mystical allies both old and new, traverses the mind-bending and dangerous alternate realities of the Multiverse to confront a mysterious new adversary.",
28+
releaseDate: "2022-05-04",
29+
title: "Movie Title",
30+
voteAverage: 5.0,
31+
),
32+
const Movie(
33+
backdropPath: "/nmGWzTLMXy9x7mKd8NKPLmHtWGa.jpg",
34+
genreIds: [
35+
14,
36+
28,
37+
12,
38+
],
39+
id: 453395,
40+
overView:
41+
"Doctor Strange, with the help of mystical allies both old and new, traverses the mind-bending and dangerous alternate realities of the Multiverse to confront a mysterious new adversary.",
42+
releaseDate: "2022-05-04",
43+
title: "Movie Title",
44+
voteAverage: 5.0,
45+
),
46+
const Movie(
47+
backdropPath: "/nmGWzTLMXy9x7mKd8NKPLmHtWGa.jpg",
48+
genreIds: [
49+
14,
50+
28,
51+
12,
52+
],
53+
id: 453395,
54+
overView:
55+
"Doctor Strange, with the help of mystical allies both old and new, traverses the mind-bending and dangerous alternate realities of the Multiverse to confront a mysterious new adversary.",
56+
releaseDate: "2022-05-04",
57+
title: "Movie Title",
58+
voteAverage: 5.0,
59+
),
60+
const Movie(
61+
backdropPath: "/nmGWzTLMXy9x7mKd8NKPLmHtWGa.jpg",
62+
genreIds: [
63+
14,
64+
28,
65+
12,
66+
],
67+
id: 453395,
68+
overView:
69+
"Doctor Strange, with the help of mystical allies both old and new, traverses the mind-bending and dangerous alternate realities of the Multiverse to confront a mysterious new adversary.",
70+
releaseDate: "2022-05-04",
71+
title: "Movie Title",
72+
voteAverage: 5.0,
73+
),
74+
const Movie(
75+
backdropPath: "/nmGWzTLMXy9x7mKd8NKPLmHtWGa.jpg",
76+
genreIds: [
77+
14,
78+
28,
79+
12,
80+
],
81+
id: 453395,
82+
overView:
83+
"Doctor Strange, with the help of mystical allies both old and new, traverses the mind-bending and dangerous alternate realities of the Multiverse to confront a mysterious new adversary.",
84+
releaseDate: "2022-05-04",
85+
title: "Movie Title",
86+
voteAverage: 5.0,
87+
),
88+
];

lib/core/utils/enums.dart

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
enum RequestState { loading, loaded, error }

lib/main.dart

+9-97
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,27 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter_movie_app/core/services/services_locator.dart';
3+
4+
import 'movies/presentation/screens/movies_screen.dart';
25

36
void main() {
7+
WidgetsFlutterBinding.ensureInitialized();
8+
ServicesLocator().init();
9+
410
runApp(const MyApp());
511
}
612

713
class MyApp extends StatelessWidget {
814
const MyApp({super.key});
915

10-
// This widget is the root of your application.
1116
@override
1217
Widget build(BuildContext context) {
1318
return MaterialApp(
14-
title: 'Flutter Demo',
19+
debugShowCheckedModeBanner: false,
20+
title: 'Movies App',
1521
theme: ThemeData(
16-
// This is the theme of your application.
17-
//
18-
// Try running your application with "flutter run". You'll see the
19-
// application has a blue toolbar. Then, without quitting the app, try
20-
// changing the primarySwatch below to Colors.green and then invoke
21-
// "hot reload" (press "r" in the console where you ran "flutter run",
22-
// or simply save your changes to "hot reload" in a Flutter IDE).
23-
// Notice that the counter didn't reset back to zero; the application
24-
// is not restarted.
2522
primarySwatch: Colors.blue,
2623
),
27-
home: const MyHomePage(title: 'Flutter Demo Home Page'),
28-
);
29-
}
30-
}
31-
32-
class MyHomePage extends StatefulWidget {
33-
const MyHomePage({super.key, required this.title});
34-
35-
// This widget is the home page of your application. It is stateful, meaning
36-
// that it has a State object (defined below) that contains fields that affect
37-
// how it looks.
38-
39-
// This class is the configuration for the state. It holds the values (in this
40-
// case the title) provided by the parent (in this case the App widget) and
41-
// used by the build method of the State. Fields in a Widget subclass are
42-
// always marked "final".
43-
44-
final String title;
45-
46-
@override
47-
State<MyHomePage> createState() => _MyHomePageState();
48-
}
49-
50-
class _MyHomePageState extends State<MyHomePage> {
51-
int _counter = 0;
52-
53-
void _incrementCounter() {
54-
setState(() {
55-
// This call to setState tells the Flutter framework that something has
56-
// changed in this State, which causes it to rerun the build method below
57-
// so that the display can reflect the updated values. If we changed
58-
// _counter without calling setState(), then the build method would not be
59-
// called again, and so nothing would appear to happen.
60-
_counter++;
61-
});
62-
}
63-
64-
@override
65-
Widget build(BuildContext context) {
66-
// This method is rerun every time setState is called, for instance as done
67-
// by the _incrementCounter method above.
68-
//
69-
// The Flutter framework has been optimized to make rerunning build methods
70-
// fast, so that you can just rebuild anything that needs updating rather
71-
// than having to individually change instances of widgets.
72-
return Scaffold(
73-
appBar: AppBar(
74-
// Here we take the value from the MyHomePage object that was created by
75-
// the App.build method, and use it to set our appbar title.
76-
title: Text(widget.title),
77-
),
78-
body: Center(
79-
// Center is a layout widget. It takes a single child and positions it
80-
// in the middle of the parent.
81-
child: Column(
82-
// Column is also a layout widget. It takes a list of children and
83-
// arranges them vertically. By default, it sizes itself to fit its
84-
// children horizontally, and tries to be as tall as its parent.
85-
//
86-
// Invoke "debug painting" (press "p" in the console, choose the
87-
// "Toggle Debug Paint" action from the Flutter Inspector in Android
88-
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
89-
// to see the wireframe for each widget.
90-
//
91-
// Column has various properties to control how it sizes itself and
92-
// how it positions its children. Here we use mainAxisAlignment to
93-
// center the children vertically; the main axis here is the vertical
94-
// axis because Columns are vertical (the cross axis would be
95-
// horizontal).
96-
mainAxisAlignment: MainAxisAlignment.center,
97-
children: <Widget>[
98-
const Text(
99-
'You have pushed the button this many times:',
100-
),
101-
Text(
102-
'$_counter',
103-
style: Theme.of(context).textTheme.headlineMedium,
104-
),
105-
],
106-
),
107-
),
108-
floatingActionButton: FloatingActionButton(
109-
onPressed: _incrementCounter,
110-
tooltip: 'Increment',
111-
child: const Icon(Icons.add),
112-
), // This trailing comma makes auto-formatting nicer for build methods.
24+
home: const MoviesScreen(),
11325
);
11426
}
11527
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'package:dio/dio.dart';
2+
import 'package:flutter_movie_app/core/error/exceptions.dart';
3+
import 'package:flutter_movie_app/core/network/api_constance.dart';
4+
import 'package:flutter_movie_app/movies/data/models/movie_model.dart';
5+
6+
import '../../../../core/network/error_message_model.dart';
7+
8+
abstract class BaseMovieRemoteDataSource {
9+
Future<List<MovieModel>> getNowPlayingMovie();
10+
Future<List<MovieModel>> getPopularMovie();
11+
Future<List<MovieModel>> getTopRatedMovie();
12+
}
13+
14+
class MovieRemoteDataSource extends BaseMovieRemoteDataSource {
15+
@override
16+
Future<List<MovieModel>> getNowPlayingMovie() async {
17+
final response = await Dio().get(ApiConstance.nowPlayingMoviePath);
18+
if (response.statusCode == 200) {
19+
return List<MovieModel>.from((response.data['results'] as List)
20+
.map((e) => MovieModel.fromJson(e)));
21+
} else {
22+
throw ServerException(
23+
errorMessageModel: ErrorMessageModel.fromJson(response.data));
24+
}
25+
}
26+
27+
@override
28+
Future<List<MovieModel>> getPopularMovie() async {
29+
final response = await Dio().get(ApiConstance.popularMoviePath);
30+
if (response.statusCode == 200) {
31+
return List<MovieModel>.from((response.data['results'] as List)
32+
.map((e) => MovieModel.fromJson(e)));
33+
} else {
34+
throw ServerException(
35+
errorMessageModel: ErrorMessageModel.fromJson(response.data));
36+
}
37+
}
38+
39+
@override
40+
Future<List<MovieModel>> getTopRatedMovie() async {
41+
final response = await Dio().get(ApiConstance.topRatedMoviePath);
42+
if (response.statusCode == 200) {
43+
return List<MovieModel>.from((response.data['results'] as List)
44+
.map((e) => MovieModel.fromJson(e)));
45+
} else {
46+
throw ServerException(
47+
errorMessageModel: ErrorMessageModel.fromJson(response.data));
48+
}
49+
}
50+
}

lib/movies/data/models/movie_model.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class MovieModel extends Movie {
1616
backdropPath: json['backdrop_path'],
1717
overView: json['overview'],
1818
genreIds: List<int>.from(json['genre_ids'].map((e) => e)),
19-
voteAverage: json['vote_average'],
19+
voteAverage: json['vote_average'].toDouble(),
2020
releaseDate: json['release_date'],
2121
);
2222
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import 'package:dartz/dartz.dart';
12
import 'package:flutter_movie_app/movies/domain/entities/movie.dart';
23

4+
import '../../../core/error/failure.dart';
5+
36
abstract class BaseMoviesRepository {
4-
Future<List<Movie>> getNowPlayingMovies();
5-
Future<List<Movie>> getTopRatedMovies();
6-
Future<List<Movie>> getPopularMovies();
7+
Future<Either<Failure, List<Movie>>> getNowPlayingMovies();
8+
Future<Either<Failure, List<Movie>>> getTopRatedMovies();
9+
Future<Either<Failure, List<Movie>>> getPopularMovies();
710
}
+3-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
import 'package:dartz/dartz.dart';
12
import 'package:flutter_movie_app/movies/domain/entities/movie.dart';
23

4+
import '../../../core/error/failure.dart';
35
import '../repo/base_movies_repo.dart';
46

57
class NowPlayingUsecase {
68
final BaseMoviesRepository baseMoviesRepository;
79

810
NowPlayingUsecase(this.baseMoviesRepository);
9-
Future<List<Movie>> excute() async {
11+
Future<Either<Failure, List<Movie>>> execute() async {
1012
return await baseMoviesRepository.getNowPlayingMovies();
1113
}
1214
}
+4-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import 'package:dartz/dartz.dart';
2+
3+
import '../../../core/error/failure.dart';
14
import '../entities/movie.dart';
25
import '../repo/base_movies_repo.dart';
36

47
class PopularUsecase {
58
final BaseMoviesRepository baseMoviesRepository;
69

710
PopularUsecase(this.baseMoviesRepository);
8-
Future<List<Movie>> excute() async {
11+
Future<Either<Failure, List<Movie>>> execute() async {
912
return await baseMoviesRepository.getPopularMovies();
1013
}
1114
}
+4-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import 'package:dartz/dartz.dart';
2+
3+
import '../../../core/error/failure.dart';
14
import '../entities/movie.dart';
25
import '../repo/base_movies_repo.dart';
36

47
class TopRatedUsecase {
58
final BaseMoviesRepository baseMoviesRepository;
69

710
TopRatedUsecase(this.baseMoviesRepository);
8-
Future<List<Movie>> excute() async {
11+
Future<Either<Failure, List<Movie>>> execute() async {
912
return await baseMoviesRepository.getTopRatedMovies();
1013
}
1114
}

0 commit comments

Comments
 (0)