feat: province move ti utils

This commit is contained in:
2026-06-05 00:19:16 +03:30
parent 8516405daf
commit 1ba6062c86
2 changed files with 155 additions and 147 deletions
@@ -8,12 +8,16 @@ import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.approagency.drug.domain.model.PharmacyItem import com.approagency.drug.domain.model.PharmacyItem
import com.approagency.drug.presentation.common.CustomBox
import com.approagency.drug.presentation.common.CustomModalBottomSheet import com.approagency.drug.presentation.common.CustomModalBottomSheet
import com.approagency.drug.presentation.viewModel.PharmacyState import com.approagency.drug.presentation.viewModel.PharmacyState
import com.approagency.drug.presentation.viewModel.PharmacyViewModel import com.approagency.drug.presentation.viewModel.PharmacyViewModel
import com.approagency.drug.utils.provinces
import com.vada.caller.ui.theme.LocalDime import com.vada.caller.ui.theme.LocalDime
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -27,45 +31,10 @@ fun PharmacyBottomSheet(
) { ) {
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val sheetState = rememberModalBottomSheetState( val sheetState = rememberModalBottomSheetState(
skipPartiallyExpanded = true, skipPartiallyExpanded = false,
confirmValueChange = { true } confirmValueChange = { true }
) )
// لیست استان‌ها (همان لیست HTML)
val provinces = listOf(
Province("0", "همه استان ها"),
Province("1", "اصفهان"),
Province("40", "تهران"),
Province("137", "آذربایجان شرقی"),
Province("138", "آذربایجان غربی"),
Province("139", "اردبیل"),
Province("140", "البرز"),
Province("141", "ایلام"),
Province("142", "بوشهر"),
Province("143", "چهارمحال و بختیاری"),
Province("144", "خراسان جنوبی"),
Province("145", "خراسان رضوی"),
Province("146", "خراسان شمالی"),
Province("147", "خوزستان"),
Province("148", "زنجان"),
Province("149", "سمنان"),
Province("150", "سیستان و بلوچستان"),
Province("151", "فارس"),
Province("152", "قزوین"),
Province("153", "قم"),
Province("154", "کردستان"),
Province("155", "کرمان"),
Province("156", "کرمانشاه"),
Province("157", "کهگیلویه و بویراحمد"),
Province("158", "گلستان"),
Province("159", "گیلان"),
Province("160", "لرستان"),
Province("161", "مازندران"),
Province("162", "مرکزی"),
Province("163", "هرمزگان"),
Province("164", "همدان"),
Province("165", "یزد")
)
var selectedProvinceId by remember { mutableStateOf("40") } // پیش‌فرض تهران var selectedProvinceId by remember { mutableStateOf("40") } // پیش‌فرض تهران
var showProvinceDropdown by remember { mutableStateOf(false) } var showProvinceDropdown by remember { mutableStateOf(false) }
@@ -85,137 +54,140 @@ fun PharmacyBottomSheet(
onDismiss = onDismiss, onDismiss = onDismiss,
scope = scope scope = scope
) { ) {
Column( CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
modifier = Modifier Column(
.fillMaxWidth() modifier = Modifier
.padding(16.dp), .fillMaxWidth()
verticalArrangement = Arrangement.spacedBy(16.dp) .padding(16.dp),
) { verticalArrangement = Arrangement.spacedBy(16.dp)
// عنوان
Text(
text = "جستجوی دارو در داروخانه‌ها",
fontWeight = FontWeight.Bold,
fontSize = MaterialTheme.typography.titleMedium.fontSize
)
// انتخاب استان
ExposedDropdownMenuBox(
expanded = showProvinceDropdown,
onExpandedChange = { showProvinceDropdown = it }
) { ) {
OutlinedTextField( // عنوان
value = provinces.find { it.id == selectedProvinceId }?.name ?: "انتخاب استان", Text(
onValueChange = {}, text = "جستجوی دارو در داروخانه‌ها",
readOnly = true, fontWeight = FontWeight.Bold,
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = showProvinceDropdown) }, fontSize = MaterialTheme.typography.titleMedium.fontSize
modifier = Modifier
.fillMaxWidth()
.menuAnchor(),
shape = MaterialTheme.shapes.small
) )
ExposedDropdownMenu( // انتخاب استان
ExposedDropdownMenuBox(
expanded = showProvinceDropdown, expanded = showProvinceDropdown,
onDismissRequest = { showProvinceDropdown = false } onExpandedChange = { showProvinceDropdown = it }
) { ) {
provinces.forEach { province -> OutlinedTextField(
DropdownMenuItem( value = provinces.find { it.id == selectedProvinceId }?.name
text = { Text(province.name) }, ?: "انتخاب استان",
onClick = { onValueChange = {},
selectedProvinceId = province.id readOnly = true,
showProvinceDropdown = false trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = showProvinceDropdown) },
// جستجو با استان جدید
viewModel.search(genericDrugId, province.id)
}
)
}
}
}
Spacer(modifier = Modifier.height(8.dp))
// نمایش نتایج
when (val state = pharmacyState) {
PharmacyState.Loading -> {
Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(200.dp), .menuAnchor(),
contentAlignment = Alignment.Center shape = MaterialTheme.shapes.large
)
ExposedDropdownMenu(
expanded = showProvinceDropdown,
onDismissRequest = { showProvinceDropdown = false }
) { ) {
Column(horizontalAlignment = Alignment.CenterHorizontally) { provinces.forEach { province ->
CircularProgressIndicator( DropdownMenuItem(
modifier = Modifier.size(32.dp) text = { Text(province.name) },
) onClick = {
Spacer(modifier = Modifier.height(8.dp)) selectedProvinceId = province.id
Text( showProvinceDropdown = false
text = "در حال جستجو...", // جستجو با استان جدید
fontSize = MaterialTheme.typography.bodySmall.fontSize viewModel.search(genericDrugId, province.id)
}
) )
} }
} }
} }
is PharmacyState.Success -> { Spacer(modifier = Modifier.height(8.dp))
if (state.items.isEmpty()) {
// نمایش نتایج
when (val state = pharmacyState) {
PharmacyState.Loading -> {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(200.dp), .height(200.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Text( Column(horizontalAlignment = Alignment.CenterHorizontally) {
text = "هیچ داروخانه‌ای یافت نشد", CircularProgressIndicator(
fontSize = MaterialTheme.typography.bodyMedium.fontSize, modifier = Modifier.size(32.dp)
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) )
) Spacer(modifier = Modifier.height(8.dp))
}
} else {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.heightIn(max = 400.dp)
) {
items(state.items) { pharmacy ->
PharmacyResultItem(pharmacy = pharmacy)
}
item {
Spacer(modifier = Modifier.height(16.dp))
Text( Text(
text = "تعداد کل: ${state.items.size} داروخانه", text = "در حال جستجو...",
fontSize = MaterialTheme.typography.bodySmall.fontSize, fontSize = MaterialTheme.typography.bodySmall.fontSize
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5f),
modifier = Modifier.padding(bottom = 8.dp)
) )
} }
} }
} }
}
is PharmacyState.Error -> { is PharmacyState.Success -> {
Box( if (state.items.isEmpty()) {
modifier = Modifier Box(
.fillMaxWidth() modifier = Modifier
.height(200.dp), .fillMaxWidth()
contentAlignment = Alignment.Center .height(200.dp),
) { contentAlignment = Alignment.Center
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = state.message,
color = MaterialTheme.colorScheme.error,
fontSize = MaterialTheme.typography.bodyMedium.fontSize
)
Spacer(modifier = Modifier.height(8.dp))
TextButton(
onClick = { viewModel.retry() }
) { ) {
Text("تلاش مجدد") Text(
text = "هیچ داروخانه‌ای یافت نشد",
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
)
}
} else {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.weight(1f),
) {
items(state.items) { pharmacy ->
PharmacyResultItem(pharmacy = pharmacy)
}
item {
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "تعداد کل: ${state.items.size} داروخانه",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5f),
modifier = Modifier.padding(bottom = 8.dp)
)
}
} }
} }
} }
}
PharmacyState.Idle -> {} is PharmacyState.Error -> {
Box(
modifier = Modifier
.fillMaxWidth()
.height(200.dp),
contentAlignment = Alignment.Center
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = state.message,
color = MaterialTheme.colorScheme.error,
fontSize = MaterialTheme.typography.bodyMedium.fontSize
)
Spacer(modifier = Modifier.height(8.dp))
TextButton(
onClick = { viewModel.retry() }
) {
Text("تلاش مجدد")
}
}
}
}
PharmacyState.Idle -> {}
}
} }
} }
} }
@@ -229,9 +201,8 @@ fun PharmacyResultItem(
) { ) {
val dime = LocalDime.current val dime = LocalDime.current
Card( CustomBox (
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
@@ -242,7 +213,7 @@ fun PharmacyResultItem(
// نام برند // نام برند
Text( Text(
text = pharmacy.brandName, text = pharmacy.brandName,
fontSize = MaterialTheme.typography.bodyMedium.fontSize, fontSize = MaterialTheme.typography.labelSmall.fontSize,
color = MaterialTheme.colorScheme.primary color = MaterialTheme.colorScheme.primary
) )
@@ -250,7 +221,7 @@ fun PharmacyResultItem(
Text( Text(
text = pharmacy.pharmacyName, text = pharmacy.pharmacyName,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = MaterialTheme.typography.bodyLarge.fontSize fontSize = MaterialTheme.typography.labelLarge.fontSize
) )
// موقعیت // موقعیت
@@ -261,9 +232,4 @@ fun PharmacyResultItem(
) )
} }
} }
} }
data class Province(
val id: String,
val name: String
)
@@ -0,0 +1,42 @@
package com.approagency.drug.utils
val provinces = listOf(
Province("0", "همه استان ها"),
Province("1", "اصفهان"),
Province("40", "تهران"),
Province("137", "آذربایجان شرقی"),
Province("138", "آذربایجان غربی"),
Province("139", "اردبیل"),
Province("140", "البرز"),
Province("141", "ایلام"),
Province("142", "بوشهر"),
Province("143", "چهارمحال و بختیاری"),
Province("144", "خراسان جنوبی"),
Province("145", "خراسان رضوی"),
Province("146", "خراسان شمالی"),
Province("147", "خوزستان"),
Province("148", "زنجان"),
Province("149", "سمنان"),
Province("150", "سیستان و بلوچستان"),
Province("151", "فارس"),
Province("152", "قزوین"),
Province("153", "قم"),
Province("154", "کردستان"),
Province("155", "کرمان"),
Province("156", "کرمانشاه"),
Province("157", "کهگیلویه و بویراحمد"),
Province("158", "گلستان"),
Province("159", "گیلان"),
Province("160", "لرستان"),
Province("161", "مازندران"),
Province("162", "مرکزی"),
Province("163", "هرمزگان"),
Province("164", "همدان"),
Province("165", "یزد")
)
data class Province(
val id: String,
val name: String
)