From 19d1190bf598a6158c022b293a5a07c81739a436 Mon Sep 17 00:00:00 2001 From: Baraa Abdulrahman Date: Fri, 18 Jul 2025 08:09:53 +0300 Subject: [PATCH 1/5] feat: similar movies screen Added the similar movies screen. --- .../similarMovies/SimilarMoviesScreen.kt | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt diff --git a/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt new file mode 100644 index 000000000..906fc71e3 --- /dev/null +++ b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt @@ -0,0 +1,169 @@ +package com.madrid.presentation.screens.similarMovies + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.madrid.designsystem.AppTheme +import com.madrid.designsystem.R +import com.madrid.designsystem.component.MovioIcon +import com.madrid.designsystem.component.MovioText +import com.madrid.presentation.composables.movioCards.MovioVerticalCard + +data class Movie( + val title: String, + val rating: Float, + val posterUrl: String, + val ageRating: String? = null +) + +val moviesList = listOf( + Movie( + "The Dark Knight", + 5.0f, + "https://image.tmdb.org/t/p/w500/qJ2tW6WMUDux911r6m7haRef0WH.jpg", + "16" + ), + Movie( + "Spider-Man: Into the Spider-Verse", + 4.8f, + "https://image.tmdb.org/t/p/w500/iiZZdoQBEYBv6id8su7ImL0oCbD.jpg", + "12" + ), + Movie( + "Grave of the Fireflies", + 4.8f, + "https://image.tmdb.org/t/p/w500/q0VOH9aVLu5QQG5kumE36e6BjLf.jpg" + ), + Movie( + "À l'instinct - En eaux profondes", + 4.8f, + "https://image.tmdb.org/t/p/w500/8UlWHLMpgZm9bx6QYh0NFoq67TZ.jpg" + ), + Movie( + "Fullmetal Alchemist: Brotherhood", + 4.8f, + "https://image.tmdb.org/t/p/w500/4grx6h2B3p6kAMPxQ4vOBFSY6kG.jpg" + ), + Movie("Our girl", 4.2f, "https://image.tmdb.org/t/p/w500/2CAL2433ZeIihfX1Hb2139CX0pW.jpg"), + Movie( + "Ocean with David Attenborough", + 4.4f, + "https://image.tmdb.org/t/p/w500/6FfCtAuVAW8XJjZ7eWeLibRLWTw.jpg" + ), + Movie( + "The Ugly Stepsister", + 4.8f, + "https://image.tmdb.org/t/p/w500/9O1Iy9od7uGqF3Qh2l1AL5fGd2u.jpg" + ), + Movie( + "Thor: Ragnarok", + 4.5f, + "https://image.tmdb.org/t/p/w500/rzRwTcFvttcN1ZpX2xv4j3tSdJu.jpg" + ), + Movie( + "Jurassic World", + 4.0f, + "https://image.tmdb.org/t/p/w500/9gk7adHYeDvHkCSEqAvQNLV5Uge.jpg" + ), + Movie("Shark Tank", 4.6f, "https://image.tmdb.org/t/p/w500/6bCplVkhowCjTHXWv49UjRPn0eK.jpg"), + Movie( + "Detective Conan", + 4.1f, + "https://image.tmdb.org/t/p/w500/2vFuG6bWGyQUzYS9d69E5l85nIz.jpg" + ) +) + +@Composable +fun SimilarMoviesScreen( + onBackClick: () -> Unit = {}, + onMovieClick: (Movie) -> Unit = {}, + modifier: Modifier = Modifier +) { + var selectedMovieId by remember { mutableStateOf(null) } + Column( + modifier = modifier + .fillMaxSize() + .background(AppTheme.colors.surfaceColor.surface) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(40.dp) + .clickable { onBackClick() }, + contentAlignment = Alignment.Center + ) { + MovioIcon( + painter = painterResource(R.drawable.arrow_left), + contentDescription = "", + tint = AppTheme.colors.surfaceColor.onSurface + ) + } + Spacer(modifier = Modifier.weight(1f)) + MovioText( + text = "similar movie", + textStyle = AppTheme.textStyle.headLine.largeBold18, + color = AppTheme.colors.surfaceColor.onSurface + ) + Spacer(modifier = Modifier.weight(1f)) + } + LazyVerticalGrid( + modifier = Modifier.fillMaxSize(), + columns = GridCells.Fixed(3), + contentPadding = PaddingValues(16.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + items(moviesList) { movie -> + MovioVerticalCard( + description = movie.title, + movieImage = movie.posterUrl, + rate = movie.rating.toString(), + width = 101.33.dp, + height = 136.dp, + onClick = { + selectedMovieId = movie.title + onMovieClick(movie) + }, + modifier = Modifier, + paddingvalue = 0.dp + ) + } + } + } +} + +@Preview(showSystemUi = true, showBackground = true) +@Composable +fun SimilarMoviesScreenPreview() { + SimilarMoviesScreen( + onBackClick = {}, + onMovieClick = {} + ) +} \ No newline at end of file From 6521bd719cd3cbdf7648eca6d39e3687b23fb864 Mon Sep 17 00:00:00 2001 From: Baraa Abdulrahman Date: Fri, 18 Jul 2025 08:36:37 +0300 Subject: [PATCH 2/5] fix: string resources Add "Similar Movies" string resource in English and Arabic. Update SimilarMoviesScreen to use the new string resource. --- .../presentation/screens/similarMovies/SimilarMoviesScreen.kt | 3 ++- presentation/src/main/res/values-ar/string.xml | 1 + presentation/src/main/res/values/string.xml | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt index 906fc71e3..20815e9b5 100644 --- a/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt +++ b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt @@ -23,6 +23,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.madrid.designsystem.AppTheme @@ -127,7 +128,7 @@ fun SimilarMoviesScreen( } Spacer(modifier = Modifier.weight(1f)) MovioText( - text = "similar movie", + text = stringResource(id = com.madrid.presentation.R.string.selected_similar_movie), textStyle = AppTheme.textStyle.headLine.largeBold18, color = AppTheme.colors.surfaceColor.onSurface ) diff --git a/presentation/src/main/res/values-ar/string.xml b/presentation/src/main/res/values-ar/string.xml index 0f3d8691a..4930953ce 100644 --- a/presentation/src/main/res/values-ar/string.xml +++ b/presentation/src/main/res/values-ar/string.xml @@ -22,5 +22,6 @@ البحث الأخير مسح الكل أفضل طاقم + أفلام مشابهة \ No newline at end of file diff --git a/presentation/src/main/res/values/string.xml b/presentation/src/main/res/values/string.xml index 2cfa7753d..e2e7b50e5 100644 --- a/presentation/src/main/res/values/string.xml +++ b/presentation/src/main/res/values/string.xml @@ -23,5 +23,6 @@ Artists SearchResult (%1$s items)// Top Cast + Similar Movies \ No newline at end of file From 5ffa7369b1ef02504fbe23b280f72d8dcca7852c Mon Sep 17 00:00:00 2001 From: Baraa Abdulrahman Date: Fri, 18 Jul 2025 13:55:49 +0300 Subject: [PATCH 3/5] Refactor/similar-movies-screen - Use Movie domain model - Remove dummy data - Clean unused code from PreferredMediaUseCase --- .../searchUseCase/PreferredMediaUseCase.kt | 9 +-- .../similarMovies/SimilarMoviesScreen.kt | 79 +++---------------- 2 files changed, 10 insertions(+), 78 deletions(-) diff --git a/domain/src/main/java/com/madrid/domain/usecase/searchUseCase/PreferredMediaUseCase.kt b/domain/src/main/java/com/madrid/domain/usecase/searchUseCase/PreferredMediaUseCase.kt index 97128563f..13054455d 100644 --- a/domain/src/main/java/com/madrid/domain/usecase/searchUseCase/PreferredMediaUseCase.kt +++ b/domain/src/main/java/com/madrid/domain/usecase/searchUseCase/PreferredMediaUseCase.kt @@ -3,12 +3,5 @@ package com.madrid.domain.usecase.searchUseCase import com.madrid.domain.repository.SearchRepository class PreferredMediaUseCase(private val searchRepository: SearchRepository) { - /* suspend fun getPreferredMedia(): List { - val categories = searchRepository.getMostSearchedCategories() - val medias: MutableList = mutableListOf() - categories.forEach { category -> - medias.add(searchRepository.getMediaByCategory(category)) - } - return medias - }*/ + } diff --git a/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt index 20815e9b5..51465075d 100644 --- a/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt +++ b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt @@ -31,78 +31,16 @@ import com.madrid.designsystem.R import com.madrid.designsystem.component.MovioIcon import com.madrid.designsystem.component.MovioText import com.madrid.presentation.composables.movioCards.MovioVerticalCard - -data class Movie( - val title: String, - val rating: Float, - val posterUrl: String, - val ageRating: String? = null -) - -val moviesList = listOf( - Movie( - "The Dark Knight", - 5.0f, - "https://image.tmdb.org/t/p/w500/qJ2tW6WMUDux911r6m7haRef0WH.jpg", - "16" - ), - Movie( - "Spider-Man: Into the Spider-Verse", - 4.8f, - "https://image.tmdb.org/t/p/w500/iiZZdoQBEYBv6id8su7ImL0oCbD.jpg", - "12" - ), - Movie( - "Grave of the Fireflies", - 4.8f, - "https://image.tmdb.org/t/p/w500/q0VOH9aVLu5QQG5kumE36e6BjLf.jpg" - ), - Movie( - "À l'instinct - En eaux profondes", - 4.8f, - "https://image.tmdb.org/t/p/w500/8UlWHLMpgZm9bx6QYh0NFoq67TZ.jpg" - ), - Movie( - "Fullmetal Alchemist: Brotherhood", - 4.8f, - "https://image.tmdb.org/t/p/w500/4grx6h2B3p6kAMPxQ4vOBFSY6kG.jpg" - ), - Movie("Our girl", 4.2f, "https://image.tmdb.org/t/p/w500/2CAL2433ZeIihfX1Hb2139CX0pW.jpg"), - Movie( - "Ocean with David Attenborough", - 4.4f, - "https://image.tmdb.org/t/p/w500/6FfCtAuVAW8XJjZ7eWeLibRLWTw.jpg" - ), - Movie( - "The Ugly Stepsister", - 4.8f, - "https://image.tmdb.org/t/p/w500/9O1Iy9od7uGqF3Qh2l1AL5fGd2u.jpg" - ), - Movie( - "Thor: Ragnarok", - 4.5f, - "https://image.tmdb.org/t/p/w500/rzRwTcFvttcN1ZpX2xv4j3tSdJu.jpg" - ), - Movie( - "Jurassic World", - 4.0f, - "https://image.tmdb.org/t/p/w500/9gk7adHYeDvHkCSEqAvQNLV5Uge.jpg" - ), - Movie("Shark Tank", 4.6f, "https://image.tmdb.org/t/p/w500/6bCplVkhowCjTHXWv49UjRPn0eK.jpg"), - Movie( - "Detective Conan", - 4.1f, - "https://image.tmdb.org/t/p/w500/2vFuG6bWGyQUzYS9d69E5l85nIz.jpg" - ) -) +import com.madrid.domain.entity.Movie @Composable fun SimilarMoviesScreen( onBackClick: () -> Unit = {}, onMovieClick: (Movie) -> Unit = {}, + movies: List = emptyList(), modifier: Modifier = Modifier ) { - var selectedMovieId by remember { mutableStateOf(null) } + var selectedMovieId by remember { mutableStateOf(null) } Column( modifier = modifier .fillMaxSize() @@ -141,15 +79,15 @@ fun SimilarMoviesScreen( horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(12.dp), ) { - items(moviesList) { movie -> + items(movies) { movie -> MovioVerticalCard( description = movie.title, - movieImage = movie.posterUrl, - rate = movie.rating.toString(), + movieImage = movie.imageUrl, + rate = movie.rate.toString(), width = 101.33.dp, height = 136.dp, onClick = { - selectedMovieId = movie.title + selectedMovieId = movie.id onMovieClick(movie) }, modifier = Modifier, @@ -165,6 +103,7 @@ fun SimilarMoviesScreen( fun SimilarMoviesScreenPreview() { SimilarMoviesScreen( onBackClick = {}, - onMovieClick = {} + onMovieClick = {}, + movies = emptyList() ) } \ No newline at end of file From 48cb143f634513f6ccccbd5cc6cb6854787f7a1a Mon Sep 17 00:00:00 2001 From: Baraa Abdulrahman Date: Fri, 18 Jul 2025 15:05:19 +0300 Subject: [PATCH 4/5] feat: Enhance SimilarMoviesScreen with loading/error states - Integrate `SearchViewModel` to manage state for Similar Movies. - Display a "Loading..." message while fetching data. - Show an error message if data fetching fails. - Update movie click handling to use `SearchScreenState.MovieUiState`. - Add "loading" string resource in English and Arabic. --- .../similarMovies/SimilarMoviesScreen.kt | 47 +++++++++++++++---- .../src/main/res/values-ar/string.xml | 1 + presentation/src/main/res/values/string.xml | 1 + 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt index 51465075d..960e4ea45 100644 --- a/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt +++ b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -31,16 +32,20 @@ import com.madrid.designsystem.R import com.madrid.designsystem.component.MovioIcon import com.madrid.designsystem.component.MovioText import com.madrid.presentation.composables.movioCards.MovioVerticalCard -import com.madrid.domain.entity.Movie +import com.madrid.presentation.screens.searchScreen.viewModel.SearchScreenState +import com.madrid.presentation.screens.searchScreen.viewModel.SearchViewModel +import org.koin.androidx.compose.koinViewModel @Composable fun SimilarMoviesScreen( onBackClick: () -> Unit = {}, - onMovieClick: (Movie) -> Unit = {}, - movies: List = emptyList(), - modifier: Modifier = Modifier + onMovieClick: (SearchScreenState.MovieUiState) -> Unit = {}, + modifier: Modifier = Modifier, + viewModel: SearchViewModel = koinViewModel() ) { - var selectedMovieId by remember { mutableStateOf(null) } + val state by viewModel.state.collectAsState() + var selectedMovieId by remember { mutableStateOf(null) } + Column( modifier = modifier .fillMaxSize() @@ -79,11 +84,11 @@ fun SimilarMoviesScreen( horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(12.dp), ) { - items(movies) { movie -> + items(state.searchUiState.exploreMoreMovies) { movie -> MovioVerticalCard( description = movie.title, movieImage = movie.imageUrl, - rate = movie.rate.toString(), + rate = movie.rating, width = 101.33.dp, height = 136.dp, onClick = { @@ -95,6 +100,31 @@ fun SimilarMoviesScreen( ) } } + if (state.searchUiState.isLoading) { + Box( + Modifier + .fillMaxWidth() + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + MovioText( + text = stringResource(id = com.madrid.presentation.R.string.loading), + color = AppTheme.colors.surfaceColor.onSurface, + textStyle = AppTheme.textStyle.body.medium14 + ) + } + } + state.searchUiState.errorMessage?.let { errorMsg -> + Box(Modifier + .fillMaxWidth() + .padding(16.dp), contentAlignment = Alignment.Center) { + MovioText( + text = errorMsg, + color = AppTheme.colors.surfaceColor.outline, + textStyle = AppTheme.textStyle.body.medium14 + ) + } + } } } @@ -103,7 +133,6 @@ fun SimilarMoviesScreen( fun SimilarMoviesScreenPreview() { SimilarMoviesScreen( onBackClick = {}, - onMovieClick = {}, - movies = emptyList() + onMovieClick = {} ) } \ No newline at end of file diff --git a/presentation/src/main/res/values-ar/string.xml b/presentation/src/main/res/values-ar/string.xml index 850ae7fba..f4fd475a3 100644 --- a/presentation/src/main/res/values-ar/string.xml +++ b/presentation/src/main/res/values-ar/string.xml @@ -32,4 +32,5 @@ من أجلك رؤية الكل البحث عن المزيد + جاري التحميل... \ No newline at end of file diff --git a/presentation/src/main/res/values/string.xml b/presentation/src/main/res/values/string.xml index e7c89bf92..ce2506883 100644 --- a/presentation/src/main/res/values/string.xml +++ b/presentation/src/main/res/values/string.xml @@ -30,6 +30,7 @@ For You See all Explore more + Loading... \ No newline at end of file From c3e217d2f8e05a7ec14e0b673d62b2551990018c Mon Sep 17 00:00:00 2001 From: Baraa Abdulrahman Date: Fri, 18 Jul 2025 19:52:27 +0300 Subject: [PATCH 5/5] Refactor: similar movies screen top app bar The `SimilarMoviesScreen` now utilizes the `TopAppBar` composable for its header, replacing the previous custom `Row`-based implementation. The top app bar includes a back arrow icon and the title "Similar Movies". The back arrow's click functionality remains, triggering the `onBackClick` callback. The screen now also incorporates `statusBarsPadding` for better layout consistency. --- .../similarMovies/SimilarMoviesScreen.kt | 35 ++++++------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt index 960e4ea45..c112cc9e5 100644 --- a/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt +++ b/presentation/src/main/java/com/madrid/presentation/screens/similarMovies/SimilarMoviesScreen.kt @@ -6,12 +6,11 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items @@ -23,14 +22,13 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.madrid.designsystem.AppTheme import com.madrid.designsystem.R -import com.madrid.designsystem.component.MovioIcon import com.madrid.designsystem.component.MovioText +import com.madrid.designsystem.component.TopAppBar import com.madrid.presentation.composables.movioCards.MovioVerticalCard import com.madrid.presentation.screens.searchScreen.viewModel.SearchScreenState import com.madrid.presentation.screens.searchScreen.viewModel.SearchViewModel @@ -50,32 +48,19 @@ fun SimilarMoviesScreen( modifier = modifier .fillMaxSize() .background(AppTheme.colors.surfaceColor.surface) + .statusBarsPadding() ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 12.dp), - verticalAlignment = Alignment.CenterVertically - ) { + Box { + TopAppBar( + text = stringResource(id = com.madrid.presentation.R.string.selected_similar_movie), + firstIcon = R.drawable.arrow_left + ) Box( modifier = Modifier + .padding(horizontal = 16.dp, vertical = 12.dp) .size(40.dp) - .clickable { onBackClick() }, - contentAlignment = Alignment.Center - ) { - MovioIcon( - painter = painterResource(R.drawable.arrow_left), - contentDescription = "", - tint = AppTheme.colors.surfaceColor.onSurface - ) - } - Spacer(modifier = Modifier.weight(1f)) - MovioText( - text = stringResource(id = com.madrid.presentation.R.string.selected_similar_movie), - textStyle = AppTheme.textStyle.headLine.largeBold18, - color = AppTheme.colors.surfaceColor.onSurface + .clickable { onBackClick() } ) - Spacer(modifier = Modifier.weight(1f)) } LazyVerticalGrid( modifier = Modifier.fillMaxSize(),