diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ca5114c6..98a588b1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -115,6 +115,8 @@ dependencies { implementation(project(":feature:questions-or-collections:impl")) implementation(project(":feature:public-collections:impl")) implementation(project(":feature:selection-specializations:impl")) + implementation(project(":feature:interview-trainer:api")) + implementation(project(":feature:interview-trainer:impl")) } tasks.withType { diff --git a/app/src/main/java/ru/yeahub/Application.kt b/app/src/main/java/ru/yeahub/Application.kt index 792c54b3..f36bfecf 100644 --- a/app/src/main/java/ru/yeahub/Application.kt +++ b/app/src/main/java/ru/yeahub/Application.kt @@ -7,6 +7,7 @@ import ru.yeahub.detail_question.impl.di.detailQuestionFeatureModule import ru.yeahub.example_details.impl.detailsFeatureModule import ru.yeahub.example_home.impl.data.di.questionsMainFeatureModule import ru.yeahub.example_profile.impl.profileFeatureModule +import ru.yeahub.interview_trainer.impl.createQuiz.di.createQuizModule import ru.yeahub.navigation_impl.navigationPathModule import ru.yeahub.network_impl.networkModule import ru.yeahub.public_collections.impl.di.CollectionsFeatureModule @@ -53,7 +54,8 @@ class Application : Application() { CollectionsFeatureModule, detailQuestionFeatureModule, collectionsAndQuestionsFeatureModule, - specializationFeatureModule + specializationFeatureModule, + createQuizModule ) } // проверка, что модули загружены diff --git a/core/navigation-api/src/main/java/ru/yeahub/navigation_api/FeatureRoute.kt b/core/navigation-api/src/main/java/ru/yeahub/navigation_api/FeatureRoute.kt index bccd38fb..4d23aba2 100644 --- a/core/navigation-api/src/main/java/ru/yeahub/navigation_api/FeatureRoute.kt +++ b/core/navigation-api/src/main/java/ru/yeahub/navigation_api/FeatureRoute.kt @@ -65,5 +65,9 @@ object FeatureRoute { object InterviewTrainerFeature { const val FEATURE_NAME = "interview_trainer" + + const val CREATE_QUIZ_SCREEN_NAME = "create_quiz" + const val INTERVIEW_QUIZ_SCREEN_NAME = "interview_quiz" + const val INTERVIEW_QUIZ_RESULT_SCREEN_NAME = "interview_quiz_result" } } \ No newline at end of file diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index 774e6c8b..1b7c1a34 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -24,4 +24,7 @@ УПС! Назад Не удалось загрузить данные + + Интервью тренажер + Улучшите свои знания перед собеседованием \ No newline at end of file diff --git a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/QuestionMainFeatureImpl.kt b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/QuestionMainFeatureImpl.kt index 2bc10887..7c9dfe3f 100644 --- a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/QuestionMainFeatureImpl.kt +++ b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/QuestionMainFeatureImpl.kt @@ -28,7 +28,7 @@ class QuestionMainFeatureImpl : FeatureApi { navGraphBuilder: NavGraphBuilder, navController: NavHostController, pathManager: NavigationPathManager, - modifier: Modifier + modifier: Modifier, ) { val currentPath = pathManager.getCurrentPath() Timber.d("HomeFeatureImpl registerGraph: currentPath: $currentPath") @@ -50,6 +50,9 @@ class QuestionMainFeatureImpl : FeatureApi { }, onNavigateToCollections = { handleCollectionsNavigation(pathManager, navController) + }, + onNavigateToInterviewTrainer = { + handleInterviewTrainerNavigation(pathManager, navController) } ) } @@ -60,7 +63,7 @@ class QuestionMainFeatureImpl : FeatureApi { */ private fun handleQuestionsNavigation( pathManager: NavigationPathManager, - navController: NavHostController + navController: NavHostController, ) { // Сбрасываем текущий путь на корневую фичу pathManager.setCurrentPath(FeatureRoute.QuestionsFeature.FEATURE_NAME) @@ -83,7 +86,7 @@ class QuestionMainFeatureImpl : FeatureApi { */ private fun handleCollectionsNavigation( pathManager: NavigationPathManager, - navController: NavHostController + navController: NavHostController, ) { // Сбрасываем текущий путь на корневую фичу pathManager.setCurrentPath(FeatureRoute.CollectionsFeature.FEATURE_NAME) @@ -100,4 +103,31 @@ class QuestionMainFeatureImpl : FeatureApi { restoreState = true } } + + /** + * Обработка навигации к интервью тренажеру. + */ + private fun handleInterviewTrainerNavigation( + pathManager: NavigationPathManager, + navController: NavHostController, + ) { + val titleTopAppBar = "Test TitleTopAppBar" + + // Сбрасываем текущий путь на корневую фичу + pathManager.setCurrentPath(FeatureRoute.InterviewTrainerFeature.FEATURE_NAME) + + val createQuizPath = pathManager.createChildPath( + featureName = FeatureRoute.InterviewTrainerFeature.CREATE_QUIZ_SCREEN_NAME + ) + "/" + titleTopAppBar + + Timber.d("HomeFeatureImpl handleInterviewTrainerNavigation: Navigating to: $createQuizPath") + + navController.navigate(createQuizPath) { + popUpTo(navController.graph.startDestinationId) { + saveState = true + } + launchSingleTop = true + restoreState = true + } + } } diff --git a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/intents/QuestionMainScreenCommand.kt b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/intents/QuestionMainScreenCommand.kt index 99d2037e..5b55dd91 100644 --- a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/intents/QuestionMainScreenCommand.kt +++ b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/intents/QuestionMainScreenCommand.kt @@ -3,4 +3,5 @@ package ru.yeahub.example_home.impl.presentation.intents sealed class QuestionMainScreenCommand { object NavigateToBaseQuestions : QuestionMainScreenCommand() object NavigateToCollections : QuestionMainScreenCommand() + object NavigateToInterviewTrainer : QuestionMainScreenCommand() } \ No newline at end of file diff --git a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/mapper/QuestionMainScreenMapper.kt b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/mapper/QuestionMainScreenMapper.kt index f8b1470f..e4db2d99 100644 --- a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/mapper/QuestionMainScreenMapper.kt +++ b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/mapper/QuestionMainScreenMapper.kt @@ -14,6 +14,13 @@ class QuestionMainScreenMapper { description = TextOrResource.Resource(R.string.base_questions_description), imageRes = R.drawable.icon_base_question ), + //imageRes тренажера потом изменить на нормальный + QuestionMainUiModel( + type = QuestionMainItemType.InterviewTrainer, + title = TextOrResource.Resource(R.string.interview_trainer_title), + description = TextOrResource.Resource(R.string.interview_trainer_description), + imageRes = R.drawable.question_square + ), QuestionMainUiModel( type = QuestionMainItemType.Collections, title = TextOrResource.Resource(R.string.collections_title), diff --git a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/model/QuestionMainItemType.kt b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/model/QuestionMainItemType.kt index dbb2aa25..4c6e20c9 100644 --- a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/model/QuestionMainItemType.kt +++ b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/model/QuestionMainItemType.kt @@ -3,4 +3,5 @@ package ru.yeahub.example_home.impl.presentation.model sealed class QuestionMainItemType { object BaseQuestions : QuestionMainItemType() object Collections : QuestionMainItemType() + object InterviewTrainer : QuestionMainItemType() } diff --git a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/view/QuestionsMainScreen.kt b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/view/QuestionsMainScreen.kt index f433bac6..fb816572 100644 --- a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/view/QuestionsMainScreen.kt +++ b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/view/QuestionsMainScreen.kt @@ -37,7 +37,8 @@ import ru.yeahub.ui.R fun QuestionsMainScreen( onBackClick: () -> Unit, onNavigateToBaseQuestions: () -> Unit, - onNavigateToCollections: () -> Unit + onNavigateToCollections: () -> Unit, + onNavigateToInterviewTrainer: () -> Unit, ) { val viewModel: QuestionMainViewModel = koinViewModel() val state by viewModel.state.collectAsStateWithLifecycle() @@ -46,6 +47,7 @@ fun QuestionsMainScreen( when (command) { is QuestionMainScreenCommand.NavigateToBaseQuestions -> onNavigateToBaseQuestions() is QuestionMainScreenCommand.NavigateToCollections -> onNavigateToCollections() + is QuestionMainScreenCommand.NavigateToInterviewTrainer -> onNavigateToInterviewTrainer() } } @@ -60,7 +62,7 @@ fun QuestionsMainScreen( fun QuestionsMainScreenContent( state: QuestionMainScreenState, onItemClick: (QuestionMainUiModel) -> Unit, - onBackClick: () -> Unit + onBackClick: () -> Unit, ) { val context = LocalContext.current val scrollState = rememberScrollState() @@ -193,6 +195,13 @@ val stateWithContent = QuestionMainScreenState.Content( description = TextOrResource.Resource(R.string.base_questions_description), imageRes = R.drawable.icon_base_question ), + //imageRes тренажера потом изменить на нормальный + QuestionMainUiModel( + type = QuestionMainItemType.InterviewTrainer, + title = TextOrResource.Resource(R.string.interview_trainer_title), + description = TextOrResource.Resource(R.string.interview_trainer_description), + imageRes = R.drawable.question_square + ), QuestionMainUiModel( type = QuestionMainItemType.Collections, title = TextOrResource.Resource(R.string.collections_title), diff --git a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/viewmodel/QuestionMainViewModel.kt b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/viewmodel/QuestionMainViewModel.kt index 2b261a43..ba3b7c6a 100644 --- a/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/viewmodel/QuestionMainViewModel.kt +++ b/feature/example-home/impl/src/main/java/ru/yeahub/example_home/impl/presentation/viewmodel/QuestionMainViewModel.kt @@ -45,6 +45,10 @@ class QuestionMainViewModel( ) QuestionMainItemType.Collections -> _command.emit(QuestionMainScreenCommand.NavigateToCollections) + + QuestionMainItemType.InterviewTrainer -> { + _command.emit(QuestionMainScreenCommand.NavigateToInterviewTrainer) + } } } } diff --git a/feature/interview-trainer/api/src/main/java/ru/yeahub/interview_trainer/api/InterviewTrainerApi.kt b/feature/interview-trainer/api/src/main/java/ru/yeahub/interview_trainer/api/InterviewTrainerApi.kt index b98d29ed..0a7c0364 100644 --- a/feature/interview-trainer/api/src/main/java/ru/yeahub/interview_trainer/api/InterviewTrainerApi.kt +++ b/feature/interview-trainer/api/src/main/java/ru/yeahub/interview_trainer/api/InterviewTrainerApi.kt @@ -10,12 +10,16 @@ import androidx.compose.runtime.Composable */ interface InterviewTrainerApi { /** - * Экран тренажера собеседований. + * Главный/первый экран тренажера собеседований (CreateQuizScreen). + * Является entry-point'ом в фичу + * С него начинается вся внутренняя навигация * * @param onBackClick Действие при нажатии кнопки "Назад" + * @param onStartTrainingClick Действие при нажатии на старт тренировки в тренажере */ @Composable - fun InterviewTrainerScreen( + fun CreateQuizScreen( onBackClick: () -> Unit, + onStartTrainingClick: (specializationId: String, questionsCount: String) -> Unit, ) } \ No newline at end of file diff --git a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/InterviewTrainerFeatureImpl.kt b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/InterviewTrainerFeatureImpl.kt index 1c9a29f4..c21f5325 100644 --- a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/InterviewTrainerFeatureImpl.kt +++ b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/InterviewTrainerFeatureImpl.kt @@ -3,11 +3,19 @@ package ru.yeahub.interview_trainer.impl import androidx.compose.ui.Modifier import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController +import androidx.navigation.NavType +import androidx.navigation.compose.composable +import androidx.navigation.navArgument +import ru.yeahub.interview_trainer.impl.createQuiz.presentation.CreateQuizResult +import ru.yeahub.interview_trainer.impl.createQuiz.ui.CreateQuizScreen import ru.yeahub.navigation_api.FeatureApi import ru.yeahub.navigation_api.FeatureRoute import ru.yeahub.navigation_api.NavigationPathManager +import timber.log.Timber -class InterviewTrainerFeatureImpl : FeatureApi { +private const val TITLE_TOP_APP_BAR = "title" + +class InterviewTrainerFeatureImpl() : FeatureApi { override fun getFeatureName(): String = FeatureRoute.InterviewTrainerFeature.FEATURE_NAME override fun registerGraph( @@ -16,6 +24,88 @@ class InterviewTrainerFeatureImpl : FeatureApi { pathManager: NavigationPathManager, modifier: Modifier, ) { - TODO("Not yet implemented") + //Регистрируем базовый путь фичи (interview_trainer) + pathManager.registerFeaturePath(featureName = getFeatureName(), basePath = getFeatureName()) + + val featurePath = pathManager.getFeaturePath(getFeatureName()) ?: getFeatureName() + + //Создаем путь экрана создания тренировки (interview_trainer/create_quiz/{title} + val createQuizRoute = + "$featurePath/${FeatureRoute.InterviewTrainerFeature.CREATE_QUIZ_SCREEN_NAME}/{$TITLE_TOP_APP_BAR}" + + Timber.d("InterviewTrainerFeatureImpl registerGraph: currentPath: $createQuizRoute") + + navGraphBuilder.composable( + route = createQuizRoute, + arguments = listOf( + navArgument(TITLE_TOP_APP_BAR) { + type = NavType.StringType + } + ) + ) { backStackEntry -> + val titleTopAppBar = backStackEntry.arguments?.getString(TITLE_TOP_APP_BAR) ?: "" + + CreateQuizScreen( + onResult = { result -> + when (result) { + is CreateQuizResult.NavigateBack -> handleBackNavigation( + pathManager, + navController + ) + + is CreateQuizResult.NavigateToInterviewQuizScreen -> handleQuizNavigation( + pathManager = pathManager, + navController = navController, + titleTopAppBar = titleTopAppBar, + specializationId = result.specializationId.toString(), + questionsCount = result.questionCount.toString() + ) + } + }, + titleTopAppBar = titleTopAppBar + ) + } + } + + /** + * Обработка навигации назад. + */ + private fun handleBackNavigation( + pathManager: NavigationPathManager, + navController: NavHostController, + ) { + val parentPath = pathManager.getParentPath() + Timber.d("InterviewTrainerFeatureImpl handleBackNavigation: Navigating to parent: $parentPath") + + pathManager.setCurrentPath(parentPath) + + if (parentPath.isEmpty()) { + navController.navigateUp() + } else { + navController.navigate(parentPath) { + popUpTo(parentPath) { + inclusive = true + } + } + } + } + + /** + * Обработка навигации к экрану тренировки (InterviewQuizScreen). + */ + private fun handleQuizNavigation( + pathManager: NavigationPathManager, + navController: NavHostController, + titleTopAppBar: String, + specializationId: String, + questionsCount: String, + ) { + val interviewQuizRoute = getFeatureName() + "/" + + FeatureRoute.InterviewTrainerFeature.INTERVIEW_QUIZ_SCREEN_NAME + "/" + + "$titleTopAppBar/$specializationId/$questionsCount" + + Timber.d("InterviewTrainerFeatureImpl registerGraph: $interviewQuizRoute") + + navController.navigate(interviewQuizRoute) } } \ No newline at end of file diff --git a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizMapperModule.kt b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizMapperModule.kt new file mode 100644 index 00000000..63404062 --- /dev/null +++ b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizMapperModule.kt @@ -0,0 +1,13 @@ +package ru.yeahub.interview_trainer.impl.createQuiz.di + +import org.koin.dsl.module +import ru.yeahub.interview_trainer.impl.createQuiz.data.CreateQuizDataToDomainMapper +import ru.yeahub.interview_trainer.impl.createQuiz.presentation.CreateQuizScreenMapper + +val createQuizScreenMapperModule = module { + single { CreateQuizScreenMapper() } +} + +val createQuizDataToDomainMapperModule = module { + factory { CreateQuizDataToDomainMapper() } +} \ No newline at end of file diff --git a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizModule.kt b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizModule.kt new file mode 100644 index 00000000..3de9b4d8 --- /dev/null +++ b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizModule.kt @@ -0,0 +1,17 @@ +package ru.yeahub.interview_trainer.impl.createQuiz.di + +import org.koin.dsl.bind +import org.koin.dsl.module +import ru.yeahub.interview_trainer.impl.InterviewTrainerFeatureImpl +import ru.yeahub.navigation_api.FeatureApi + +val createQuizModule = module { + includes( + createQuizScreenMapperModule, + createQuizDataToDomainMapperModule, + createQuizRepositoryModule, + createQuizUseCaseModule, + createQuizViewModelModule + ) + single { InterviewTrainerFeatureImpl() } bind FeatureApi::class +} \ No newline at end of file diff --git a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizRepositoryModule.kt b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizRepositoryModule.kt new file mode 100644 index 00000000..6ee18e69 --- /dev/null +++ b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizRepositoryModule.kt @@ -0,0 +1,14 @@ +package ru.yeahub.interview_trainer.impl.createQuiz.di + +import org.koin.dsl.module +import ru.yeahub.interview_trainer.impl.createQuiz.data.CreateQuizRepositoryImpl +import ru.yeahub.interview_trainer.impl.createQuiz.domain.CreateQuizRepositoryApi + +val createQuizRepositoryModule = module { + single { + CreateQuizRepositoryImpl( + apiService = get(), + mapper = get() + ) + } +} \ No newline at end of file diff --git a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizUseCaseModule.kt b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizUseCaseModule.kt new file mode 100644 index 00000000..c38e3a9e --- /dev/null +++ b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizUseCaseModule.kt @@ -0,0 +1,13 @@ +package ru.yeahub.interview_trainer.impl.createQuiz.di + +import org.koin.dsl.module +import ru.yeahub.interview_trainer.impl.createQuiz.domain.GetSpecializationsListUseCaseImpl +import ru.yeahub.interview_trainer.impl.createQuiz.domain.GetSpecializationsUseCase + +val createQuizUseCaseModule = module { + factory { + GetSpecializationsListUseCaseImpl( + repository = get() + ) + } +} \ No newline at end of file diff --git a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizViewModelModule.kt b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizViewModelModule.kt new file mode 100644 index 00000000..2661abfa --- /dev/null +++ b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/di/CreateQuizViewModelModule.kt @@ -0,0 +1,14 @@ +package ru.yeahub.interview_trainer.impl.createQuiz.di + +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.dsl.module +import ru.yeahub.interview_trainer.impl.createQuiz.presentation.CreateQuizViewModel + +val createQuizViewModelModule = module { + viewModel { + CreateQuizViewModel( + getSpecializationsListUseCase = get(), + screenMapper = get() + ) + } +} \ No newline at end of file diff --git a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/presentation/CreateQuizScreenMapper.kt b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/presentation/CreateQuizScreenMapper.kt index 1abd7353..1a17edd5 100644 --- a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/presentation/CreateQuizScreenMapper.kt +++ b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/presentation/CreateQuizScreenMapper.kt @@ -2,7 +2,7 @@ package ru.yeahub.interview_trainer.impl.createQuiz.presentation import ru.yeahub.interview_trainer.impl.createQuiz.domain.DomainSpecialization -object CreateQuizScreenMapper { +class CreateQuizScreenMapper() { fun getScreenState( specializations: List, diff --git a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/ui/CreateQuizScreen.kt b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/ui/CreateQuizScreen.kt index 8ef23837..7a4203bc 100644 --- a/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/ui/CreateQuizScreen.kt +++ b/feature/interview-trainer/impl/src/main/java/ru/yeahub/interview_trainer/impl/createQuiz/ui/CreateQuizScreen.kt @@ -14,7 +14,9 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold @@ -36,9 +38,11 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow +import org.koin.androidx.compose.koinViewModel import ru.yeahub.core_ui.component.ErrorScreen import ru.yeahub.core_ui.component.PrimaryButton import ru.yeahub.core_ui.component.SkillButton @@ -65,23 +69,46 @@ private val FIGMA_HORIZONTAL_PADDING = 16.dp private val FIGMA_VERTICAL_BLOCKS_PADDING = 16.dp private val FIGMA_VERTICAL_FIRST_AND_LAST_ELEMENT_PADDING = 24.dp +@Composable +fun CreateQuizScreen( + onResult: (CreateQuizResult) -> Unit, + titleTopAppBar: String, +) { + val viewModel: CreateQuizViewModel = koinViewModel() + + val screenState by viewModel.screenState.collectAsStateWithLifecycle() + + HandleCommand( + commandFlow = viewModel.commands, + onResult = { result -> onResult(result) } + ) + + ScreenUI( + state = screenState, + onEvent = viewModel::onEvent, + titleTopAppBar = TextOrResource.Text(titleTopAppBar) + ) +} + @Composable private fun ScreenUI( state: CreateQuizState, onEvent: (CreateQuizEvent) -> Unit, - headerText: TextOrResource, + titleTopAppBar: TextOrResource, ) { Scaffold( containerColor = colors.black10, topBar = { TopAppBarWithBottomBorder( - title = headerText, + title = titleTopAppBar, onBackClick = { onEvent(CreateQuizEvent.OnBackClick) } ) } ) { paddingValues -> Box( - modifier = Modifier.padding(paddingValues) + modifier = Modifier + .padding(paddingValues) + .verticalScroll(rememberScrollState()) ) { when (state) { CreateQuizState.Loading -> CreateQuizLoading() @@ -409,7 +436,7 @@ fun CreateQuizScreenPreview( ScreenUI( state = state, onEvent = { }, - headerText = TextOrResource.Resource(R.string.create_quiz_top_bar_header_text), + titleTopAppBar = TextOrResource.Resource(R.string.create_quiz_top_bar_header_text), ) } @@ -433,7 +460,7 @@ fun DynamicPreviewUI() { } val mockViewModel = viewModelCreator { - CreateQuizViewModel(mockUseCase, CreateQuizScreenMapper) + CreateQuizViewModel(mockUseCase, CreateQuizScreenMapper()) } val mockState by mockViewModel.screenState.collectAsState() @@ -458,7 +485,7 @@ fun DynamicPreviewUI() { ScreenUI( state = mockState, onEvent = mockViewModel::onEvent, - headerText = TextOrResource.Resource(R.string.create_quiz_top_bar_header_text) + titleTopAppBar = TextOrResource.Resource(R.string.create_quiz_top_bar_header_text) ) } } diff --git a/feature/interview-trainer/impl/src/test/java/test/CreateQuizScreenMapperTest.kt b/feature/interview-trainer/impl/src/test/java/test/CreateQuizScreenMapperTest.kt index a041a7d3..0e85697d 100644 --- a/feature/interview-trainer/impl/src/test/java/test/CreateQuizScreenMapperTest.kt +++ b/feature/interview-trainer/impl/src/test/java/test/CreateQuizScreenMapperTest.kt @@ -15,7 +15,7 @@ class CreateQuizScreenMapperTest { fun getScreenStateTest( testCase: CreateQuizScreenMapperTestCase, ) { - val result = CreateQuizScreenMapper.getScreenState( + val result = CreateQuizScreenMapper().getScreenState( specializations = testCase.specializations, selectedSpecializationId = testCase.selectedSpecializationId, questionsCount = testCase.questionsCount