feat: add database lab_test
This commit is contained in:
@@ -2,6 +2,7 @@ plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
alias(libs.plugins.ksp)
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -82,4 +83,9 @@ dependencies {
|
||||
|
||||
//navigation
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
|
||||
// Room Database
|
||||
implementation(libs.androidx.room.runtime)
|
||||
implementation(libs.androidx.room.ktx)
|
||||
ksp(libs.androidx.room.compiler)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<application
|
||||
android:name=".DrugApp"
|
||||
android:allowBackup="true"
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,10 @@
|
||||
package com.approagency.drug
|
||||
|
||||
import android.app.Application
|
||||
import com.approagency.drug.data.local.database.LabDatabase
|
||||
import com.approagency.drug.di.appModule
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.context.startKoin
|
||||
|
||||
@@ -13,5 +16,10 @@ class DrugApp : Application(){
|
||||
modules(appModule)
|
||||
printLogger()
|
||||
}
|
||||
|
||||
// Preload database (optional, for faster access)
|
||||
GlobalScope.launch {
|
||||
LabDatabase.getInstance(this@DrugApp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.approagency.drug.data.local.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.approagency.drug.data.local.entities.TestGroupEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface TestGroupDao {
|
||||
@Query("SELECT * FROM testGroup ORDER BY Id")
|
||||
fun getAllGroups(): Flow<List<TestGroupEntity>>
|
||||
|
||||
@Query("SELECT * FROM testGroup WHERE Id = :groupId")
|
||||
suspend fun getGroupById(groupId: Int): TestGroupEntity?
|
||||
|
||||
@Query("SELECT * FROM testGroup WHERE Isparent = '1'")
|
||||
fun getParentGroups(): Flow<List<TestGroupEntity>>
|
||||
|
||||
@Query("SELECT * FROM testGroup WHERE Isparent = '0'")
|
||||
fun getChildGroups(): Flow<List<TestGroupEntity>>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertGroup(group: TestGroupEntity)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertAllGroups(groups: List<TestGroupEntity>)
|
||||
|
||||
@Query("DELETE FROM testGroup")
|
||||
suspend fun deleteAllGroups()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.approagency.drug.data.local.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.approagency.drug.data.local.entities.TestItemEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface TestItemDao {
|
||||
@Query("SELECT * FROM testItem ORDER BY Id")
|
||||
fun getAllItems(): Flow<List<TestItemEntity>>
|
||||
|
||||
@Query("SELECT * FROM testItem WHERE Group_Id = :groupId ORDER BY Id")
|
||||
fun getItemsByGroupId(groupId: Int): Flow<List<TestItemEntity>>
|
||||
|
||||
@Query("SELECT * FROM testItem WHERE Id = :itemId")
|
||||
suspend fun getItemById(itemId: Int): TestItemEntity?
|
||||
|
||||
@Query("""
|
||||
SELECT ti.* FROM testItem ti
|
||||
INNER JOIN testGroup tg ON ti.Group_Id = tg.Id
|
||||
WHERE tg.Isparent = '0' AND ti.Title LIKE '%' || :searchQuery || '%'
|
||||
""")
|
||||
fun searchTestItems(searchQuery: String): Flow<List<TestItemEntity>>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertItem(item: TestItemEntity)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertAllItems(items: List<TestItemEntity>)
|
||||
|
||||
@Query("DELETE FROM testItem")
|
||||
suspend fun deleteAllItems()
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.approagency.drug.data.local.database
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import com.approagency.drug.data.local.dao.TestGroupDao
|
||||
import com.approagency.drug.data.local.dao.TestItemDao
|
||||
import com.approagency.drug.data.local.entities.TestGroupEntity
|
||||
import com.approagency.drug.data.local.entities.TestItemEntity
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
TestGroupEntity::class,
|
||||
TestItemEntity::class
|
||||
],
|
||||
version = 1,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class LabDatabase : RoomDatabase() {
|
||||
abstract fun testGroupDao(): TestGroupDao
|
||||
abstract fun testItemDao(): TestItemDao
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var INSTANCE: LabDatabase? = null
|
||||
|
||||
fun getInstance(context: Context): LabDatabase {
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
val instance = Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
LabDatabase::class.java,
|
||||
"lab_tests.db" // This will use your existing database
|
||||
)
|
||||
.createFromAsset("lab_tests.db") // IMPORTANT: Copy from assets
|
||||
.fallbackToDestructiveMigration() // For development only
|
||||
.build()
|
||||
INSTANCE = instance
|
||||
instance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.approagency.drug.data.local.entities
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "testGroup")
|
||||
data class TestGroupEntity(
|
||||
@PrimaryKey
|
||||
@ColumnInfo(name = "Id")
|
||||
val id: Int,
|
||||
|
||||
@ColumnInfo(name = "Ename")
|
||||
val ename: String?,
|
||||
|
||||
@ColumnInfo(name = "Fname")
|
||||
val fname: String?,
|
||||
|
||||
@ColumnInfo(name = "Detail")
|
||||
val detail: String?,
|
||||
|
||||
@ColumnInfo(name = "Isparent")
|
||||
val isParent: String?
|
||||
)
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.approagency.drug.data.local.entities
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(
|
||||
tableName = "testItem",
|
||||
// foreignKeys = [
|
||||
// ForeignKey(
|
||||
// entity = TestGroupEntity::class,
|
||||
// parentColumns = ["Id"],
|
||||
// childColumns = ["Group_Id"],
|
||||
// onDelete = ForeignKey.CASCADE
|
||||
// )
|
||||
// ],
|
||||
indices = [Index(value = ["Group_Id"])]
|
||||
)
|
||||
data class TestItemEntity(
|
||||
@PrimaryKey
|
||||
@ColumnInfo(name = "Id")
|
||||
val id: Int,
|
||||
|
||||
@ColumnInfo(name = "Group_Id")
|
||||
val groupId: Int,
|
||||
|
||||
@ColumnInfo(name = "Title")
|
||||
val title: String?,
|
||||
|
||||
@ColumnInfo(name = "Normal_Value")
|
||||
val normalValue: String?,
|
||||
|
||||
@ColumnInfo(name = "Detail")
|
||||
val detail: String?
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.approagency.drug.data.repository
|
||||
|
||||
import com.approagency.drug.data.local.dao.TestGroupDao
|
||||
import com.approagency.drug.data.local.dao.TestItemDao
|
||||
import com.approagency.drug.data.local.entities.TestGroupEntity
|
||||
import com.approagency.drug.data.local.entities.TestItemEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class LabRepositoryImpl (
|
||||
private val testGroupDao: TestGroupDao,
|
||||
private val testItemDao: TestItemDao
|
||||
) {
|
||||
// Test Group Operations
|
||||
fun getAllGroups(): Flow<List<TestGroupEntity>> = testGroupDao.getAllGroups()
|
||||
fun getParentGroups(): Flow<List<TestGroupEntity>> = testGroupDao.getParentGroups()
|
||||
fun getChildGroups(): Flow<List<TestGroupEntity>> = testGroupDao.getChildGroups()
|
||||
suspend fun getGroupById(groupId: Int): TestGroupEntity? = testGroupDao.getGroupById(groupId)
|
||||
|
||||
// Test Item Operations
|
||||
fun getAllItems(): Flow<List<TestItemEntity>> = testItemDao.getAllItems()
|
||||
fun getItemsByGroupId(groupId: Int): Flow<List<TestItemEntity>> = testItemDao.getItemsByGroupId(groupId)
|
||||
suspend fun getItemById(itemId: Int): TestItemEntity? = testItemDao.getItemById(itemId)
|
||||
fun searchTestItems(query: String): Flow<List<TestItemEntity>> = testItemDao.searchTestItems(query)
|
||||
}
|
||||
@@ -2,20 +2,32 @@ package com.approagency.drug.di
|
||||
|
||||
|
||||
import android.app.Application
|
||||
import com.approagency.drug.data.local.database.LabDatabase
|
||||
import com.approagency.drug.data.remote.DrugApiService
|
||||
import com.approagency.drug.data.repository.DrugRepositoryImpl
|
||||
import com.approagency.drug.data.repository.LabRepositoryImpl
|
||||
import com.approagency.drug.domain.repository.DrugRepository
|
||||
import com.approagency.drug.domain.usecase.GetDarmanUseCase
|
||||
import com.approagency.drug.domain.usecase.GetDrugDetailUseCase
|
||||
import com.approagency.drug.domain.usecase.GetDrugSearchUseCase
|
||||
import com.approagency.drug.domain.usecase.GetTestGroupUseCase
|
||||
import com.approagency.drug.domain.usecase.GetTestItemByGroupId
|
||||
import com.approagency.drug.presentation.viewModel.HomeViewModel
|
||||
import com.approagency.drug.presentation.viewModel.LabViewModel
|
||||
import com.approagency.drug.utils.Config
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.module.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
val appModule= module {
|
||||
|
||||
single { LabDatabase.getInstance(androidContext()) }
|
||||
|
||||
single { get<LabDatabase>().testGroupDao() }
|
||||
single { get<LabDatabase>().testItemDao() }
|
||||
|
||||
single {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(Config.BASE_URL)
|
||||
@@ -47,8 +59,21 @@ val appModule= module {
|
||||
GetDarmanUseCase(get())
|
||||
}
|
||||
|
||||
single {
|
||||
GetTestGroupUseCase(get())
|
||||
}
|
||||
|
||||
single {
|
||||
GetTestItemByGroupId(get())
|
||||
}
|
||||
|
||||
single { LabRepositoryImpl(get(), get()) }
|
||||
//view model
|
||||
viewModel {
|
||||
HomeViewModel(get() , get() , get())
|
||||
}
|
||||
|
||||
viewModel {
|
||||
LabViewModel(get() , get())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.approagency.drug.domain.model
|
||||
|
||||
data class TestGroup(
|
||||
val id: Int,
|
||||
val ename: String?,
|
||||
val fname: String?,
|
||||
val detail: String?,
|
||||
val isParent: Boolean
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.approagency.drug.domain.model
|
||||
|
||||
data class TestItem(
|
||||
val id: Int,
|
||||
val groupId: Int,
|
||||
val title: String?,
|
||||
val normalValue: String?,
|
||||
val detail: String?
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.approagency.drug.domain.usecase
|
||||
|
||||
import com.approagency.drug.data.repository.LabRepositoryImpl
|
||||
import com.approagency.drug.domain.model.TestGroup
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class GetTestGroupUseCase (
|
||||
private val repository: LabRepositoryImpl
|
||||
) {
|
||||
operator fun invoke(): Flow<List<TestGroup>> {
|
||||
return repository.getAllGroups().map { entities ->
|
||||
entities.map { entity ->
|
||||
TestGroup(
|
||||
id = entity.id,
|
||||
ename = entity.ename,
|
||||
fname = entity.fname,
|
||||
detail = entity.detail,
|
||||
isParent = entity.isParent == "1"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.approagency.drug.domain.usecase
|
||||
|
||||
import com.approagency.drug.data.local.entities.TestItemEntity
|
||||
import com.approagency.drug.data.repository.LabRepositoryImpl
|
||||
import com.approagency.drug.domain.model.TestItem
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class GetTestItemByGroupId (
|
||||
private val repository: LabRepositoryImpl
|
||||
) {
|
||||
operator fun invoke(id:Int): Flow<List<TestItem>> {
|
||||
return repository.getItemsByGroupId(groupId = id).map {
|
||||
entities -> entities.map {
|
||||
entity ->
|
||||
TestItem(
|
||||
id = entity.id,
|
||||
groupId = entity.groupId,
|
||||
title = entity.title,
|
||||
normalValue = entity.normalValue,
|
||||
detail = entity.detail,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,185 @@
|
||||
package com.approagency.drug.presentation.screens
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.approagency.drug.presentation.viewModel.HomeViewModel
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.approagency.drug.domain.model.TestGroup
|
||||
import com.approagency.drug.presentation.common.CustomBox
|
||||
import com.approagency.drug.presentation.common.CustomModalDialog
|
||||
import com.approagency.drug.presentation.common.Loading
|
||||
import com.approagency.drug.presentation.common.PrimaryButton
|
||||
import com.approagency.drug.presentation.viewModel.LabViewModel
|
||||
import com.vada.caller.ui.theme.dime
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.count
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Composable
|
||||
fun LabScreen(
|
||||
modifier: Modifier,
|
||||
viewModel: HomeViewModel = koinViewModel()
|
||||
){}
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: LabViewModel = koinViewModel()
|
||||
) {
|
||||
val testGroupsState by viewModel.testGroups.collectAsState()
|
||||
val isLoading = testGroupsState.isLoading
|
||||
val error = testGroupsState.error
|
||||
val testGroups = testGroupsState.testGroup
|
||||
|
||||
Column(modifier = modifier.fillMaxSize()) {
|
||||
if (isLoading) {
|
||||
CustomModalDialog(
|
||||
onDismissRequest = { /* maybe disable dismiss while loading */ },
|
||||
content = {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Loading(color = MaterialTheme.colorScheme.primary)
|
||||
Spacer(modifier = Modifier.height(MaterialTheme.dime.sm))
|
||||
Text("در حال جستجو..." , textAlign = TextAlign.Right)
|
||||
}
|
||||
},
|
||||
// modifier = Modifier
|
||||
// .matchParentSize()
|
||||
// .background(MaterialTheme.colorScheme.background.copy(alpha = 0.5f))
|
||||
)
|
||||
}
|
||||
else if(error != null){
|
||||
CustomBox(
|
||||
child = {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.padding(MaterialTheme.dime.md)
|
||||
) {
|
||||
Text(
|
||||
text = "خطا در دریافت اطلاعات",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.error
|
||||
)
|
||||
Text(
|
||||
text = error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
PrimaryButton(
|
||||
text = "تلاش مجدد",
|
||||
height = 40,
|
||||
isLoading = false,
|
||||
onClick = { viewModel.loadTestGroups() }
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
else if (testGroups != null){
|
||||
TestGroupsList(
|
||||
testGroupsFlow = testGroups,
|
||||
viewModel = viewModel
|
||||
)
|
||||
} else {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text("هیچ دادهای موجود نیست")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TestGroupsList(
|
||||
testGroupsFlow: Flow<List<TestGroup>>,
|
||||
viewModel: LabViewModel
|
||||
) {
|
||||
val testGroups by testGroupsFlow.collectAsState(initial = emptyList())
|
||||
|
||||
if (testGroups.isEmpty()) {
|
||||
CustomModalDialog(
|
||||
onDismissRequest = { /* maybe disable dismiss while loading */ },
|
||||
content = {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Loading(color = MaterialTheme.colorScheme.primary)
|
||||
Spacer(modifier = Modifier.height(MaterialTheme.dime.sm))
|
||||
Text("در حال جستجو..." , textAlign = TextAlign.Right)
|
||||
}
|
||||
},
|
||||
// modifier = Modifier
|
||||
// .matchParentSize()
|
||||
// .background(MaterialTheme.colorScheme.background.copy(alpha = 0.5f))
|
||||
)
|
||||
} else {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
items(testGroups) { group ->
|
||||
TestGroupItem(
|
||||
group = group,
|
||||
onClick = {
|
||||
// Navigate to test items of this group
|
||||
// viewModel.loadTestItemsByGroup(group.id)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TestGroupItem(
|
||||
group: TestGroup,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
CustomBox (
|
||||
modifier = Modifier
|
||||
.padding(bottom = MaterialTheme.dime.sm)
|
||||
.clickable(
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
onClick()
|
||||
},
|
||||
) {
|
||||
Column (
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.Start
|
||||
) {
|
||||
Text(
|
||||
text = group.fname ?: group.ename ?: "بدون نام",
|
||||
style = MaterialTheme.typography.titleMedium.copy(
|
||||
textAlign = TextAlign.Right,
|
||||
textDirection = TextDirection.Rtl
|
||||
),
|
||||
modifier = Modifier.padding(vertical = MaterialTheme.dime.xs)
|
||||
)
|
||||
group.detail?.let {
|
||||
Text(
|
||||
text = it,
|
||||
style = MaterialTheme.typography.bodySmall.copy(
|
||||
textAlign = TextAlign.Right ,
|
||||
textDirection = TextDirection.Rtl
|
||||
),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(horizontal = MaterialTheme.dime.lg)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ fun RootScreen(navHostController: NavHostController, modifier: Modifier){
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(110.dp).padding(bottom = 2.dp).clip(MaterialTheme.shapes.extraLarge), // 👈 کوچیکتر از حالت پیشفرض
|
||||
.height(110.dp).padding(bottom = 2.dp).clip(MaterialTheme.shapes.extraLarge),
|
||||
tonalElevation = 8.dp, // subtle shadow
|
||||
windowInsets = WindowInsets.navigationBars
|
||||
.only(WindowInsetsSides.Bottom)
|
||||
@@ -114,7 +114,7 @@ fun RootScreen(navHostController: NavHostController, modifier: Modifier){
|
||||
)
|
||||
},
|
||||
|
||||
alwaysShowLabel = true // 👈 فقط وقتی select شد label نشون بده
|
||||
alwaysShowLabel = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.approagency.drug.presentation.viewModel
|
||||
|
||||
import android.net.http.HttpException
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.approagency.drug.data.dto.DrugListResponse
|
||||
import com.approagency.drug.data.dto.DrugModels
|
||||
import com.approagency.drug.domain.model.TestGroup
|
||||
import com.approagency.drug.domain.model.TestItem
|
||||
import com.approagency.drug.domain.usecase.GetTestGroupUseCase
|
||||
import com.approagency.drug.domain.usecase.GetTestItemByGroupId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
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 LabViewModel (
|
||||
private val getTestGroupUseCase: GetTestGroupUseCase,
|
||||
private val getTestItemByGroupId: GetTestItemByGroupId
|
||||
) : ViewModel(){
|
||||
private val _testGroups = MutableStateFlow(TestGroupItem())
|
||||
val testGroups: StateFlow<TestGroupItem> = _testGroups.asStateFlow()
|
||||
|
||||
private val _testItems = MutableStateFlow(TestItemState())
|
||||
val testItems: StateFlow<TestItemState> = _testItems.asStateFlow()
|
||||
|
||||
init {
|
||||
loadTestGroups()
|
||||
}
|
||||
|
||||
fun loadTestGroups(){
|
||||
_testGroups.update {
|
||||
it.copy(
|
||||
isLoading = true
|
||||
)
|
||||
}
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val result = getTestGroupUseCase.invoke();
|
||||
_testGroups.update {
|
||||
it.copy(
|
||||
isLoading = false,
|
||||
testGroup = result,
|
||||
)
|
||||
}
|
||||
} catch (e:HttpException){
|
||||
handleError(e.message)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun getItemByGroupId(id:Int){
|
||||
_testItems.update { it.copy(isLoading = true) }
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val result = getTestItemByGroupId.invoke(id);
|
||||
_testItems.update {
|
||||
it.copy(
|
||||
isLoading = false,
|
||||
testItem = result
|
||||
)
|
||||
}
|
||||
} catch (e:HttpException){
|
||||
handleError(e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
private suspend fun handleError(message: String?) {
|
||||
_testGroups.update {
|
||||
it.copy(
|
||||
isLoading = false,
|
||||
testGroup = null,
|
||||
error = message
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class TestGroupItem(
|
||||
val isLoading: Boolean = false,
|
||||
val testGroup: Flow<List<TestGroup>>? = null,
|
||||
val error:String? = null
|
||||
)
|
||||
|
||||
data class TestItemState(
|
||||
val isLoading: Boolean = false,
|
||||
val testItem: Flow<List<TestItem>>? = null,
|
||||
val error:String? = null
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
agp = "8.13.0"
|
||||
kotlin = "2.2.10"
|
||||
kotlin = "2.0.21"
|
||||
coreKtx = "1.10.1"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
@@ -8,16 +8,16 @@ espressoCore = "3.5.1"
|
||||
lifecycleRuntimeKtx = "2.6.1"
|
||||
activityCompose = "1.8.0"
|
||||
composeBom = "2024.09.00"
|
||||
|
||||
retrofit = "3.0.0"
|
||||
okhttp = "5.1.0"
|
||||
ksp = "2.0.21-1.0.27"
|
||||
retrofit = "2.11.0"
|
||||
okhttp = "4.12.0"
|
||||
gson = "2.13.1"
|
||||
coil = "2.7.0"
|
||||
location = "21.3.0"
|
||||
koinAndroid = "4.1.0"
|
||||
koinAndroidxCompose = "4.1.0"
|
||||
lifecycleViewmodelKtx = "2.9.4"
|
||||
|
||||
room = "2.6.1"
|
||||
navigationCompose = "2.8.5"
|
||||
material3 = "1.4.0"
|
||||
|
||||
@@ -51,8 +51,14 @@ location-services = { group = "com.google.android.gms", name = "play-services-lo
|
||||
androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
|
||||
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
|
||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
||||
|
||||
|
||||
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
|
||||
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
|
||||
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
|
||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||
Reference in New Issue
Block a user