From 293b7f75b95dbd8bd4c59b96b071fd297efb0972 Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot Date: Tue, 2 Sep 2025 22:29:15 +0200 Subject: [PATCH] feat: Implement data layer and basic quiz fetching logic This commit introduces the data layer, including the `QuizRepository` and its implementation, and integrates it with the domain layer's `GetQuizUseCase`. It also sets up Hilt for dependency injection in the app module and makes preliminary UI changes to display fetched quiz data. Key changes include: - **Data Layer (`model:data` module):** - Added `QuizRepositoryImpl` which implements `QuizRepository` from the domain layer. - Implemented `getQuiz()` in `QuizRepositoryImpl` to fetch quiz data from `QuizApi` and map it to the domain `Quiz` model using `QuizMapper`. - Created `QuizMapper` to convert `QuizResponseDto` to the domain `Quiz` model. - Added `RepositoryModule` for Hilt to provide `QuizRepository` bindings. - **Domain Layer (`domain` module):** - Created `Quiz` domain model. - Defined `QuizRepository` interface. - Implemented `GetQuizUseCase` to interact with `QuizRepository`. - **App Module (`app` module):** - Added `MyApplication` class annotated with `@HiltAndroidApp`. - Updated `AndroidManifest.xml` to use `MyApplication` and add internet permission. - In `MainActivity`: - Injected `GetQuizUseCase`. - Used `LaunchedEffect` to call the use case and update a mutable state `quizId`. - Modified the `Greeting` composable to display the fetched `quizId`. - Added dependency on the `domain` module in `app/build.gradle.kts`. - **Network Layer (`core:network` module):** - Moved DTOs from `core.network.model` package to `core.network.models`. - Made `NetworkModule` internal. - Removed unused `QuizService` interface and `QuizServiceImpl` class. - **Testing (`core:network` test):** - Updated import path for `QuizResponseDto` in `QuizResponseDtoParsingTest`. --- app/build.gradle.kts | 1 + app/src/main/AndroidManifest.xml | 7 +++--- .../dev/adriankuta/kahootquiz/MainActivity.kt | 22 ++++++++++++++++++- .../adriankuta/kahootquiz/MyApplication.kt | 7 ++++++ .../kahootquiz/core/network/QuizService.kt | 4 ---- .../core/network/QuizServiceImpl.kt | 4 ---- .../core/network/di/NetworkModule.kt | 2 +- .../network/{model => models}/CommonDtos.kt | 2 +- .../{model => models}/ContentTagsDto.kt | 2 +- .../network/{model => models}/CoverDtos.kt | 2 +- .../network/{model => models}/MetadataDtos.kt | 2 +- .../network/{model => models}/QuestionDtos.kt | 2 +- .../network/{model => models}/QuizResponse.kt | 2 +- .../{model => models}/QuizResponseDto.kt | 2 +- .../core/network/retrofit/QuizApi.kt | 2 +- .../network/QuizResponseDtoParsingTest.kt | 2 +- .../kahootquiz/domain/models/Quiz.kt | 5 +++++ .../domain/repositories/QuizRepository.kt | 7 ++++++ .../domain/usecases/GetQuizUseCase.kt | 14 ++++++++++++ .../model/data/QuizRepositoryImpl.kt | 16 ++++++++++++++ .../model/data/di/RepositoryModule.kt | 20 +++++++++++++++++ .../model/data/mappers/QuizMapper.kt | 7 ++++++ 22 files changed, 112 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/dev/adriankuta/kahootquiz/MyApplication.kt delete mode 100644 core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/QuizService.kt delete mode 100644 core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/QuizServiceImpl.kt rename core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/{model => models}/CommonDtos.kt (84%) rename core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/{model => models}/ContentTagsDto.kt (72%) rename core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/{model => models}/CoverDtos.kt (91%) rename core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/{model => models}/MetadataDtos.kt (93%) rename core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/{model => models}/QuestionDtos.kt (97%) rename core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/{model => models}/QuizResponse.kt (86%) rename core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/{model => models}/QuizResponseDto.kt (95%) create mode 100644 domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/models/Quiz.kt create mode 100644 domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/repositories/QuizRepository.kt create mode 100644 domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/usecases/GetQuizUseCase.kt create mode 100644 model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/QuizRepositoryImpl.kt create mode 100644 model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/di/RepositoryModule.kt create mode 100644 model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/mappers/QuizMapper.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7afebdf..bc1c146 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -28,6 +28,7 @@ android { dependencies { implementation(projects.ui.quiz) + implementation(projects.domain) implementation(projects.model.data) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 28a5aa0..cc72f51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,8 +1,10 @@ - + + + diff --git a/app/src/main/java/dev/adriankuta/kahootquiz/MainActivity.kt b/app/src/main/java/dev/adriankuta/kahootquiz/MainActivity.kt index 7e13051..1f0192a 100644 --- a/app/src/main/java/dev/adriankuta/kahootquiz/MainActivity.kt +++ b/app/src/main/java/dev/adriankuta/kahootquiz/MainActivity.kt @@ -9,19 +9,39 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview +import dagger.hilt.android.AndroidEntryPoint +import dev.adriankuta.kahootquiz.domain.usecases.GetQuizUseCase import dev.adriankuta.kahootquiz.ui.theme.KahootQuizTheme +import javax.inject.Inject +@AndroidEntryPoint class MainActivity : ComponentActivity() { + + @Inject + lateinit var getQuizUseCase: GetQuizUseCase + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { KahootQuizTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> + + var quizId by remember { mutableStateOf(null) } + + LaunchedEffect(Unit) { + quizId = getQuizUseCase().id + } + Greeting( - name = "Android", + name = quizId ?: "Android", modifier = Modifier.padding(innerPadding) ) } diff --git a/app/src/main/java/dev/adriankuta/kahootquiz/MyApplication.kt b/app/src/main/java/dev/adriankuta/kahootquiz/MyApplication.kt new file mode 100644 index 0000000..b856884 --- /dev/null +++ b/app/src/main/java/dev/adriankuta/kahootquiz/MyApplication.kt @@ -0,0 +1,7 @@ +package dev.adriankuta.kahootquiz + +import android.app.Application +import dagger.hilt.android.HiltAndroidApp + +@HiltAndroidApp +class MyApplication: Application() diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/QuizService.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/QuizService.kt deleted file mode 100644 index df6679d..0000000 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/QuizService.kt +++ /dev/null @@ -1,4 +0,0 @@ -package dev.adriankuta.kahootquiz.core.network - -interface QuizService { -} \ No newline at end of file diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/QuizServiceImpl.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/QuizServiceImpl.kt deleted file mode 100644 index 38d4cbd..0000000 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/QuizServiceImpl.kt +++ /dev/null @@ -1,4 +0,0 @@ -package dev.adriankuta.kahootquiz.core.network - -internal class QuizServiceImpl: QuizService { -} \ No newline at end of file diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/di/NetworkModule.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/di/NetworkModule.kt index 17bdb92..48ab164 100644 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/di/NetworkModule.kt +++ b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/di/NetworkModule.kt @@ -12,7 +12,7 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) -object NetworkModule { +internal object NetworkModule { @Provides @Singleton diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/CommonDtos.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/CommonDtos.kt similarity index 84% rename from core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/CommonDtos.kt rename to core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/CommonDtos.kt index f5bd507..d9b6c94 100644 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/CommonDtos.kt +++ b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/CommonDtos.kt @@ -1,4 +1,4 @@ -package dev.adriankuta.kahootquiz.core.network.model +package dev.adriankuta.kahootquiz.core.network.models // Commonly reused DTOs diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/ContentTagsDto.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/ContentTagsDto.kt similarity index 72% rename from core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/ContentTagsDto.kt rename to core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/ContentTagsDto.kt index 27bc9ea..39d93b2 100644 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/ContentTagsDto.kt +++ b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/ContentTagsDto.kt @@ -1,4 +1,4 @@ -package dev.adriankuta.kahootquiz.core.network.model +package dev.adriankuta.kahootquiz.core.network.models // Content tags DTOs diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/CoverDtos.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/CoverDtos.kt similarity index 91% rename from core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/CoverDtos.kt rename to core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/CoverDtos.kt index 6192bb2..5f8a3c2 100644 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/CoverDtos.kt +++ b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/CoverDtos.kt @@ -1,4 +1,4 @@ -package dev.adriankuta.kahootquiz.core.network.model +package dev.adriankuta.kahootquiz.core.network.models // Cover metadata and related DTOs diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/MetadataDtos.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/MetadataDtos.kt similarity index 93% rename from core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/MetadataDtos.kt rename to core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/MetadataDtos.kt index 16829fc..738a954 100644 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/MetadataDtos.kt +++ b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/MetadataDtos.kt @@ -1,4 +1,4 @@ -package dev.adriankuta.kahootquiz.core.network.model +package dev.adriankuta.kahootquiz.core.network.models // Metadata section DTOs diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/QuestionDtos.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/QuestionDtos.kt similarity index 97% rename from core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/QuestionDtos.kt rename to core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/QuestionDtos.kt index 9adcab2..f1d9e08 100644 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/QuestionDtos.kt +++ b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/QuestionDtos.kt @@ -1,4 +1,4 @@ -package dev.adriankuta.kahootquiz.core.network.model +package dev.adriankuta.kahootquiz.core.network.models // Question and choice related DTOs diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/QuizResponse.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/QuizResponse.kt similarity index 86% rename from core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/QuizResponse.kt rename to core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/QuizResponse.kt index 7001c97..426456d 100644 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/QuizResponse.kt +++ b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/QuizResponse.kt @@ -1,4 +1,4 @@ -package dev.adriankuta.kahootquiz.core.network.model +package dev.adriankuta.kahootquiz.core.network.models // This file used to contain all DTOs in one place. // The DTOs have been split into separate files for maintainability: diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/QuizResponseDto.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/QuizResponseDto.kt similarity index 95% rename from core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/QuizResponseDto.kt rename to core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/QuizResponseDto.kt index 0c1c54b..4050762 100644 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/model/QuizResponseDto.kt +++ b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/models/QuizResponseDto.kt @@ -1,4 +1,4 @@ -package dev.adriankuta.kahootquiz.core.network.model +package dev.adriankuta.kahootquiz.core.network.models import com.google.gson.annotations.SerializedName diff --git a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/retrofit/QuizApi.kt b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/retrofit/QuizApi.kt index 8d1be03..8b3256a 100644 --- a/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/retrofit/QuizApi.kt +++ b/core/network/src/main/kotlin/dev/adriankuta/kahootquiz/core/network/retrofit/QuizApi.kt @@ -1,6 +1,6 @@ package dev.adriankuta.kahootquiz.core.network.retrofit -import dev.adriankuta.kahootquiz.core.network.model.QuizResponseDto +import dev.adriankuta.kahootquiz.core.network.models.QuizResponseDto import retrofit2.http.GET interface QuizApi { diff --git a/core/network/src/test/kotlin/dev/adriankuta/kahootquiz/core/network/QuizResponseDtoParsingTest.kt b/core/network/src/test/kotlin/dev/adriankuta/kahootquiz/core/network/QuizResponseDtoParsingTest.kt index 372cd26..810a949 100644 --- a/core/network/src/test/kotlin/dev/adriankuta/kahootquiz/core/network/QuizResponseDtoParsingTest.kt +++ b/core/network/src/test/kotlin/dev/adriankuta/kahootquiz/core/network/QuizResponseDtoParsingTest.kt @@ -2,7 +2,7 @@ package dev.adriankuta.kahootquiz.core.network import com.google.common.truth.Truth.assertThat import com.google.gson.Gson -import dev.adriankuta.kahootquiz.core.network.model.QuizResponseDto +import dev.adriankuta.kahootquiz.core.network.models.QuizResponseDto import org.junit.Test import java.io.InputStreamReader diff --git a/domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/models/Quiz.kt b/domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/models/Quiz.kt new file mode 100644 index 0000000..a55a16c --- /dev/null +++ b/domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/models/Quiz.kt @@ -0,0 +1,5 @@ +package dev.adriankuta.kahootquiz.domain.models + +data class Quiz( + val id: String +) \ No newline at end of file diff --git a/domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/repositories/QuizRepository.kt b/domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/repositories/QuizRepository.kt new file mode 100644 index 0000000..4056a45 --- /dev/null +++ b/domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/repositories/QuizRepository.kt @@ -0,0 +1,7 @@ +package dev.adriankuta.kahootquiz.domain.repositories + +import dev.adriankuta.kahootquiz.domain.models.Quiz + +interface QuizRepository { + suspend fun getQuiz(): Quiz +} diff --git a/domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/usecases/GetQuizUseCase.kt b/domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/usecases/GetQuizUseCase.kt new file mode 100644 index 0000000..b1ae02b --- /dev/null +++ b/domain/src/main/kotlin/dev/adriankuta/kahootquiz/domain/usecases/GetQuizUseCase.kt @@ -0,0 +1,14 @@ +package dev.adriankuta.kahootquiz.domain.usecases + +import dev.adriankuta.kahootquiz.domain.models.Quiz +import dev.adriankuta.kahootquiz.domain.repositories.QuizRepository +import javax.inject.Inject + +class GetQuizUseCase @Inject constructor( + private val quizRepository: QuizRepository +) { + + suspend operator fun invoke(): Quiz { + return quizRepository.getQuiz() + } +} diff --git a/model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/QuizRepositoryImpl.kt b/model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/QuizRepositoryImpl.kt new file mode 100644 index 0000000..9ae8f24 --- /dev/null +++ b/model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/QuizRepositoryImpl.kt @@ -0,0 +1,16 @@ +package dev.adriankuta.kahootquiz.model.data + +import dev.adriankuta.kahootquiz.core.network.retrofit.QuizApi +import dev.adriankuta.kahootquiz.domain.models.Quiz +import dev.adriankuta.kahootquiz.domain.repositories.QuizRepository +import dev.adriankuta.kahootquiz.model.data.mappers.toDomainModel +import javax.inject.Inject + +internal class QuizRepositoryImpl @Inject constructor( + private val quizApi: QuizApi +) : QuizRepository { + + override suspend fun getQuiz(): Quiz { + return quizApi.getQuiz().toDomainModel() + } +} diff --git a/model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/di/RepositoryModule.kt b/model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/di/RepositoryModule.kt new file mode 100644 index 0000000..a7e858f --- /dev/null +++ b/model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/di/RepositoryModule.kt @@ -0,0 +1,20 @@ +package dev.adriankuta.kahootquiz.model.data.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dev.adriankuta.kahootquiz.domain.repositories.QuizRepository +import dev.adriankuta.kahootquiz.model.data.QuizRepositoryImpl +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +internal abstract class RepositoryModule { + + @Binds + @Singleton + abstract fun bindsQuizRepository( + quizRepositoryImpl: QuizRepositoryImpl + ): QuizRepository +} diff --git a/model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/mappers/QuizMapper.kt b/model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/mappers/QuizMapper.kt new file mode 100644 index 0000000..f564f10 --- /dev/null +++ b/model/data/src/main/kotlin/dev/adriankuta/kahootquiz/model/data/mappers/QuizMapper.kt @@ -0,0 +1,7 @@ +package dev.adriankuta.kahootquiz.model.data.mappers + +import dev.adriankuta.kahootquiz.core.network.models.QuizResponseDto +import dev.adriankuta.kahootquiz.domain.models.Quiz + +internal fun QuizResponseDto.toDomainModel(): Quiz = + Quiz(this.uuid ?: "")