feat: implement history and save detection result to local database
This commit is contained in:
parent
5151379922
commit
287d5774e8
|
|
@ -11,6 +11,7 @@ import androidx.core.app.ActivityCompat
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.di.cameraModule
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.di.databaseModule
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.di.diagnosisModule
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.navigation.NavGraph
|
||||
import com.syaroful.agrilinkvocpro.presentation.theme.AgrilinkVocproTheme
|
||||
|
|
@ -21,7 +22,7 @@ class PlantDiseaseDetectionActivity : ComponentActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// load Module
|
||||
loadKoinModules(listOf(cameraModule, diagnosisModule))
|
||||
loadKoinModules(listOf(cameraModule, diagnosisModule, databaseModule))
|
||||
|
||||
Log.d("KOIN_DEBUG", "✅ cameraModule loaded, yeay 🤗")
|
||||
|
||||
|
|
@ -39,7 +40,7 @@ class PlantDiseaseDetectionActivity : ComponentActivity() {
|
|||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
unloadKoinModules(listOf(cameraModule, diagnosisModule))
|
||||
unloadKoinModules(listOf(cameraModule, diagnosisModule, databaseModule))
|
||||
Log.d("KOIN_DEBUG", "🧹 cameraModule unloaded")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.data.network.
|
|||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.data.repository.PlantDiagnosisRepository
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.data.repository.PlantDiagnosisRepositoryImpl
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.presentation.detail.PlantDiagnosisViewModel
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.presentation.history.HistoryViewModel
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
|
|
@ -43,5 +44,6 @@ val diagnosisModule = module {
|
|||
get<Retrofit>().create(GeminiApiService::class.java)
|
||||
}
|
||||
single<PlantDiagnosisRepository> { PlantDiagnosisRepositoryImpl(get()) }
|
||||
viewModel { PlantDiagnosisViewModel(get()) }
|
||||
viewModel { PlantDiagnosisViewModel(get(), get()) }
|
||||
viewModel { HistoryViewModel(get()) }
|
||||
}
|
||||
|
|
@ -2,16 +2,22 @@ package com.syaroful.agrilinkvocpro.plant_disease_detection_feature.navigation
|
|||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navArgument
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.presentation.camera.CameraScreen
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.presentation.camera.CameraViewModel
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.presentation.detail.DetailScreen
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.presentation.history.DetailHistoryScreen
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.presentation.history.HistoryScreen
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.presentation.history.HistoryViewModel
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Composable
|
||||
fun NavGraph(navController: NavHostController) {
|
||||
val cameraViewModel: CameraViewModel = koinViewModel()
|
||||
val historyViewModel: HistoryViewModel = koinViewModel()
|
||||
|
||||
|
||||
NavHost(navController, startDestination = "camera_screen") {
|
||||
|
|
@ -24,5 +30,20 @@ fun NavGraph(navController: NavHostController) {
|
|||
onBack = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
composable("history") {
|
||||
HistoryScreen(navController = navController, viewModel = historyViewModel)
|
||||
}
|
||||
composable(
|
||||
route = "detail-history/{id}",
|
||||
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
||||
) { backStackEntry ->
|
||||
val id = backStackEntry.arguments?.getInt("id") ?: return@composable
|
||||
|
||||
DetailHistoryScreen(
|
||||
navController = navController,
|
||||
diagnosisId = id,
|
||||
viewModel = historyViewModel
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -37,6 +37,7 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.syaroful.agrilinkvocpro.R
|
||||
import com.syaroful.agrilinkvocpro.core.components.AppButton
|
||||
import com.syaroful.agrilinkvocpro.core.components.DefaultErrorComponent
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.core.AppConstant
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.presentation.camera.CameraViewModel
|
||||
|
|
@ -53,6 +54,7 @@ fun DetailScreen(
|
|||
|
||||
val bitmap by cameraViewModel.bitmap.collectAsState()
|
||||
val diagnosisState by diagnosisViewModel.state.collectAsState()
|
||||
val saveLoading by diagnosisViewModel.saveLoadingState.collectAsState()
|
||||
|
||||
LaunchedEffect(bitmap) {
|
||||
if (bitmap != null && diagnosisState == null) {
|
||||
|
|
@ -101,6 +103,7 @@ fun DetailScreen(
|
|||
shape = RoundedCornerShape(8.dp),
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
bitmap = it.asImageBitmap(),
|
||||
contentDescription = "Gambar Tanaman",
|
||||
contentScale = ContentScale.Crop, // Make image fill the Card
|
||||
|
|
@ -141,7 +144,6 @@ fun DetailScreen(
|
|||
)
|
||||
}
|
||||
} else if (data?.diagnosis != null) {
|
||||
// Tampilkan detail diagnosis
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(
|
||||
|
|
@ -213,6 +215,12 @@ fun DetailScreen(
|
|||
}
|
||||
}
|
||||
}
|
||||
AppButton(
|
||||
label = if (saveLoading) "Menyimpan..." else "Simpan Hasil Deteksi",
|
||||
isEnable = !saveLoading
|
||||
) {
|
||||
diagnosisViewModel.saveResultToLocal(data, bitmap!!)
|
||||
}
|
||||
} else {
|
||||
Text("Gagal parsing response")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,18 +5,26 @@ import android.util.Log
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.core.extention.toBase64
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.core.extention.toByteArray
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.data.local.entity.PlantDiagnosisEntity
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.data.model.PlantDiseaseDetectionResponse
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.data.repository.PlantDiagnosisLocalRepository
|
||||
import com.syaroful.agrilinkvocpro.plant_disease_detection_feature.data.repository.PlantDiagnosisRepository
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class PlantDiagnosisViewModel(
|
||||
private val repository: PlantDiagnosisRepository
|
||||
private val repository: PlantDiagnosisRepository,
|
||||
private val localRepository: PlantDiagnosisLocalRepository
|
||||
) : ViewModel() {
|
||||
private val _state = MutableStateFlow<Result<PlantDiseaseDetectionResponse>?>(null)
|
||||
val state: StateFlow<Result<PlantDiseaseDetectionResponse>?> = _state
|
||||
|
||||
private val _saveLoadingState = MutableStateFlow(false)
|
||||
val saveLoadingState: StateFlow<Boolean> = _saveLoadingState
|
||||
|
||||
fun analyzePlant(bitmap: Bitmap, prompt: String) {
|
||||
Log.d("PlantDiagnosisViewModel", "analyzePlant() called")
|
||||
viewModelScope.launch {
|
||||
|
|
@ -31,4 +39,23 @@ class PlantDiagnosisViewModel(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun saveResultToLocal(response: PlantDiseaseDetectionResponse, image: Bitmap) {
|
||||
_saveLoadingState.value = true
|
||||
viewModelScope.launch {
|
||||
delay(1000L)
|
||||
val entity = PlantDiagnosisEntity(
|
||||
diagnosis = response.diagnosis ?: "Unknown",
|
||||
cause = response.cause ?: "-",
|
||||
description = response.description ?: "-",
|
||||
prevention = response.prevention?.joinToString(", ") ?: "-",
|
||||
image = image.toByteArray(),
|
||||
treatment = response.treatment?.joinToString(", ") {
|
||||
"${it.method}: ${it.description}"
|
||||
} ?: "-",
|
||||
)
|
||||
localRepository.saveDiagnosis(entity)
|
||||
_saveLoadingState.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user