feat: initial project

This commit is contained in:
2026-02-27 00:32:29 +03:30
commit ce86dc27ea
47 changed files with 1252 additions and 0 deletions
@@ -0,0 +1,47 @@
package com.approagency.drug
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.approagency.drug.ui.theme.DrugTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
DrugTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
DrugTheme {
Greeting("Android")
}
}
@@ -0,0 +1,74 @@
package com.approagency.drug.data.dto
data class DrugModels(
val success: Boolean,
val message: String?,
val data: DrugDetail?,
val meta: Meta?
)
data class DrugDetail(
val cod: Int?,
val goroh_darmani_detail_cod: Int?,
val goroh_daroei_cod: Int?,
val goroh_farmakologic_cod: Int?,
val goroh_darmani_cod: Int?,
val nam_fa: String?,
val nam_en: String?,
val mavaredmasraf: String?,
val meghdarmasraf: String?,
val masrafdarhamelegi: String?,
val masrafdarshirdehi: String?,
val manemasraf: String?,
val avarez: String?,
val tadakhol: String?,
val mekanismtasir: String?,
val nokte: String?,
val hoshdar: String?,
val sharayetnegahdari: String?,
val ashkal_daroei: String?,
val created_at: String?,
val updated_at: String?,
val goroh_daroei: GorohDaroei?,
val goroh_darmani: GorohDarmani?,
val goroh_darmani_detail: GorohDarmaniDetail?
)
data class GorohDaroei(
val cod: Int?,
val nam: String?,
val created_at: String?,
val updated_at: String?
)
data class GorohDarmani(
val cod: Int?,
val nam_fa: String?,
val nam_en: String?,
val giyahi_ya_shimiyaei: String?,
val image: String?,
val created_at: String?,
val updated_at: String?
)
data class GorohDarmaniDetail(
val cod: Int?,
val nam: String?,
val created_at: String?,
val updated_at: String?
)
data class Meta(
val current_page: Int?,
val last_page: Int?,
val per_page: Int?,
val total: Int?
)
// For list response compatibility
data class DrugListResponse(
val success: Boolean,
val message: String?,
val data: List<DrugDetail> = emptyList(),
val meta: Meta?
)
@@ -0,0 +1,24 @@
package com.approagency.drug.data.remote
import com.approagency.drug.data.dto.DrugListResponse
import com.approagency.drug.data.dto.DrugModels
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query
interface DrugApiService {
@GET("/drugs/search")
suspend fun getDrugs(
@Query("q")query: String?,
@Query("per_page")perPage:Int? = 20,
@Query("with_relations")withRelations: Boolean? =true,
@Query("goroh_daroei_cod")drugGroup:Int?,
@Query("goroh_darmani_cod")healGroup:Int?,
): DrugListResponse
@GET("/drugs/{cod}")
suspend fun getDrugDetail(
@Path("cod") cod: Int
): DrugModels
}
@@ -0,0 +1,19 @@
package com.approagency.drug.data.repository
import com.approagency.drug.data.dto.DrugListResponse
import com.approagency.drug.data.remote.DrugApiService
import com.approagency.drug.domain.model.DrugSearchParams
import com.approagency.drug.domain.repository.DrugRepository
class DrugRepositoryImpl(
private val apiService: DrugApiService
): DrugRepository {
override suspend fun searchDrug(params: DrugSearchParams): Result<DrugListResponse> {
return try {
val response = apiService.getDrugs(query = params.query , perPage = params.perPage , withRelations = params.withRelations , healGroup = params.healGroup , drugGroup = params.drugGroup )
return Result.success(response)
}catch (e: Exception){
Result.failure(e)
}
}
}
@@ -0,0 +1,33 @@
package com.approagency.drug.di
import com.approagency.drug.data.repository.DrugRepositoryImpl
import com.approagency.drug.domain.repository.DrugRepository
import com.approagency.drug.domain.usecase.GetDrugSearchUseCase
import com.approagency.drug.utils.Config
import org.koin.dsl.module
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
val appModule= module {
single {
Retrofit.Builder()
.baseUrl(Config.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
//repo
single<DrugRepository> {
DrugRepositoryImpl(get())
}
//UseCase
single {
GetDrugSearchUseCase(get())
}
//
}
@@ -0,0 +1,9 @@
package com.approagency.drug.domain.model
data class DrugSearchParams(
val query: String? = null,
val perPage: Int = 20,
val withRelations: Boolean = true,
val drugGroup: Int? = null,
val healGroup: Int? = null,
)
@@ -0,0 +1,8 @@
package com.approagency.drug.domain.repository
import com.approagency.drug.data.dto.DrugListResponse
import com.approagency.drug.domain.model.DrugSearchParams
interface DrugRepository {
suspend fun searchDrug(params: DrugSearchParams): Result<DrugListResponse>
}
@@ -0,0 +1,13 @@
package com.approagency.drug.domain.usecase
import com.approagency.drug.data.dto.DrugListResponse
import com.approagency.drug.domain.model.DrugSearchParams
import com.approagency.drug.domain.repository.DrugRepository
class GetDrugSearchUseCase (
private val repository: DrugRepository
){
suspend operator fun invoke(params: DrugSearchParams): Result<DrugListResponse> {
return repository.searchDrug(params)
}
}
@@ -0,0 +1,11 @@
package com.approagency.drug.presentation.screens
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun HomeScreen(
modifier: Modifier,
view
)
@@ -0,0 +1,11 @@
package com.approagency.drug.ui.theme
import androidx.compose.ui.graphics.Color
val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)
val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
@@ -0,0 +1,58 @@
package com.approagency.drug.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable
fun DrugTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
@@ -0,0 +1,34 @@
package com.approagency.drug.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
/* Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)
@@ -0,0 +1,5 @@
package com.approagency.drug.utils
object Config {
const val BASE_URL = "https://drug.approagency.ir/api"
}