feat: add pharmacy detail
This commit is contained in:
@@ -7,6 +7,7 @@ import retrofit2.http.Headers
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import retrofit2.http.Url
|
||||
|
||||
interface DarooyabApiService {
|
||||
@FormUrlEncoded
|
||||
@@ -33,7 +34,16 @@ interface DarooyabApiService {
|
||||
@Path(value = "detailUrl", encoded = true) detailUrl: String
|
||||
): String
|
||||
|
||||
|
||||
@GET
|
||||
@Headers(
|
||||
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9",
|
||||
"Accept-Language: en-US,en;q=0.9,fa;q=0.8"
|
||||
)
|
||||
// @GET("{pharmacyPath}")
|
||||
suspend fun getPharmacyDetail(
|
||||
@Url url: String
|
||||
): String
|
||||
@POST("Home/partialPatientReferralList")
|
||||
@FormUrlEncoded
|
||||
@Headers(
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
// data/remote/PharmacyHtmlParser.kt
|
||||
package com.approagency.drug.data.remote
|
||||
|
||||
import com.approagency.drug.domain.model.PharmacyDetail
|
||||
import com.approagency.drug.domain.model.PharmacyItem
|
||||
import org.jsoup.Jsoup
|
||||
|
||||
object PharmacyHtmlParser {
|
||||
|
||||
// private const val BASE_URL = "https://www.darooyab.ir"
|
||||
|
||||
fun parse(html: String): List<PharmacyItem> {
|
||||
val items = mutableListOf<PharmacyItem>()
|
||||
val doc = Jsoup.parse(html)
|
||||
@@ -28,7 +32,7 @@ object PharmacyHtmlParser {
|
||||
val brandCell = cells[brandIndex]
|
||||
val brandLink = brandCell.select("a").first()
|
||||
val brandName = brandLink?.text()?.trim() ?: ""
|
||||
val brandUrl = brandLink?.attr("href")?.trim() ?: ""
|
||||
val brandUrl = normalizeUrl(brandLink?.attr("href")?.trim() ?: "")
|
||||
val brandId = extractIdFromUrl(brandUrl, "/B-(\\d+)/?")
|
||||
|
||||
// ستون داروخانه
|
||||
@@ -40,7 +44,10 @@ object PharmacyHtmlParser {
|
||||
!it.text().contains("اطلاعات تماس")
|
||||
}
|
||||
val pharmacyName = pharmacyLink?.text()?.trim() ?: ""
|
||||
val pharmacyUrl = pharmacyLink?.attr("href")?.trim() ?: ""
|
||||
var pharmacyUrl = pharmacyLink?.attr("href")?.trim() ?: ""
|
||||
|
||||
// نرمال کردن URL داروخانه
|
||||
pharmacyUrl = normalizeUrl(pharmacyUrl)
|
||||
val pharmacyId = extractIdFromUrl(pharmacyUrl, "/ph-(\\d+)/?")
|
||||
|
||||
// ستون موقعیت
|
||||
@@ -70,6 +77,37 @@ object PharmacyHtmlParser {
|
||||
return items
|
||||
}
|
||||
|
||||
/**
|
||||
* نرمال کردن URL: تبدیل مسیرهای نسبی به URL کامل
|
||||
* مثال: ~/../../../../../ph-12012/... -> https://www.darooyab.ir/ph-12012/...
|
||||
*/
|
||||
private fun normalizeUrl(url: String): String {
|
||||
if (url.isBlank()) return ""
|
||||
|
||||
// اگر absolute بود domain را حذف کن
|
||||
if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||
return url
|
||||
.replace("https://www.darooyab.ir", "")
|
||||
.replace("http://www.darooyab.ir", "")
|
||||
}
|
||||
|
||||
var cleanUrl = url
|
||||
|
||||
if (cleanUrl.startsWith("~/")) {
|
||||
cleanUrl = cleanUrl.removePrefix("~/")
|
||||
}
|
||||
|
||||
while (cleanUrl.startsWith("../")) {
|
||||
cleanUrl = cleanUrl.removePrefix("../")
|
||||
}
|
||||
|
||||
return if (cleanUrl.startsWith("/")) {
|
||||
cleanUrl
|
||||
} else {
|
||||
"/$cleanUrl"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* تشخیص وجود ستون تضمین موجودی با بررسی سربرگ جدول
|
||||
*/
|
||||
@@ -100,4 +138,29 @@ object PharmacyHtmlParser {
|
||||
val regex = pattern.toRegex()
|
||||
return regex.find(url)?.groupValues?.get(1) ?: ""
|
||||
}
|
||||
|
||||
fun parsePharmacyDetail(html: String): PharmacyDetail {
|
||||
val doc = Jsoup.parse(html)
|
||||
|
||||
// استخراج نام داروخانه
|
||||
val pharmacyTitle = doc.select("h2#pharmacyTitle").first()?.text()?.trim() ?: ""
|
||||
|
||||
// استخراج آدرس
|
||||
val addressElement = doc.select("h2#h2Address").first()
|
||||
val address = addressElement?.text()?.trim() ?: ""
|
||||
|
||||
// استخراج تلفن
|
||||
val phoneElement = doc.select("h3#h3Phone a").first()
|
||||
val phone = phoneElement?.text()?.trim() ?: ""
|
||||
|
||||
// استخراج دانشگاه (اختیاری)
|
||||
val university = doc.select("div.alert.alert-success > span").first()?.text()?.trim()
|
||||
|
||||
return PharmacyDetail(
|
||||
name = pharmacyTitle,
|
||||
address = address,
|
||||
phone = phone,
|
||||
university = university
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import com.approagency.drug.domain.model.DaroYabSearchResult
|
||||
import com.approagency.drug.domain.model.DrugDetail
|
||||
import com.approagency.drug.domain.model.DrugSearchParams
|
||||
import com.approagency.drug.domain.model.DrugSearchResult
|
||||
import com.approagency.drug.domain.model.PharmacyDetail
|
||||
import com.approagency.drug.domain.model.PharmacyItem
|
||||
import com.approagency.drug.domain.repository.DrugRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -110,4 +111,15 @@ class DrugRepositoryImpl(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPharmacyDetail(pharmacyUrl: String): PharmacyDetail {
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val html = darooyabApiService.getPharmacyDetail(pharmacyUrl)
|
||||
PharmacyHtmlParser.parsePharmacyDetail(html)
|
||||
} catch (e: Exception) {
|
||||
PharmacyDetail("", "", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ 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.GetPharmaciesUseCase
|
||||
import com.approagency.drug.domain.usecase.GetPharmacyDetailUseCase
|
||||
import com.approagency.drug.domain.usecase.GetTestGroupUseCase
|
||||
import com.approagency.drug.domain.usecase.GetTestItemByGroupId
|
||||
import com.approagency.drug.domain.usecase.SearchDrugsYabUseCase
|
||||
@@ -135,6 +136,10 @@ val appModule= module {
|
||||
DrugDetailYabUseCase(get())
|
||||
}
|
||||
|
||||
single {
|
||||
GetPharmacyDetailUseCase(get())
|
||||
}
|
||||
|
||||
viewModel {
|
||||
DrugDetailViewModel(get())
|
||||
}
|
||||
@@ -149,7 +154,7 @@ val appModule= module {
|
||||
SearchViewModel(get())
|
||||
}
|
||||
viewModel {
|
||||
PharmacyViewModel(get())
|
||||
PharmacyViewModel(get() , get ())
|
||||
}
|
||||
|
||||
viewModel {
|
||||
|
||||
@@ -17,5 +17,15 @@ data class PharmacyItem(
|
||||
val pharmacyId: String, // ID داروخانه
|
||||
|
||||
val province: String, // نام استان
|
||||
val city: String // نام شهر
|
||||
val city: String , // نام شهر
|
||||
val address: String? = null,
|
||||
val phone: String? = null
|
||||
)
|
||||
|
||||
// مدل برای اطلاعات کامل داروخانه
|
||||
data class PharmacyDetail(
|
||||
val name: String,
|
||||
val address: String,
|
||||
val phone: String,
|
||||
val university: String? = null
|
||||
)
|
||||
@@ -8,6 +8,7 @@ import com.approagency.drug.domain.model.DaroYabSearchResult
|
||||
import com.approagency.drug.domain.model.DrugDetail
|
||||
import com.approagency.drug.domain.model.DrugSearchParams
|
||||
import com.approagency.drug.domain.model.DrugSearchResult
|
||||
import com.approagency.drug.domain.model.PharmacyDetail
|
||||
import com.approagency.drug.domain.model.PharmacyItem
|
||||
|
||||
interface DrugRepository {
|
||||
@@ -18,4 +19,6 @@ interface DrugRepository {
|
||||
suspend fun getDrugDetailFromYab(detailUrl: String):Result<DrugDetail>
|
||||
suspend fun searchPharmacies(genericDrugId: String,provId: String): List<PharmacyItem>
|
||||
|
||||
suspend fun getPharmacyDetail(pharmacyUrl: String): PharmacyDetail
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.approagency.drug.domain.usecase
|
||||
|
||||
import com.approagency.drug.domain.model.PharmacyDetail
|
||||
import com.approagency.drug.domain.repository.DrugRepository
|
||||
|
||||
class GetPharmacyDetailUseCase(
|
||||
private val repository: DrugRepository
|
||||
) {
|
||||
suspend operator fun invoke(pharmacyUrl: String): PharmacyDetail {
|
||||
return repository.getPharmacyDetail(pharmacyUrl)
|
||||
}
|
||||
}
|
||||
+140
-30
@@ -3,8 +3,12 @@ package com.approagency.drug.presentation.components
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.LocationOn
|
||||
import androidx.compose.material.icons.filled.Phone
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -14,10 +18,12 @@ import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
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.Loading
|
||||
import com.approagency.drug.presentation.viewModel.PharmacyDetailState
|
||||
import com.approagency.drug.presentation.viewModel.PharmacyState
|
||||
import com.approagency.drug.presentation.viewModel.PharmacyViewModel
|
||||
import com.approagency.drug.utils.provinces
|
||||
@@ -29,16 +35,11 @@ import kotlinx.coroutines.launch
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun PharmacyBottomSheet(
|
||||
viewModel: PharmacyViewModel,
|
||||
genericDrugId: String,
|
||||
isOpen: Boolean,
|
||||
onDismiss: () -> Unit
|
||||
viewModel: PharmacyViewModel, genericDrugId: String, isOpen: Boolean, onDismiss: () -> Unit
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val sheetState = rememberModalBottomSheetState(
|
||||
skipPartiallyExpanded = false,
|
||||
confirmValueChange = { true }
|
||||
)
|
||||
skipPartiallyExpanded = false, confirmValueChange = { true })
|
||||
|
||||
|
||||
var selectedProvinceId by remember { mutableStateOf("40") } // پیشفرض تهران
|
||||
@@ -55,14 +56,14 @@ fun PharmacyBottomSheet(
|
||||
|
||||
if (isOpen) {
|
||||
CustomModalBottomSheet(
|
||||
sheetState = sheetState,
|
||||
onDismiss = onDismiss,
|
||||
scope = scope
|
||||
sheetState = sheetState, onDismiss = onDismiss, scope = scope
|
||||
) {
|
||||
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxHeight()
|
||||
.fillMaxWidth().heightIn(min = 400.dp)
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 400.dp)
|
||||
.padding(MaterialTheme.dime.md),
|
||||
verticalArrangement = Arrangement.spacedBy(MaterialTheme.dime.xl)
|
||||
) {
|
||||
@@ -78,8 +79,7 @@ fun PharmacyBottomSheet(
|
||||
item {
|
||||
ExposedDropdownMenuBox(
|
||||
expanded = showProvinceDropdown,
|
||||
onExpandedChange = { showProvinceDropdown = it }
|
||||
) {
|
||||
onExpandedChange = { showProvinceDropdown = it }) {
|
||||
OutlinedTextField(
|
||||
value = provinces.find { it.id == selectedProvinceId }?.name
|
||||
?: "انتخاب استان",
|
||||
@@ -94,18 +94,14 @@ fun PharmacyBottomSheet(
|
||||
|
||||
ExposedDropdownMenu(
|
||||
expanded = showProvinceDropdown,
|
||||
onDismissRequest = { showProvinceDropdown = false }
|
||||
) {
|
||||
onDismissRequest = { showProvinceDropdown = false }) {
|
||||
provinces.forEach { province ->
|
||||
DropdownMenuItem(
|
||||
text = { Text(province.name) },
|
||||
onClick = {
|
||||
DropdownMenuItem(text = { Text(province.name) }, onClick = {
|
||||
selectedProvinceId = province.id
|
||||
showProvinceDropdown = false
|
||||
// جستجو با استان جدید
|
||||
viewModel.search(genericDrugId, province.id)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,8 +109,6 @@ fun PharmacyBottomSheet(
|
||||
// انتخاب استان
|
||||
|
||||
|
||||
|
||||
|
||||
// نمایش نتایج
|
||||
when (val state = pharmacyState) {
|
||||
PharmacyState.Loading -> {
|
||||
@@ -156,9 +150,8 @@ fun PharmacyBottomSheet(
|
||||
}
|
||||
|
||||
} else {
|
||||
items(state.items)
|
||||
{ pharmacy ->
|
||||
PharmacyResultItem(pharmacy = pharmacy)
|
||||
items(state.items) { pharmacy ->
|
||||
PharmacyResultItem(pharmacy = pharmacy, viewModel)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(MaterialTheme.dime.md))
|
||||
@@ -199,8 +192,7 @@ fun PharmacyBottomSheet(
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
TextButton(
|
||||
onClick = { viewModel.retry() }
|
||||
) {
|
||||
onClick = { viewModel.retry() }) {
|
||||
Text("تلاش مجدد")
|
||||
}
|
||||
}
|
||||
@@ -219,11 +211,30 @@ fun PharmacyBottomSheet(
|
||||
|
||||
@Composable
|
||||
fun PharmacyResultItem(
|
||||
pharmacy: PharmacyItem,
|
||||
modifier: Modifier = Modifier
|
||||
pharmacy: PharmacyItem, viewModel: PharmacyViewModel, modifier: Modifier = Modifier
|
||||
) {
|
||||
val dime = LocalDime.current
|
||||
var showDetails by remember { mutableStateOf(false) }
|
||||
// گرفتن State مخصوص این داروخانه از Map
|
||||
val detailStates by viewModel.pharmacyDetailStates.collectAsState()
|
||||
val detailState = detailStates[pharmacy.pharmacyUrl] ?: PharmacyDetailState.Idle
|
||||
|
||||
// Reset detail state when item changes
|
||||
LaunchedEffect(pharmacy.pharmacyUrl) {
|
||||
println(pharmacy.pharmacyUrl)
|
||||
showDetails = false
|
||||
}
|
||||
|
||||
// Load detail when expanded
|
||||
LaunchedEffect(showDetails) {
|
||||
if (showDetails) {
|
||||
// فقط اگر Idle هست (هنوز لود نشده) درخواست بده
|
||||
if (detailState is PharmacyDetailState.Idle) {
|
||||
println(pharmacy.pharmacyUrl)
|
||||
viewModel.loadPharmacyDetail(pharmacy.pharmacyUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
CustomBox(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
) {
|
||||
@@ -248,11 +259,110 @@ fun PharmacyResultItem(
|
||||
)
|
||||
|
||||
// موقعیت
|
||||
// موقعیت و دکمه اطلاعات تماس
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(
|
||||
text = "${pharmacy.province} - ${pharmacy.city}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
|
||||
)
|
||||
|
||||
TextButton(
|
||||
onClick = { showDetails = !showDetails }) {
|
||||
Text(
|
||||
text = if (showDetails) "بستن" else "اطلاعات تماس",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize
|
||||
)
|
||||
}
|
||||
}
|
||||
if (showDetails) {
|
||||
Divider(modifier = Modifier.padding(vertical = 4.dp))
|
||||
|
||||
when (detailState) {
|
||||
is PharmacyDetailState.Loading -> {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
CircularProgressIndicator(modifier = Modifier.size(24.dp))
|
||||
}
|
||||
}
|
||||
|
||||
is PharmacyDetailState.Success -> {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
// آدرس
|
||||
Row(
|
||||
verticalAlignment = Alignment.Top,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.LocationOn,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Text(
|
||||
text = detailState.detail.address,
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = 18.sp
|
||||
)
|
||||
}
|
||||
|
||||
// تلفن
|
||||
if (detailState.detail.phone.isNotBlank()) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Phone,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Text(
|
||||
text = detailState.detail.phone,
|
||||
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// هشدار (اطلاعات از HTML)
|
||||
Text(
|
||||
text = "⚠️ دریافت دارو فقط با نسخه کامل و بصورت حضوری در محل داروخانه امکان پذیر است",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier.padding(top = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is PharmacyDetailState.Error -> {
|
||||
Text(
|
||||
text = "خطا در دریافت اطلاعات تماس",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
color = MaterialTheme.colorScheme.error
|
||||
)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Text(
|
||||
text = "${pharmacy.pharmacyUrl}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,20 @@ package com.approagency.drug.presentation.viewModel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.approagency.drug.domain.model.PharmacyDetail
|
||||
import com.approagency.drug.domain.model.PharmacyItem
|
||||
import com.approagency.drug.domain.usecase.GetPharmaciesUseCase
|
||||
import com.approagency.drug.domain.usecase.GetPharmacyDetailUseCase
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
sealed class PharmacyDetailState {
|
||||
object Idle : PharmacyDetailState()
|
||||
object Loading : PharmacyDetailState()
|
||||
data class Success(val detail: PharmacyDetail) : PharmacyDetailState()
|
||||
data class Error(val message: String) : PharmacyDetailState()
|
||||
}
|
||||
sealed class PharmacyState {
|
||||
object Idle : PharmacyState()
|
||||
object Loading : PharmacyState()
|
||||
@@ -18,15 +25,48 @@ sealed class PharmacyState {
|
||||
}
|
||||
|
||||
class PharmacyViewModel(
|
||||
private val getPharmaciesUseCase: GetPharmaciesUseCase
|
||||
private val getPharmaciesUseCase: GetPharmaciesUseCase,
|
||||
private val getPharmacyDetailUseCase: GetPharmacyDetailUseCase
|
||||
) : ViewModel() {
|
||||
|
||||
private val _state = MutableStateFlow<PharmacyState>(PharmacyState.Idle)
|
||||
val state: StateFlow<PharmacyState> = _state.asStateFlow()
|
||||
|
||||
|
||||
// استفاده از Map برای نگهداری State هر داروخانه به صورت جداگانه
|
||||
private val _pharmacyDetailStates = MutableStateFlow<Map<String, PharmacyDetailState>>(emptyMap())
|
||||
val pharmacyDetailStates: StateFlow<Map<String, PharmacyDetailState>> = _pharmacyDetailStates.asStateFlow()
|
||||
|
||||
private var currentGenericDrugId: String = ""
|
||||
private var currentProvinceId: String = "0"
|
||||
|
||||
fun loadPharmacyDetail(pharmacyUrl: String) {
|
||||
// اگر در حال حاضر لود میشود یا موفقیت آمیز بوده، دوباره درخواست نده
|
||||
val currentState = _pharmacyDetailStates.value[pharmacyUrl]
|
||||
if (currentState is PharmacyDetailState.Loading || currentState is PharmacyDetailState.Success) {
|
||||
return
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
// تنظیم Loading برای این داروخانه خاص
|
||||
_pharmacyDetailStates.value = _pharmacyDetailStates.value.toMutableMap().apply {
|
||||
put(pharmacyUrl, PharmacyDetailState.Loading)
|
||||
}
|
||||
|
||||
try {
|
||||
val detail = getPharmacyDetailUseCase(pharmacyUrl)
|
||||
_pharmacyDetailStates.value = _pharmacyDetailStates.value.toMutableMap().apply {
|
||||
put(pharmacyUrl, PharmacyDetailState.Success(detail))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
_pharmacyDetailStates.value = _pharmacyDetailStates.value.toMutableMap().apply {
|
||||
put(pharmacyUrl, PharmacyDetailState.Error(e.message ?: "خطا در دریافت اطلاعات"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun search(genericDrugId: String, provinceId: String) {
|
||||
if (genericDrugId.isBlank()) return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user