Skip to content

Commit 3ee583a

Browse files
authored
Merge pull request #6 from piashcse/feature-search
[feat] Implemented movie search functionality
2 parents 36594b8 + f952a99 commit 3ee583a

File tree

15 files changed

+401
-104
lines changed

15 files changed

+401
-104
lines changed

ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
buildConfiguration = "Debug"
2727
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
2930
shouldUseLaunchSchemeArgsEnv = "YES">
3031
<MacroExpansion>
3132
<BuildableReference
@@ -54,11 +55,13 @@
5455
buildConfiguration = "Debug"
5556
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
5657
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
58+
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
5759
launchStyle = "0"
5860
useCustomWorkingDirectory = "NO"
5961
ignoresPersistentStateOnLaunch = "NO"
6062
debugDocumentVersioning = "YES"
6163
debugServiceExtension = "internal"
64+
enableGPUValidationMode = "1"
6265
allowLocationSimulation = "YES">
6366
<BuildableProductRunnable
6467
runnableDebuggingMode = "0">

lib/features/movie/data/datasources/movie_remote_data_source.dart

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,53 @@ class MovieRemoteDataSource {
88
MovieRemoteDataSource(this.dio);
99

1010
Future<List<MovieModel>> getNowPlaying(int page) async {
11-
final response = await dio.get('movie/now_playing', queryParameters: {'page': page});
11+
final response =
12+
await dio.get('movie/now_playing', queryParameters: {'page': page});
1213
return (response.data['results'] as List)
1314
.map((e) => MovieModel.fromJson(e))
1415
.toList();
1516
}
17+
1618
Future<List<MovieModel>> getPopular(int page) async {
17-
final response = await dio.get('movie/popular', queryParameters: {'page': page});
19+
final response =
20+
await dio.get('movie/popular', queryParameters: {'page': page});
1821
return (response.data['results'] as List)
1922
.map((e) => MovieModel.fromJson(e))
2023
.toList();
2124
}
25+
2226
Future<List<MovieModel>> getUpcoming(int page) async {
23-
final response = await dio.get('movie/top_rated', queryParameters: {'page': page});
27+
final response =
28+
await dio.get('movie/top_rated', queryParameters: {'page': page});
2429
return (response.data['results'] as List)
2530
.map((e) => MovieModel.fromJson(e))
2631
.toList();
2732
}
33+
2834
Future<List<MovieModel>> getTopRated(int page) async {
29-
final response = await dio.get('movie/upcoming', queryParameters: {'page': page});
35+
final response =
36+
await dio.get('movie/upcoming', queryParameters: {'page': page});
3037
return (response.data['results'] as List)
3138
.map((e) => MovieModel.fromJson(e))
3239
.toList();
3340
}
3441

3542
Future<MovieDetailModel> getMovieDetail(int id) async {
3643
final response = await dio.get('/movie/$id');
37-
if (response.statusCode == 200 && response.data != null && response.data is Map<String, dynamic>) {
44+
if (response.statusCode == 200 &&
45+
response.data != null &&
46+
response.data is Map<String, dynamic>) {
3847
return MovieDetailModel.fromJson(response.data as Map<String, dynamic>);
3948
} else {
4049
throw Exception('Failed to load movie detail: Invalid response');
4150
}
4251
}
52+
53+
Future<List<MovieModel>> getMovieSearch(String query) async {
54+
final response =
55+
await dio.get('/search/movie', queryParameters: {'query': query});
56+
return (response.data['results'] as List)
57+
.map((e) => MovieModel.fromJson(e))
58+
.toList();
59+
}
4360
}

lib/features/movie/data/repositories/movie_repository_impl.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,16 @@ class MovieRepositoryImpl implements MovieRepository {
7777
productionCompanies: model.productionCompanies?.map((company) => company.name ?? "").toList() ?? [],
7878
);
7979
}
80+
@override
81+
Future<List<Movie>> getMovieSearch(String query) async {
82+
final models = await remoteDataSource.getMovieSearch(query);
83+
return models
84+
.map((e) => Movie(
85+
id: e.id,
86+
title: e.title,
87+
posterPath: e.posterPath,
88+
overview: e.overview ?? '',
89+
))
90+
.toList();
91+
}
8092
}

lib/features/movie/domain/repositories/entities/movie_repository.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ abstract class MovieRepository {
77
Future<List<Movie>> getTopRated(int page);
88
Future<List<Movie>> getUpComing(int page);
99
Future<MovieDetail> getMovieDetail(int movieId);
10+
Future<List<Movie>> getMovieSearch(String query);
1011
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import 'package:flutter_movie_clean_architecture/features/movie/domain/entities/movie.dart';
2+
import 'package:flutter_movie_clean_architecture/features/movie/domain/repositories/entities/movie_repository.dart';
3+
4+
class GetMovieSearch {
5+
final MovieRepository repository;
6+
7+
GetMovieSearch(this.repository);
8+
9+
Future<List<Movie>> call(String query) => repository.getMovieSearch( query);
10+
}

lib/features/movie/presentation/pages/movie_main_page.dart

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,96 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_movie_clean_architecture/features/movie/presentation/pages/popular_page.dart';
33
import 'package:flutter_movie_clean_architecture/features/movie/presentation/pages/top_rated_page.dart';
44
import 'package:flutter_movie_clean_architecture/features/movie/presentation/pages/up_coming_page.dart';
5-
import 'now_playing_page.dart';
5+
import 'package:flutter_movie_clean_architecture/features/movie/presentation/widgets/movie_search.dart'
6+
show MovieSearchWidget;
7+
import 'package:flutter_riverpod/flutter_riverpod.dart';
68

9+
import 'now_playing_page.dart';
710

8-
class MovieMainPage extends StatefulWidget {
11+
class MovieMainPage extends ConsumerStatefulWidget {
912
const MovieMainPage({super.key});
1013

1114
@override
12-
State<MovieMainPage> createState() => _MovieMainPageState();
15+
ConsumerState<MovieMainPage> createState() => _MovieMainPageState();
1316
}
1417

15-
class _MovieMainPageState extends State<MovieMainPage> {
18+
class _MovieMainPageState extends ConsumerState<MovieMainPage> {
1619
int _selectedIndex = 0;
20+
bool _isSearching = false;
1721

1822
final _pages = [
19-
NowPlayingPage(),
20-
PopularPage(),
21-
TopRatedPage(),
22-
UpComingPage(),
23+
const NowPlayingPage(),
24+
const PopularPage(),
25+
const TopRatedPage(),
26+
const UpComingPage(),
27+
];
28+
29+
final _pageLabels = [
30+
'Now Playing',
31+
'Popular',
32+
'Top Rated',
33+
'Upcoming',
2334
];
2435

2536
void _onItemTapped(int index) {
2637
setState(() {
2738
_selectedIndex = index;
39+
_isSearching = false;
40+
});
41+
}
42+
43+
void _toggleSearch() {
44+
setState(() {
45+
_isSearching = !_isSearching;
46+
});
47+
}
48+
49+
void _closeSearch() {
50+
setState(() {
51+
_isSearching = false;
2852
});
2953
}
3054

3155
@override
3256
Widget build(BuildContext context) {
3357
return Scaffold(
34-
appBar: AppBar(title: const Text('Flutter Movie')),
35-
body: _pages[_selectedIndex],
58+
appBar: AppBar(
59+
title: Text(_pageLabels[_selectedIndex]),
60+
),
61+
body: Stack(
62+
children: [
63+
// Main content
64+
_pages[_selectedIndex],
65+
// Search overlay
66+
if (_isSearching)
67+
MovieSearchWidget(onClose: _closeSearch),
68+
],
69+
),
70+
floatingActionButton: FloatingActionButton(
71+
onPressed: _toggleSearch,
72+
child: const Icon(Icons.search),
73+
),
3674
bottomNavigationBar: BottomNavigationBar(
3775
currentIndex: _selectedIndex,
3876
onTap: _onItemTapped,
3977
type: BottomNavigationBarType.fixed,
4078
items: const [
41-
BottomNavigationBarItem(icon: Icon(Icons.movie), label: 'Now Playing'),
42-
BottomNavigationBarItem(icon: Icon(Icons.trending_up), label: 'Popular'),
43-
BottomNavigationBarItem(icon: Icon(Icons.star), label: 'Top Rated'),
44-
BottomNavigationBarItem(icon: Icon(Icons.keyboard_arrow_down), label: 'Upcoming'),
79+
BottomNavigationBarItem(
80+
icon: Icon(Icons.movie),
81+
label: 'Now Playing',
82+
),
83+
BottomNavigationBarItem(
84+
icon: Icon(Icons.trending_up),
85+
label: 'Popular',
86+
),
87+
BottomNavigationBarItem(
88+
icon: Icon(Icons.star),
89+
label: 'Top Rated',
90+
),
91+
BottomNavigationBarItem(
92+
icon: Icon(Icons.keyboard_arrow_down),
93+
label: 'Upcoming',
94+
),
4595
],
4696
),
4797
);

lib/features/movie/presentation/pages/now_playing_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class _MovieHomePageState extends ConsumerState<NowPlayingPage> {
7171
),
7272
itemCount: _movies.length,
7373
itemBuilder: (context, index) {
74-
return MovieCard(movie: _movies[index]);
74+
return MovieCardWidget(movie: _movies[index]);
7575
},
7676
),
7777
),

lib/features/movie/presentation/pages/popular_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class _PopularMoviePageState extends ConsumerState<PopularPage> {
7171
),
7272
itemCount: _movies.length,
7373
itemBuilder: (context, index) {
74-
return MovieCard(movie: _movies[index]);
74+
return MovieCardWidget(movie: _movies[index]);
7575
},
7676
),
7777
),

lib/features/movie/presentation/pages/top_rated_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class _TopRatedMoviePageState extends ConsumerState<TopRatedPage> {
7171
),
7272
itemCount: _movies.length,
7373
itemBuilder: (context, index) {
74-
return MovieCard(movie: _movies[index]);
74+
return MovieCardWidget(movie: _movies[index]);
7575
},
7676
),
7777
),

lib/features/movie/presentation/pages/up_coming_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class _UpComingMoviePageState extends ConsumerState<UpComingPage> {
7171
),
7272
itemCount: _movies.length,
7373
itemBuilder: (context, index) {
74-
return MovieCard(movie: _movies[index]);
74+
return MovieCardWidget(movie: _movies[index]);
7575
},
7676
),
7777
),

0 commit comments

Comments
 (0)