diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index f851d74..eecd9ed 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,15 +1,18 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
+ id("kotlin-kapt")
+ alias(libs.plugins.hilt.android)
+ id("org.jlleitschuh.gradle.ktlint") version "11.6.1"
}
android {
namespace = "kr.ac.anu.mumu"
- compileSdk = 35
+ compileSdk = 36
defaultConfig {
applicationId = "kr.ac.anu.mumu"
- minSdk = 24
+ minSdk = 26
targetSdk = 35
versionCode = 1
versionName = "1.0"
@@ -33,6 +36,9 @@ android {
kotlinOptions {
jvmTarget = "11"
}
+ buildFeatures {
+ viewBinding = true
+ }
}
dependencies {
@@ -45,4 +51,23 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
-}
\ No newline at end of file
+
+ // Retrofit & GSON
+ implementation(libs.retrofit2)
+ implementation(libs.converter.gson)
+
+ // Hilt
+ implementation(libs.hilt.android)
+ kapt(libs.hilt.android.compiler)
+
+ // Coroutines
+ implementation(libs.kotlinx.coroutines.android)
+
+ // ViewModel & LifeCycle
+ implementation(libs.androidx.lifecycle.viewmodel.ktx)
+ implementation(libs.androidx.lifecycle.runtime.ktx)
+
+ // UI 확장
+ implementation(libs.androidx.activity.ktx)
+ implementation(libs.androidx.fragment.ktx)
+}
diff --git a/app/src/androidTest/java/kr/ac/anu/mumu/ExampleInstrumentedTest.kt b/app/src/androidTest/java/kr/ac/anu/mumu/ExampleInstrumentedTest.kt
index 6ba8b6f..2857e90 100644
--- a/app/src/androidTest/java/kr/ac/anu/mumu/ExampleInstrumentedTest.kt
+++ b/app/src/androidTest/java/kr/ac/anu/mumu/ExampleInstrumentedTest.kt
@@ -1,13 +1,11 @@
package kr.ac.anu.mumu
-import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
-
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.Assert.*
-
/**
* Instrumented test, which will execute on an Android device.
*
@@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("kr.ac.anu.mumu", appContext.packageName)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b224e33..f0aaafd 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,7 +2,11 @@
+
+
@@ -21,6 +25,10 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt b/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt
new file mode 100644
index 0000000..5eceb62
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt
@@ -0,0 +1,7 @@
+package kr.ac.anu.mumu
+
+import android.app.Application
+import dagger.hilt.android.HiltAndroidApp
+
+@HiltAndroidApp
+class MumuApplication : Application()
diff --git a/app/src/main/java/kr/ac/anu/mumu/data/datasource/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/data/datasource/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt b/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt
new file mode 100644
index 0000000..8c3d418
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt
@@ -0,0 +1,12 @@
+package kr.ac.anu.mumu.data.datasource
+
+import kr.ac.anu.mumu.data.model.LoginRequest
+import kr.ac.anu.mumu.data.model.LoginResponse
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.POST
+
+interface AuthService {
+ @POST("/api/users/login")
+ suspend fun login(@Body request: LoginRequest): Response
+}
diff --git a/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt b/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt
new file mode 100644
index 0000000..01e8b01
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt
@@ -0,0 +1,28 @@
+package kr.ac.anu.mumu.data.model
+
+import com.google.gson.annotations.SerializedName
+
+data class LoginRequest(
+ @SerializedName("id")
+ val id: String,
+ @SerializedName("password")
+ val pw: String
+)
+
+data class LoginResponse(
+ val success: Boolean,
+ val message: String,
+ val token: String,
+ val user: UserDto
+)
+
+data class UserDto(
+ @SerializedName("user_id")
+ val userId: Int,
+ val id: String,
+ val name: String,
+ val phone: String?,
+ @SerializedName("profile_image")
+ val profileImage: String?,
+ val role: String
+)
diff --git a/app/src/main/java/kr/ac/anu/mumu/data/repository/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/data/repository/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt b/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt
new file mode 100644
index 0000000..27749cc
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt
@@ -0,0 +1,38 @@
+package kr.ac.anu.mumu.data.repository
+
+import kr.ac.anu.mumu.data.datasource.AuthService
+import kr.ac.anu.mumu.data.model.LoginRequest
+import kr.ac.anu.mumu.domain.model.User
+import kr.ac.anu.mumu.domain.repository.LoginRepository
+import javax.inject.Inject
+
+class LoginRepositoryImpl @Inject constructor(
+ private val authService: AuthService
+) : LoginRepository {
+
+ override suspend fun login(id: String, pw: String): Result {
+ return try {
+ val response = authService.login(LoginRequest(id, pw))
+
+ if (response.isSuccessful && response.body() != null) {
+ val result = response.body()!!
+
+ if (result.success) {
+ val domainUser = User(
+ name = result.user.name,
+ token = result.token,
+ profileImage = result.user.profileImage,
+ role = result.user.role
+ )
+ Result.success(domainUser)
+ } else {
+ Result.failure(Exception(result.message))
+ }
+ } else {
+ Result.failure(Exception("통신 오류 : ${response.code()}"))
+ }
+ } catch (e: Exception) {
+ Result.failure(e)
+ }
+ }
+}
diff --git a/app/src/main/java/kr/ac/anu/mumu/di/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/di/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt b/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt
new file mode 100644
index 0000000..f0cdb98
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt
@@ -0,0 +1,29 @@
+package kr.ac.anu.mumu.di
+
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import kr.ac.anu.mumu.data.datasource.AuthService
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+object NetworkModule {
+ @Provides
+ @Singleton
+ fun provideRetrofit(): Retrofit {
+ return Retrofit.Builder()
+ .baseUrl("https://keagan-slipperier-bewilderedly.ngrok-free.dev") // 서버 주소
+ .addConverterFactory(GsonConverterFactory.create())
+ .build()
+ }
+
+ @Provides
+ @Singleton
+ fun provideAuthService(retrofit: Retrofit): AuthService {
+ return retrofit.create(AuthService::class.java)
+ }
+}
diff --git a/app/src/main/java/kr/ac/anu/mumu/di/RepositoryModule.kt b/app/src/main/java/kr/ac/anu/mumu/di/RepositoryModule.kt
new file mode 100644
index 0000000..3e12006
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/di/RepositoryModule.kt
@@ -0,0 +1,19 @@
+package kr.ac.anu.mumu.di
+
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import kr.ac.anu.mumu.data.repository.LoginRepositoryImpl
+import kr.ac.anu.mumu.domain.repository.LoginRepository
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+abstract class RepositoryModule {
+ @Binds
+ @Singleton
+ abstract fun bindLoginRepository(
+ loginRepositoryImpl: LoginRepositoryImpl
+ ): LoginRepository
+}
diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/model/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/domain/model/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt b/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt
new file mode 100644
index 0000000..8056a13
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt
@@ -0,0 +1,8 @@
+package kr.ac.anu.mumu.domain.model
+
+data class User(
+ val name: String,
+ val token: String,
+ val profileImage: String?,
+ val role: String
+)
diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/repository/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/domain/repository/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt b/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt
new file mode 100644
index 0000000..de31e19
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt
@@ -0,0 +1,7 @@
+package kr.ac.anu.mumu.domain.repository
+
+import kr.ac.anu.mumu.domain.model.User
+
+interface LoginRepository {
+ suspend fun login(id: String, pw: String): Result
+}
diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/usecase/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt
new file mode 100644
index 0000000..051a3d6
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt
@@ -0,0 +1,13 @@
+package kr.ac.anu.mumu.domain.usecase
+
+import kr.ac.anu.mumu.domain.model.User
+import kr.ac.anu.mumu.domain.repository.LoginRepository
+import javax.inject.Inject
+
+class LoginUseCase @Inject constructor(
+ private val repository: LoginRepository
+) {
+ suspend operator fun invoke(id: String, pw: String): Result {
+ return repository.login(id, pw)
+ }
+}
diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt
new file mode 100644
index 0000000..5856b43
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt
@@ -0,0 +1,127 @@
+package kr.ac.anu.mumu.presentation.login
+
+import android.content.Intent
+import android.os.Bundle
+import android.text.Editable
+import android.text.Spannable
+import android.text.SpannableStringBuilder
+import android.text.TextWatcher
+import android.text.style.ForegroundColorSpan
+import android.util.Log
+import android.view.View
+import androidx.activity.enableEdgeToEdge
+import androidx.activity.viewModels
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.launch
+import kr.ac.anu.mumu.R
+import kr.ac.anu.mumu.databinding.ActivityLoginBinding
+import kr.ac.anu.mumu.presentation.main.MainActivity
+
+@AndroidEntryPoint
+class LoginActivity : AppCompatActivity() {
+
+ private lateinit var binding: ActivityLoginBinding
+ private val viewModel: LoginViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ binding = ActivityLoginBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
+ val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
+ insets
+ }
+
+ viewSet()
+
+ initInputListener()
+ initObserver()
+ }
+
+ private fun viewSet() {
+ val originText = binding.tvTitle.text.toString()
+ val spannable = SpannableStringBuilder(originText)
+
+ val targetWord = "Mumu"
+ val start = originText.indexOf(targetWord)
+ val end = start + targetWord.length
+
+ if (start != -1) {
+ val color = ContextCompat.getColor(this, R.color.mumumint_300)
+
+ spannable.setSpan(
+ ForegroundColorSpan(color),
+ start,
+ end,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ }
+
+ binding.tvTitle.text = spannable
+ }
+
+ private fun initInputListener() {
+ val textWatcher = object : TextWatcher {
+ override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
+ override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
+
+ override fun afterTextChanged(p0: Editable?) {
+ val id = binding.etId.text.toString()
+ val pw = binding.etPw.text.toString()
+
+ binding.btnLogin.isEnabled = id.isNotEmpty() && pw.isNotEmpty()
+
+ binding.tvError.visibility = View.GONE
+ }
+ }
+
+ binding.etId.addTextChangedListener(textWatcher)
+ binding.etPw.addTextChangedListener(textWatcher)
+
+ // 버튼 클릭 시 로그인 요청
+ binding.btnLogin.setOnClickListener {
+ val id = binding.etId.text.toString()
+ val pw = binding.etPw.text.toString()
+
+ viewModel.login(id, pw)
+ }
+ }
+
+ // 로그인 결과 -> UI 업데이트
+ private fun initObserver() {
+ lifecycleScope.launch {
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
+ viewModel.uiState.collect { state ->
+ when (state) {
+ is LoginUiState.Loading -> {
+ // 로딩 상태 처리
+ binding.btnLogin.isEnabled = false
+ }
+ is LoginUiState.Success -> {
+ // 로그인 성공 처리
+ val intent = Intent(this@LoginActivity, MainActivity::class.java)
+ startActivity(intent)
+ finish()
+ }
+ is LoginUiState.Error -> {
+ // 로그인 실패 처리
+ binding.tvError.visibility = View.VISIBLE
+ Log.e("emumu : ", state.message)
+ binding.btnLogin.isEnabled = true
+ }
+ else -> {}
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt
new file mode 100644
index 0000000..6bc6345
--- /dev/null
+++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt
@@ -0,0 +1,43 @@
+package kr.ac.anu.mumu.presentation.login
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import kr.ac.anu.mumu.domain.usecase.LoginUseCase
+import javax.inject.Inject
+
+// 화면 상태
+sealed class LoginUiState {
+ object Idle : LoginUiState() // 대기
+ object Loading : LoginUiState() // 로딩
+ object Success : LoginUiState() // 로그인 성공
+ data class Error(val message: String) : LoginUiState() // 실패
+}
+
+@HiltViewModel
+class LoginViewModel @Inject constructor(
+ private val loginUseCase: LoginUseCase
+) : ViewModel() {
+
+ private val _uiState = MutableStateFlow(LoginUiState.Idle)
+ val uiState: StateFlow = _uiState.asStateFlow()
+
+ // 로그인 함수
+ fun login(id: String, pw: String) {
+ viewModelScope.launch {
+ _uiState.value = LoginUiState.Loading
+
+ loginUseCase(id, pw)
+ .onSuccess {
+ _uiState.value = LoginUiState.Success
+ }
+ .onFailure { error ->
+ _uiState.value = LoginUiState.Error(error.message ?: "로그인 실패")
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/main/MainActivity.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/main/MainActivity.kt
index 93bdd86..7901e6c 100644
--- a/app/src/main/java/kr/ac/anu/mumu/presentation/main/MainActivity.kt
+++ b/app/src/main/java/kr/ac/anu/mumu/presentation/main/MainActivity.kt
@@ -18,4 +18,4 @@ class MainActivity : AppCompatActivity() {
insets
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/res/drawable/btn_disabled.xml b/app/src/main/res/drawable/btn_disabled.xml
new file mode 100644
index 0000000..375755b
--- /dev/null
+++ b/app/src/main/res/drawable/btn_disabled.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_enabled.xml b/app/src/main/res/drawable/btn_enabled.xml
new file mode 100644
index 0000000..3fce4ed
--- /dev/null
+++ b/app/src/main/res/drawable/btn_enabled.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_join_background.xml b/app/src/main/res/drawable/btn_join_background.xml
new file mode 100644
index 0000000..ab4e216
--- /dev/null
+++ b/app/src/main/res/drawable/btn_join_background.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_selector.xml b/app/src/main/res/drawable/btn_selector.xml
new file mode 100644
index 0000000..c876632
--- /dev/null
+++ b/app/src/main/res/drawable/btn_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/gray_edit_box.xml b/app/src/main/res/drawable/gray_edit_box.xml
new file mode 100644
index 0000000..f7c1aec
--- /dev/null
+++ b/app/src/main/res/drawable/gray_edit_box.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
new file mode 100644
index 0000000..0c52a7a
--- /dev/null
+++ b/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/kr/ac/anu/mumu/ExampleUnitTest.kt b/app/src/test/java/kr/ac/anu/mumu/ExampleUnitTest.kt
index 11aca07..fce10fb 100644
--- a/app/src/test/java/kr/ac/anu/mumu/ExampleUnitTest.kt
+++ b/app/src/test/java/kr/ac/anu/mumu/ExampleUnitTest.kt
@@ -1,9 +1,8 @@
package kr.ac.anu.mumu
+import org.junit.Assert.assertEquals
import org.junit.Test
-import org.junit.Assert.*
-
/**
* Example local unit test, which will execute on the development machine (host).
*
@@ -14,4 +13,4 @@ class ExampleUnitTest {
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
-}
\ No newline at end of file
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index 922f551..08c5569 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,4 +2,5 @@
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
+ alias(libs.plugins.hilt.android) apply false
}
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index b419512..f58600b 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,26 +1,41 @@
[versions]
+activityKtx = "1.12.3"
agp = "8.10.1"
+fragmentKtx = "1.8.9"
+hiltAndroid = "2.51.1"
kotlin = "2.0.21"
coreKtx = "1.17.0"
junit = "4.13.2"
junitVersion = "1.3.0"
espressoCore = "3.7.0"
appcompat = "1.7.1"
+kotlinxCoroutinesAndroid = "1.9.0"
+lifecycleViewmodelKtx = "2.10.0"
material = "1.13.0"
activity = "1.12.1"
constraintlayout = "2.2.1"
+retrofit2 = "2.9.0"
[libraries]
+androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityKtx" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragmentKtx" }
+androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleViewmodelKtx" }
+androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
+converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit2" }
+hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
+hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+retrofit2 = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit2" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
-
+hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroid" }