feat: seprate retrofit

This commit is contained in:
2026-05-17 08:23:57 +03:30
parent 28f0c868d5
commit 1e66246020
7 changed files with 107 additions and 12 deletions
@@ -0,0 +1,17 @@
package com.approagency.drug.data.remote
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.Query
interface DarooyabApiService {
@GET("Search")
@Headers(
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language: en-US,en;q=0.5"
)
suspend fun searchDrugs(
@Query("SearchText") searchText: String
): String // Returns raw HTML for the first page
}
@@ -28,14 +28,4 @@ interface DrugApiService {
@GET("drugs/goroh-darmani") @GET("drugs/goroh-darmani")
suspend fun getGorohDaroei(): DarmanModel suspend fun getGorohDaroei(): DarmanModel
@GET("Search")
@Headers(
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language: en-US,en;q=0.5"
)
suspend fun searchDrugs(
@Query("SearchText") searchText: String
): String // Returns raw HTML for the first page
} }
@@ -3,12 +3,20 @@ package com.approagency.drug.data.repository
import com.approagency.drug.data.dto.DarmanModel import com.approagency.drug.data.dto.DarmanModel
import com.approagency.drug.data.dto.DrugListResponse import com.approagency.drug.data.dto.DrugListResponse
import com.approagency.drug.data.dto.DrugModels import com.approagency.drug.data.dto.DrugModels
import com.approagency.drug.data.remote.DarooyabApiService
import com.approagency.drug.data.remote.DrugApiService import com.approagency.drug.data.remote.DrugApiService
import com.approagency.drug.data.remote.DrugHtmlParser
import com.approagency.drug.domain.model.DrugSearchParams import com.approagency.drug.domain.model.DrugSearchParams
import com.approagency.drug.domain.model.DrugSearchResult
import com.approagency.drug.domain.repository.DrugRepository import com.approagency.drug.domain.repository.DrugRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.IOException
class DrugRepositoryImpl( class DrugRepositoryImpl(
private val apiService: DrugApiService private val apiService: DrugApiService,
private val darooyabApiService: DarooyabApiService,
private val parser: DrugHtmlParser
): DrugRepository { ): DrugRepository {
override suspend fun searchDrug(params: DrugSearchParams): Result<DrugListResponse> { override suspend fun searchDrug(params: DrugSearchParams): Result<DrugListResponse> {
return try { return try {
@@ -36,4 +44,28 @@ class DrugRepositoryImpl(
Result.failure(e) Result.failure(e)
} }
} }
override suspend fun searchDrugs(params: DrugSearchParams): Result<List<DrugSearchResult>> {
return withContext(Dispatchers.IO) {
try {
// 1. Fetch raw HTML from the website
val htmlResponse = darooyabApiService.searchDrugs(params.query!!)
// 2. Parse the HTML to extract drug data
val drugList = parser.parseSearchResults(htmlResponse)
if (drugList.isNotEmpty()) {
Result.success(drugList)
} else {
Result.failure(Exception("No drugs found for query: '${params.query}'"))
}
} catch (e: IOException) {
// Network error
Result.failure(Exception("Network error: ${e.message}", e))
} catch (e: Exception) {
// Parsing or other error
Result.failure(Exception("An error occurred: ${e.message}", e))
}
}
}
} }
@@ -3,7 +3,9 @@ package com.approagency.drug.di
import android.app.Application import android.app.Application
import com.approagency.drug.data.local.database.LabDatabase import com.approagency.drug.data.local.database.LabDatabase
import com.approagency.drug.data.remote.DarooyabApiService
import com.approagency.drug.data.remote.DrugApiService import com.approagency.drug.data.remote.DrugApiService
import com.approagency.drug.data.remote.DrugHtmlParser
import com.approagency.drug.data.repository.DrugRepositoryImpl import com.approagency.drug.data.repository.DrugRepositoryImpl
import com.approagency.drug.data.repository.LabRepositoryImpl import com.approagency.drug.data.repository.LabRepositoryImpl
import com.approagency.drug.domain.repository.DrugRepository import com.approagency.drug.domain.repository.DrugRepository
@@ -12,15 +14,19 @@ import com.approagency.drug.domain.usecase.GetDrugDetailUseCase
import com.approagency.drug.domain.usecase.GetDrugSearchUseCase import com.approagency.drug.domain.usecase.GetDrugSearchUseCase
import com.approagency.drug.domain.usecase.GetTestGroupUseCase import com.approagency.drug.domain.usecase.GetTestGroupUseCase
import com.approagency.drug.domain.usecase.GetTestItemByGroupId import com.approagency.drug.domain.usecase.GetTestItemByGroupId
import com.approagency.drug.domain.usecase.SearchDrugsYabUseCase
import com.approagency.drug.domain.usecase.SearchTestsUseCase import com.approagency.drug.domain.usecase.SearchTestsUseCase
import com.approagency.drug.presentation.viewModel.HomeViewModel import com.approagency.drug.presentation.viewModel.HomeViewModel
import com.approagency.drug.presentation.viewModel.LabViewModel import com.approagency.drug.presentation.viewModel.LabViewModel
import com.approagency.drug.utils.Config import com.approagency.drug.utils.Config
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.core.module.dsl.viewModel import org.koin.core.module.dsl.viewModel
import org.koin.dsl.module import org.koin.dsl.module
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
val appModule= module { val appModule= module {
@@ -29,19 +35,47 @@ val appModule= module {
single { get<LabDatabase>().testGroupDao() } single { get<LabDatabase>().testGroupDao() }
single { get<LabDatabase>().testItemDao() } single { get<LabDatabase>().testItemDao() }
single {
OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BASIC
})
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
}
// ========== Retrofit for YOUR API ==========
single { single {
Retrofit.Builder() Retrofit.Builder()
.baseUrl(Config.BASE_URL) .baseUrl(Config.BASE_URL)
.client(get<OkHttpClient>())
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
.build() .build()
} }
single<DrugApiService> { single<DrugApiService> {
get<Retrofit>().create(DrugApiService::class.java) get<Retrofit>().create(DrugApiService::class.java)
} }
// ========== Retrofit for DAROOYAB Website API ==========
single {
Retrofit.Builder()
.baseUrl(Config.Darro_Url) // Darooyab base URL
.client(get<OkHttpClient>())
.addConverterFactory(GsonConverterFactory.create())
.build()
.let { retrofit ->
retrofit.create(DarooyabApiService::class.java)
}
}
factory { DrugHtmlParser() }
//repo //repo
single<DrugRepository> { single<DrugRepository> {
DrugRepositoryImpl(get()) DrugRepositoryImpl(get<DrugApiService>() , get<DarooyabApiService>() , get())
} }
@@ -52,6 +86,10 @@ val appModule= module {
} }
single {
SearchDrugsYabUseCase(get())
}
single{ single{
GetDrugDetailUseCase(get()) GetDrugDetailUseCase(get())
} }
@@ -4,9 +4,11 @@ import com.approagency.drug.data.dto.DarmanModel
import com.approagency.drug.data.dto.DrugListResponse import com.approagency.drug.data.dto.DrugListResponse
import com.approagency.drug.data.dto.DrugModels import com.approagency.drug.data.dto.DrugModels
import com.approagency.drug.domain.model.DrugSearchParams import com.approagency.drug.domain.model.DrugSearchParams
import com.approagency.drug.domain.model.DrugSearchResult
interface DrugRepository { interface DrugRepository {
suspend fun searchDrug(params: DrugSearchParams): Result<DrugListResponse> suspend fun searchDrug(params: DrugSearchParams): Result<DrugListResponse>
suspend fun drugDetail(cod:Int): Result<DrugModels> suspend fun drugDetail(cod:Int): Result<DrugModels>
suspend fun getGorohDaroei(): Result<DarmanModel> suspend fun getGorohDaroei(): Result<DarmanModel>
suspend fun searchDrugs(params:DrugSearchParams):Result<List<DrugSearchResult>>
} }
@@ -0,0 +1,15 @@
package com.approagency.drug.domain.usecase
import com.approagency.drug.data.repository.DrugRepositoryImpl
import com.approagency.drug.domain.model.DrugSearchParams
import com.approagency.drug.domain.model.DrugSearchResult
import com.approagency.drug.domain.repository.DrugRepository
class SearchDrugsYabUseCase (
private val repository: DrugRepository
) {
suspend operator fun invoke(query: String): Result<List<DrugSearchResult>> {
val params = DrugSearchParams(query = query)
return repository.searchDrugs(params)
}
}
@@ -2,4 +2,5 @@ package com.approagency.drug.utils
object Config { object Config {
const val BASE_URL = "https://drug.approagency.ir/api/" const val BASE_URL = "https://drug.approagency.ir/api/"
const val Darro_Url = "https://www.darooyab.ir/"
} }