auth to server-V2

This commit is contained in:
Eric85710 2026-04-27 18:24:00 +08:00
parent ff86c28ee0
commit 8c26b4c5a1
8 changed files with 74 additions and 119 deletions

View file

@ -1,30 +0,0 @@
package com.example.login_v3.auth
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.login_v3.data.api.api_class.LoginResponse
import com.example.login_v3.data.repository.basic.ITecnologiaRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class LoginViewModel @Inject constructor(
private val repository: ITecnologiaRepository
) : ViewModel() {
// 使用 StateFlow 或 LiveData 來傳遞結果給 UI
private val _loginResult = MutableStateFlow<Result<LoginResponse>?>(null)
val loginResult = _loginResult.asStateFlow()
fun performLogin(username: String, password: String) {
viewModelScope.launch {
// 直接呼叫 repository,ViewModel 不關心資料是從網路還是資料庫來的
val result = repository.login(username, password)
_loginResult.value = result
}
}
}

View file

@ -1,4 +1,4 @@
package com.example.login_v3.auth
package com.example.login_v3.auth.login
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.AccountCircle
@ -47,8 +46,6 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavBackStackEntry
import coil.ImageLoader
import coil.compose.AsyncImage
import coil.decode.SvgDecoder
@ -159,7 +156,7 @@ fun LoginScreen(
label = {
Text(
emailError.ifEmpty { "Email" },
color = if (emailError.isNotEmpty()) Red else androidx.compose.ui.graphics.Color.Unspecified
color = if (emailError.isNotEmpty()) Red else Color.Unspecified
)
},
@ -190,7 +187,7 @@ fun LoginScreen(
label = {
Text(
passwordError.ifEmpty { "Password" },
color = if (passwordError.isNotEmpty()) Red else androidx.compose.ui.graphics.Color.Unspecified
color = if (passwordError.isNotEmpty()) Red else Color.Unspecified
)
},
leadingIcon = {

View file

@ -0,0 +1 @@
package com.example.login_v3.auth.login

View file

@ -1,4 +1,4 @@
package com.example.login_v3.auth
package com.example.login_v3.auth.reg
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.AccountCircle
@ -45,8 +44,6 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import com.example.login_v3.data.health.HealthCheckViewModel
import com.example.login_v3.ui.theme.main_orange
import kotlin.text.ifEmpty
@ -137,7 +134,7 @@ fun Register_Screen(
label = {
Text(
user_name_Error.ifEmpty { "username" },
color = if (user_name_Error.isNotEmpty()) Red else androidx.compose.ui.graphics.Color.Unspecified
color = if (user_name_Error.isNotEmpty()) Red else Color.Unspecified
)
},
@ -168,7 +165,7 @@ fun Register_Screen(
label = {
Text(
emailError.ifEmpty { "Email" },
color = if (emailError.isNotEmpty()) Red else androidx.compose.ui.graphics.Color.Unspecified
color = if (emailError.isNotEmpty()) Red else Color.Unspecified
)
},
@ -199,7 +196,7 @@ fun Register_Screen(
label = {
Text(
passwordError.ifEmpty { "Password" },
color = if (passwordError.isNotEmpty()) Red else androidx.compose.ui.graphics.Color.Unspecified
color = if (passwordError.isNotEmpty()) Red else Color.Unspecified
)
},
leadingIcon = {

View file

@ -0,0 +1,42 @@
package com.example.login_v3.auth.reg
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.login_v3.data.api.api_class.RegisterRequest
import com.example.login_v3.data.repository.basic.AuthRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class RegisterViewModel @Inject constructor(
private val repository: AuthRepository
) : ViewModel() {
fun handleRegister() {
val request = RegisterRequest(
display_name = "測試員",
email = "test@example.com",
password = "password123",
username = "tester01"
)
viewModelScope.launch {
try {
val response = repository.register(request)
if (response.isSuccessful) {
// 註冊成功,處理 response.body()
val successMsg = response.body()?.message
println("註冊成功: $successMsg")
} else {
// 註冊失敗,處理錯誤訊息 (例如 400 重複註冊)
val errorJson = response.errorBody()?.string()
println("註冊失敗: $errorJson")
}
} catch (e: Exception) {
// 處理網路連線異常
println("網路錯誤: ${e.message}")
}
}
}
}

View file

@ -0,0 +1,22 @@
package com.example.login_v3.data.repository.basic
import com.example.login_v3.data.api.TecnologiaApi
import com.example.login_v3.data.api.api_class.ApiResponse
import com.example.login_v3.data.api.api_class.RegisterRequest
import retrofit2.Response
import javax.inject.Inject
class AuthRepository @Inject constructor(
private val api: TecnologiaApi
) {
/**
* 處理用戶註冊
* 回傳 Response<ApiResponse>,讓 ViewModel 可以根據 isSuccessful 判斷結果
*/
suspend fun register(request: RegisterRequest): Response<ApiResponse> {
return api.register(request)
}
// 你也可以在這裡加入其他的 Auth 相關功能,例如登入
// suspend fun login(request: LoginRequest) = api.login(request)
}

View file

@ -1,66 +0,0 @@
package com.example.login_v3.data.repository.basic
import com.example.login_v3.data.api.TecnologiaApi
import com.example.login_v3.data.api.api_class.ApiResponse
import com.example.login_v3.data.api.api_class.FriendRequest
import com.example.login_v3.data.api.api_class.LoginRequest
import com.example.login_v3.data.api.api_class.LoginResponse
import com.example.login_v3.data.api.api_class.User
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import java.lang.Exception
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TecnologiaRepositoryImpl @Inject constructor(
private val api: TecnologiaApi // Hilt 會從 NetworkModule 找這個 API
) : ITecnologiaRepository {
override suspend fun login(username: String, password: String): Result<LoginResponse> {
return try {
val response = api.login(LoginRequest(username, password))
Result.success(response)
} catch (e: Exception) {
Result.failure(e)
}
}
override suspend fun getMe(token: String): Result<User> {
return try {
val response = api.getMe("Bearer $token")
Result.success(response)
} catch (e: Exception) {
Result.failure(e)
}
}
override suspend fun sendFriendRequest(token: String, friendId: String): Result<ApiResponse> {
return try {
val response = api.sendFriendRequest("Bearer $token", FriendRequest(friendId))
Result.success(response)
} catch (e: Exception) {
Result.failure(e)
}
}
}
@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindTecnologiaRepository(
repositoryImpl: TecnologiaRepositoryImpl // 這裡要對應實作類別的名稱
): ITecnologiaRepository
}
interface ITecnologiaRepository {
suspend fun login(username: String, password: String): Result<LoginResponse>
suspend fun getMe(token: String): Result<User>
suspend fun sendFriendRequest(token: String, friendId: String): Result<ApiResponse>
}

View file

@ -1,23 +1,15 @@
package com.example.login_v3.navigation
import android.R.attr.padding
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.example.login_v3.auth.LoginScreen
import com.example.login_v3.auth.LoginViewModel
import com.example.login_v3.auth.login.LoginScreen
import com.example.login_v3.auth.Login_or_Reg_page
import com.example.login_v3.auth.Register_Screen
import com.example.login_v3.auth.reg.Register_Screen
import com.example.login_v3.home.HomeScreen
import com.example.login_v3.home.Tg_MarketPlace
@Composable
fun AppNavGraph(