diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 8a0331c..caae2a6 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,3 +1,5 @@
+import java.util.Properties
+
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.compose)
@@ -21,6 +23,12 @@ android {
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+
+ val properties = Properties()
+ properties.load(project.rootProject.file("local.properties").inputStream())
+
+ buildConfigField("String", "SUPABASE_URL", "\"${properties.getProperty("SUPABASE_URL")}\"")
+ buildConfigField("String", "SUPABASE_ANON_KEY", "\"${properties.getProperty("SUPABASE_ANON_KEY")}\"")
}
buildTypes {
@@ -38,6 +46,7 @@ android {
}
buildFeatures {
compose = true
+ buildConfig = true
}
}
@@ -45,6 +54,7 @@ dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
+ implementation(libs.androidx.activity.ktx)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)
@@ -75,6 +85,11 @@ dependencies {
implementation(libs.coil.compose)
implementation(libs.coil.network.okhttp)
+ // Supabase
+ implementation(platform(libs.bom))
+ implementation(libs.postgrest.kt)
+ implementation(libs.ktor.client.android)
+
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6d91e7b..e133306 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,6 +5,7 @@
{ GundamdexHomeViewModel.Factory }
+
setContent {
GundamdexAppTheme {
- GundamdexNavigation()
+ GundamdexNavigation(
+ gundamdexHomeViewModel = gundamdexHomeViewModel,
+ )
}
}
}
diff --git a/app/src/main/java/com/example/gundamdexapp/data/network/AppContainer.kt b/app/src/main/java/com/example/gundamdexapp/data/network/AppContainer.kt
new file mode 100644
index 0000000..872a22a
--- /dev/null
+++ b/app/src/main/java/com/example/gundamdexapp/data/network/AppContainer.kt
@@ -0,0 +1,10 @@
+package com.example.gundamdexapp.data.network
+
+import com.example.gundamdexapp.data.network.repositoryImpl.GundamRepositoryImpl
+import com.example.gundamdexapp.domain.repository.GundamRepository
+
+class AppContainer {
+ val gundamRepository: GundamRepository by lazy {
+ GundamRepositoryImpl(SupabaseNetwork.gundamApi)
+ }
+}
diff --git a/app/src/main/java/com/example/gundamdexapp/data/network/SupabaseNetwork.kt b/app/src/main/java/com/example/gundamdexapp/data/network/SupabaseNetwork.kt
new file mode 100644
index 0000000..078be2c
--- /dev/null
+++ b/app/src/main/java/com/example/gundamdexapp/data/network/SupabaseNetwork.kt
@@ -0,0 +1,33 @@
+package com.example.gundamdexapp.data.network
+
+import com.example.gundamdexapp.BuildConfig
+import com.example.gundamdexapp.data.network.api.GundamApi
+import kotlinx.serialization.json.Json
+import okhttp3.MediaType.Companion.toMediaType
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Retrofit
+import retrofit2.converter.kotlinx.serialization.asConverterFactory
+
+object SupabaseNetwork {
+ // Logcat에서 통신 로그를 보기 위한 설정
+ private val loggingInterceptor = HttpLoggingInterceptor().apply {
+ level = HttpLoggingInterceptor.Level.BODY
+ }
+
+ private val okHttpClient = OkHttpClient.Builder()
+ .addInterceptor(loggingInterceptor)
+ .build()
+
+ private val json = Json {
+ ignoreUnknownKeys = true
+ }
+
+ private val retrofit = Retrofit.Builder()
+ .baseUrl("${BuildConfig.SUPABASE_URL}/")
+ .client(okHttpClient)
+ .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
+ .build()
+
+ val gundamApi: GundamApi = retrofit.create(GundamApi::class.java)
+}
diff --git a/app/src/main/java/com/example/gundamdexapp/data/network/api/GundamApi.kt b/app/src/main/java/com/example/gundamdexapp/data/network/api/GundamApi.kt
new file mode 100644
index 0000000..62acdd0
--- /dev/null
+++ b/app/src/main/java/com/example/gundamdexapp/data/network/api/GundamApi.kt
@@ -0,0 +1,25 @@
+package com.example.gundamdexapp.data.network.api
+
+import com.example.gundamdexapp.BuildConfig
+import com.example.gundamdexapp.data.network.dto.GundamDto
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Header
+import retrofit2.http.Query
+
+interface GundamApi {
+ @GET("rest/v1/gundams")
+ suspend fun getGundams(
+ @Header("apikey") apikey: String = BuildConfig.SUPABASE_ANON_KEY,
+ @Header("Authorization") auth: String = "Bearer ${BuildConfig.SUPABASE_ANON_KEY}",
+ @Query("select") selectQuery: String = "*, armaments(*)",
+ ): Response>
+
+ @GET("rest/v1/gundams")
+ suspend fun getGundamDetail(
+ @Header("apikey") apikey: String = BuildConfig.SUPABASE_ANON_KEY,
+ @Header("Authorization") auth: String = "Bearer ${BuildConfig.SUPABASE_ANON_KEY}",
+ @Query("id") idFilter: String,
+ @Query("select") selectQuery: String = "*, armaments(*)",
+ ): Response>
+}
diff --git a/app/src/main/java/com/example/gundamdexapp/data/network/dto/ArmamentDto.kt b/app/src/main/java/com/example/gundamdexapp/data/network/dto/ArmamentDto.kt
new file mode 100644
index 0000000..75e2e3c
--- /dev/null
+++ b/app/src/main/java/com/example/gundamdexapp/data/network/dto/ArmamentDto.kt
@@ -0,0 +1,21 @@
+package com.example.gundamdexapp.data.network.dto
+
+import com.example.gundamdexapp.domain.model.Armament
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ArmamentDto(
+ @SerialName("gundam_id")
+ val gundamId: String,
+ val name: String,
+ val details: String? = null,
+ @SerialName("indicator_color")
+ val indicatorColor: String,
+) {
+ fun toDomain(): Armament = Armament(
+ name = this.name,
+ details = this.details ?: "",
+ indicatorColor = this.indicatorColor,
+ )
+}
diff --git a/app/src/main/java/com/example/gundamdexapp/data/network/dto/GundamDto.kt b/app/src/main/java/com/example/gundamdexapp/data/network/dto/GundamDto.kt
new file mode 100644
index 0000000..d1cda74
--- /dev/null
+++ b/app/src/main/java/com/example/gundamdexapp/data/network/dto/GundamDto.kt
@@ -0,0 +1,68 @@
+package com.example.gundamdexapp.data.network.dto
+
+import com.example.gundamdexapp.domain.model.Armaments
+import com.example.gundamdexapp.domain.model.Dimensions
+import com.example.gundamdexapp.domain.model.GundamInfo
+import com.example.gundamdexapp.domain.model.TechnicalSpecifications
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class GundamDto(
+ val id: String,
+ @SerialName("model_number")
+ val modelNumber: String? = null,
+ val name: String,
+ val series: String,
+ @SerialName("image_url")
+ val imageUrl: String? = null,
+ val era: String,
+ val faction: String,
+ val pilot: String? = null,
+ val description: String,
+ @SerialName("dim_weight")
+ val weight: String? = null,
+ @SerialName("dim_height")
+ val height: String? = null,
+ @SerialName("tech_generator_output")
+ val generatorOutput: String? = null,
+ @SerialName("tech_armor_material")
+ val armorMaterial: String? = null,
+ @SerialName("tech_total_trust")
+ val totalTrust: String? = null,
+ @SerialName("tech_sensor_radius")
+ val sensorRadius: String? = null,
+ @SerialName("tech_crew")
+ val crew: String? = null,
+ val armaments: List = emptyList(),
+) {
+ fun toDomain(): GundamInfo = GundamInfo(
+ id = this.id,
+ modelNumber = this.modelNumber ?: MISSING_TEXT,
+ name = this.name,
+ series = this.series,
+ imageUrl = this.imageUrl ?: MISSING_URL,
+ era = this.era,
+ faction = this.faction,
+ pilot = this.pilot ?: MISSING_TEXT,
+ description = this.description,
+ dimensions = Dimensions(
+ height = this.height ?: MISSING_TEXT,
+ weight = this.weight ?: MISSING_TEXT,
+ ),
+ technicalSpecifications = TechnicalSpecifications(
+ generatorOutput = this.generatorOutput ?: MISSING_TEXT,
+ armorMaterial = this.armorMaterial ?: MISSING_TEXT,
+ totalTrust = this.totalTrust ?: MISSING_TEXT,
+ sensorRadius = this.sensorRadius ?: MISSING_TEXT,
+ crew = this.crew ?: MISSING_TEXT,
+ ),
+ armaments = Armaments(this.armaments.map { it.toDomain() }),
+ )
+
+ companion object {
+ const val MISSING_TEXT = "[ ? ]"
+ const val MISSING_URL =
+ "https://imgfiles-cdn.plaync.com/file/BladeNSoul/download/20190802085052-S4BOYrvsgcmithzSaShj0-v4"
+ }
+}
diff --git a/app/src/main/java/com/example/gundamdexapp/data/network/repositoryImpl/GundamRepositoryImpl.kt b/app/src/main/java/com/example/gundamdexapp/data/network/repositoryImpl/GundamRepositoryImpl.kt
new file mode 100644
index 0000000..db0e60f
--- /dev/null
+++ b/app/src/main/java/com/example/gundamdexapp/data/network/repositoryImpl/GundamRepositoryImpl.kt
@@ -0,0 +1,39 @@
+package com.example.gundamdexapp.data.network.repositoryImpl
+
+import com.example.gundamdexapp.data.network.api.GundamApi
+import com.example.gundamdexapp.domain.model.GundamInfo
+import com.example.gundamdexapp.domain.repository.GundamRepository
+
+class GundamRepositoryImpl(
+ private val api: GundamApi,
+) : GundamRepository {
+ override suspend fun getGundamList(): Result> = try {
+ val response = api.getGundams()
+
+ if (response.isSuccessful) {
+ val dtoList = response.body() ?: emptyList()
+
+ val domainList = dtoList.map { it.toDomain() }
+ Result.success(domainList)
+ } else {
+ Result.failure(Exception("서버 통신 실패 : ${response.code()}"))
+ }
+ } catch (e: Exception) {
+ Result.failure(e)
+ }
+
+ override suspend fun getGundamDetail(id: String): Result> = try {
+ val response = api.getGundamDetail(idFilter = "eq.$id")
+
+ if (response.isSuccessful) {
+ val gundamDto = response.body() ?: emptyList()
+
+ val domainList = gundamDto.map { it.toDomain() }
+ Result.success(domainList)
+ } else {
+ Result.failure(Exception("서버 통신 실패 : ${response.code()}"))
+ }
+ } catch (e: Exception) {
+ Result.failure(e)
+ }
+}
diff --git a/app/src/main/java/com/example/gundamdexapp/domain/repository/GundamRepository.kt b/app/src/main/java/com/example/gundamdexapp/domain/repository/GundamRepository.kt
new file mode 100644
index 0000000..23dc82d
--- /dev/null
+++ b/app/src/main/java/com/example/gundamdexapp/domain/repository/GundamRepository.kt
@@ -0,0 +1,8 @@
+package com.example.gundamdexapp.domain.repository
+
+import com.example.gundamdexapp.domain.model.GundamInfo
+
+interface GundamRepository {
+ suspend fun getGundamList(): Result>
+ suspend fun getGundamDetail(id: String): Result>
+}
diff --git a/app/src/main/java/com/example/gundamdexapp/feature/detail/GundamdexDetailStateHolder.kt b/app/src/main/java/com/example/gundamdexapp/feature/detail/GundamdexDetailStateHolder.kt
deleted file mode 100644
index 4943dfa..0000000
--- a/app/src/main/java/com/example/gundamdexapp/feature/detail/GundamdexDetailStateHolder.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.example.gundamdexapp.feature.detail
-
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import com.example.gundamdexapp.domain.model.GundamInfo
-import com.example.gundamdexapp.feature.detail.uimodel.ArmamentUiModel
-import com.example.gundamdexapp.feature.detail.uimodel.DimensionsUiModel
-import com.example.gundamdexapp.feature.detail.uimodel.GundamdexDetailUiModel
-import com.example.gundamdexapp.feature.detail.uimodel.IndicatorColor
-import com.example.gundamdexapp.feature.detail.uimodel.TechnicalSpecificationsUiModel
-
-class GundamdexDetailStateHolder(
- id: String,
- gundamData: List,
-) {
- var uiState by mutableStateOf(GundamdexDetailUiState())
-
- init {
- uiState = (
- gundamData.firstOrNull { it.id == id }?.let {
- uiState.copy(
- id = id,
- gundamdexDetailUiModel = GundamdexDetailUiModel(
- modelNumber = it.modelNumber,
- name = it.name,
- series = it.series,
- imageUrl = it.imageUrl,
- era = it.era,
- faction = it.faction,
- pilot = it.pilot,
- description = it.description,
- dimensions = it.dimensions.let { data ->
- DimensionsUiModel(
- height = data.height,
- weight = data.weight,
- )
- },
- technicalSpecifications = it.technicalSpecifications.let { data ->
- TechnicalSpecificationsUiModel(
- generatorOutput = data.generatorOutput,
- armorMaterial = data.armorMaterial,
- totalTrust = data.totalTrust,
- sensorRadius = data.sensorRadius,
- crew = data.crew,
- )
- },
- armaments = it.armaments.let { data ->
- data.value.map {
- ArmamentUiModel(
- name = it.name,
- details = it.details,
- indicatorColor = IndicatorColor.dataToIndicatorColor(it.indicatorColor),
- )
- }
- },
- ),
- )
- } ?: throw IllegalArgumentException("해당 카드의 id는 존재하지 않습니다.")
- )
- }
-}
diff --git a/app/src/main/java/com/example/gundamdexapp/feature/detail/GundamdexDetailViewModel.kt b/app/src/main/java/com/example/gundamdexapp/feature/detail/GundamdexDetailViewModel.kt
new file mode 100644
index 0000000..321989e
--- /dev/null
+++ b/app/src/main/java/com/example/gundamdexapp/feature/detail/GundamdexDetailViewModel.kt
@@ -0,0 +1,91 @@
+package com.example.gundamdexapp.feature.detail
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
+import androidx.lifecycle.viewModelScope
+import androidx.lifecycle.viewmodel.CreationExtras
+import com.example.gundamdexapp.GundamApplication
+import com.example.gundamdexapp.domain.model.GundamInfo
+import com.example.gundamdexapp.domain.repository.GundamRepository
+import com.example.gundamdexapp.feature.detail.uimodel.ArmamentUiModel
+import com.example.gundamdexapp.feature.detail.uimodel.DimensionsUiModel
+import com.example.gundamdexapp.feature.detail.uimodel.GundamdexDetailUiModel
+import com.example.gundamdexapp.feature.detail.uimodel.IndicatorColor
+import com.example.gundamdexapp.feature.detail.uimodel.TechnicalSpecificationsUiModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+
+class GundamdexDetailViewModel(
+ private val id: String,
+ private val repository: GundamRepository,
+) : ViewModel() {
+ private val _uiState = MutableStateFlow(GundamdexDetailUiState())
+ val uiState: StateFlow = _uiState.asStateFlow()
+
+ init {
+ viewModelScope.launch {
+ val gundamInfo = getGundamDetail(id)
+ setUiState(gundamInfo)
+ }
+ }
+
+ suspend fun getGundamDetail(id: String): GundamInfo? = repository.getGundamDetail(id).getOrNull()?.firstOrNull()
+
+ fun setUiState(gundamInfo: GundamInfo?) {
+ gundamInfo?.let { gundamInfo ->
+ _uiState.update {
+ it.copy(
+ id = id,
+ gundamdexDetailUiModel = GundamdexDetailUiModel(
+ modelNumber = gundamInfo.modelNumber,
+ name = gundamInfo.name,
+ series = gundamInfo.series,
+ imageUrl = gundamInfo.imageUrl,
+ era = gundamInfo.era,
+ faction = gundamInfo.faction,
+ pilot = gundamInfo.pilot,
+ description = gundamInfo.description,
+ dimensions = gundamInfo.dimensions.let { data ->
+ DimensionsUiModel(
+ height = data.height,
+ weight = data.weight,
+ )
+ },
+ technicalSpecifications = gundamInfo.technicalSpecifications.let { data ->
+ TechnicalSpecificationsUiModel(
+ generatorOutput = data.generatorOutput,
+ armorMaterial = data.armorMaterial,
+ totalTrust = data.totalTrust,
+ sensorRadius = data.sensorRadius,
+ crew = data.crew,
+ )
+ },
+ armaments = gundamInfo.armaments.let { data ->
+ data.value.map { value ->
+ ArmamentUiModel(
+ name = value.name,
+ details = value.details,
+ indicatorColor = IndicatorColor.dataToIndicatorColor(value.indicatorColor),
+ )
+ }
+ },
+ ),
+ )
+ }
+ } ?: throw IllegalArgumentException("해당 id를 가진 건담에 대한 정보가 존재하지 않습니다.")
+ }
+
+ class Factory(private val id: String) : ViewModelProvider.Factory {
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class, extras: CreationExtras): T {
+ val application = checkNotNull(extras[APPLICATION_KEY]) as GundamApplication
+ val repository = application.appContainer.gundamRepository
+
+ return GundamdexDetailViewModel(id = id, repository = repository) as T
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/gundamdexapp/feature/detail/mapper/IndicatorColorMapper.kt b/app/src/main/java/com/example/gundamdexapp/feature/detail/mapper/IndicatorColorMapper.kt
index 3680bc3..6ae7c1e 100644
--- a/app/src/main/java/com/example/gundamdexapp/feature/detail/mapper/IndicatorColorMapper.kt
+++ b/app/src/main/java/com/example/gundamdexapp/feature/detail/mapper/IndicatorColorMapper.kt
@@ -3,11 +3,11 @@ package com.example.gundamdexapp.feature.detail.mapper
import androidx.compose.ui.graphics.Color
import com.example.gundamdexapp.feature.detail.uimodel.IndicatorColor
import com.example.gundamdexapp.feature.detail.uimodel.IndicatorColor.BLUE
-import com.example.gundamdexapp.feature.detail.uimodel.IndicatorColor.GRAY
+import com.example.gundamdexapp.feature.detail.uimodel.IndicatorColor.GREY
import com.example.gundamdexapp.feature.detail.uimodel.IndicatorColor.RED
fun IndicatorColor.toColor(): Color = when (this) {
RED -> Color.Red
BLUE -> Color.Blue
- GRAY -> Color.Gray
+ GREY -> Color.Gray
}
diff --git a/app/src/main/java/com/example/gundamdexapp/feature/detail/uimodel/IndicatorColor.kt b/app/src/main/java/com/example/gundamdexapp/feature/detail/uimodel/IndicatorColor.kt
index c9e8748..f691990 100644
--- a/app/src/main/java/com/example/gundamdexapp/feature/detail/uimodel/IndicatorColor.kt
+++ b/app/src/main/java/com/example/gundamdexapp/feature/detail/uimodel/IndicatorColor.kt
@@ -3,14 +3,14 @@ package com.example.gundamdexapp.feature.detail.uimodel
enum class IndicatorColor {
RED,
BLUE,
- GRAY,
+ GREY,
;
companion object {
fun dataToIndicatorColor(value: String): IndicatorColor = when (value) {
"red" -> RED
"blue" -> BLUE
- "gray" -> GRAY
+ "grey" -> GREY
else -> throw IllegalArgumentException("잘못된 indicator color 입력 값을 전달받았습니다.")
}
}
diff --git a/app/src/main/java/com/example/gundamdexapp/feature/home/GundamdexHomeStatHolder.kt b/app/src/main/java/com/example/gundamdexapp/feature/home/GundamdexHomeStatHolder.kt
deleted file mode 100644
index 19ecc12..0000000
--- a/app/src/main/java/com/example/gundamdexapp/feature/home/GundamdexHomeStatHolder.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.example.gundamdexapp.feature.home
-
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import com.example.gundamdexapp.domain.model.GundamInfo
-
-class GundamdexHomeStatHolder(
- gundamData: List,
-) {
- var uiState by mutableStateOf(GundamdexHomeUiState())
-
- init {
- uiState = uiState.copy(
- gundamInfoList = gundamData.map {
- GundamdexHomeUiModel(
- id = it.id,
- modelNumber = it.modelNumber,
- name = it.name,
- series = it.series,
- imageUrl = it.imageUrl,
- )
- },
- )
- }
-}
diff --git a/app/src/main/java/com/example/gundamdexapp/feature/home/GundamdexHomeViewModel.kt b/app/src/main/java/com/example/gundamdexapp/feature/home/GundamdexHomeViewModel.kt
new file mode 100644
index 0000000..50d94f5
--- /dev/null
+++ b/app/src/main/java/com/example/gundamdexapp/feature/home/GundamdexHomeViewModel.kt
@@ -0,0 +1,55 @@
+package com.example.gundamdexapp.feature.home
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
+import androidx.lifecycle.viewModelScope
+import androidx.lifecycle.viewmodel.initializer
+import androidx.lifecycle.viewmodel.viewModelFactory
+import com.example.gundamdexapp.GundamApplication
+import com.example.gundamdexapp.domain.repository.GundamRepository
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+
+class GundamdexHomeViewModel(
+ private val gundamRepository: GundamRepository,
+) : ViewModel() {
+ private val _uiState = MutableStateFlow(GundamdexHomeUiState())
+ val uiState: StateFlow = _uiState.asStateFlow()
+
+ init {
+ getGundamList()
+ }
+
+ fun getGundamList() {
+ viewModelScope.launch {
+ _uiState.update {
+ it.copy(
+ gundamInfoList = gundamRepository.getGundamList()
+ .getOrThrow().map { gundamInfo ->
+ GundamdexHomeUiModel(
+ id = gundamInfo.id,
+ modelNumber = gundamInfo.modelNumber,
+ name = gundamInfo.name,
+ series = gundamInfo.series,
+ imageUrl = gundamInfo.imageUrl,
+ )
+ },
+ )
+ }
+ }
+ }
+
+ companion object {
+ val Factory = viewModelFactory {
+ initializer {
+ val application = this[APPLICATION_KEY] as GundamApplication
+ val repository = application.appContainer.gundamRepository
+
+ GundamdexHomeViewModel(gundamRepository = repository)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/gundamdexapp/feature/navigation/GundamdexNavigation.kt b/app/src/main/java/com/example/gundamdexapp/feature/navigation/GundamdexNavigation.kt
index 8ab25d4..4d4b810 100644
--- a/app/src/main/java/com/example/gundamdexapp/feature/navigation/GundamdexNavigation.kt
+++ b/app/src/main/java/com/example/gundamdexapp/feature/navigation/GundamdexNavigation.kt
@@ -2,21 +2,23 @@ package com.example.gundamdexapp.feature.navigation
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.toRoute
-import com.example.gundamdexapp.data.mock.GundamMockData
import com.example.gundamdexapp.feature.detail.GundamdexDetail
-import com.example.gundamdexapp.feature.detail.GundamdexDetailStateHolder
+import com.example.gundamdexapp.feature.detail.GundamdexDetailViewModel
import com.example.gundamdexapp.feature.home.GundamdexHome
-import com.example.gundamdexapp.feature.home.GundamdexHomeStatHolder
+import com.example.gundamdexapp.feature.home.GundamdexHomeViewModel
@Composable
-fun GundamdexNavigation() {
+fun GundamdexNavigation(
+ gundamdexHomeViewModel: GundamdexHomeViewModel,
+) {
val navController = rememberNavController()
- val gundamData = GundamMockData.mockGundams
SharedTransitionLayout {
NavHost(
@@ -24,8 +26,7 @@ fun GundamdexNavigation() {
startDestination = HomeRoute,
) {
composable {
- val gundamdexHomeStateHolder = remember { GundamdexHomeStatHolder(gundamData = gundamData) }
- val uiState = gundamdexHomeStateHolder.uiState
+ val uiState by gundamdexHomeViewModel.uiState.collectAsState()
GundamdexHome(
gundamdexHomeUiState = uiState,
@@ -41,13 +42,12 @@ fun GundamdexNavigation() {
val routeData = backStackEntity.toRoute()
val id = routeData.id
- val gundamdexDetailStateHolder = remember {
- GundamdexDetailStateHolder(
+ val viewModel: GundamdexDetailViewModel = viewModel(
+ factory = GundamdexDetailViewModel.Factory(
id = id,
- gundamData = gundamData,
- )
- }
- val uiState = remember { gundamdexDetailStateHolder.uiState }
+ ),
+ )
+ val uiState by viewModel.uiState.collectAsState()
GundamdexDetail(
gundamdexDetailUiState = uiState,
diff --git a/app/src/main/java/com/example/gundamdexapp/feature/utils/SharedTransitionKey.kt b/app/src/main/java/com/example/gundamdexapp/feature/utils/SharedTransitionKey.kt
index 3e8a1ae..4163467 100644
--- a/app/src/main/java/com/example/gundamdexapp/feature/utils/SharedTransitionKey.kt
+++ b/app/src/main/java/com/example/gundamdexapp/feature/utils/SharedTransitionKey.kt
@@ -2,9 +2,10 @@ package com.example.gundamdexapp.feature.utils
data class SharedTransitionKey(
val id: String,
- val type: SharedType
+ val type: SharedType,
)
enum class SharedType {
- COMPOSABLE, IMAGE
+ COMPOSABLE,
+ IMAGE,
}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 442c728..0b3023c 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,5 +1,6 @@
[versions]
agp = "9.2.1"
+bom = "3.6.0"
coilCompose = "3.5.0"
converterKotlinxSerialization = "2.11.0"
coreKtx = "1.16.0"
@@ -9,6 +10,7 @@ espressoCore = "3.7.0"
kotlinxCoroutinesAndroid = "1.11.0"
kotlinxCoroutinesCore = "1.11.0"
kotlinxSerializationJson = "1.11.0"
+ktorClientAndroid = "3.5.0"
lifecycleRuntimeKtx = "2.10.0"
activityCompose = "1.13.0"
kotlin = "2.4.0"
@@ -19,11 +21,13 @@ retrofit = "2.11.0"
ktlint = "14.2.0"
[libraries]
+androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityCompose" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleRuntimeKtx" }
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" }
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
+bom = { module = "io.github.jan-tennert.supabase:bom", version.ref = "bom" }
coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coilCompose" }
coil-network-okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coilCompose" }
converter-kotlinx-serialization = { module = "com.squareup.retrofit2:converter-kotlinx-serialization", version.ref = "converterKotlinxSerialization" }
@@ -43,7 +47,9 @@ androidx-compose-material3 = { group = "androidx.compose.material3", name = "mat
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesCore" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
+ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktorClientAndroid" }
logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "loggingInterceptor" }
+postgrest-kt = { module = "io.github.jan-tennert.supabase:postgrest-kt" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
[plugins]