day2_commit_10_fixed_alotofbugs_added_admin_logic
This commit is contained in:
parent
1d9207a5f5
commit
85a5c82d8c
@ -23,7 +23,7 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Default"
|
||||
tools:targetApi="31">
|
||||
tools:targetApi="34">
|
||||
<activity
|
||||
android:name=".ui.RootActivity"
|
||||
android:exported="true">
|
||||
|
@ -1,5 +1,12 @@
|
||||
package ru.myitschool.work
|
||||
|
||||
object SessionManager {
|
||||
var userLogin: String = ""
|
||||
var userLogin: String? = null // Логин пользователя
|
||||
var userRole: String? = null // Роль пользователя
|
||||
|
||||
// Метод для очистки данных сессии
|
||||
fun clearSession() {
|
||||
userLogin = null
|
||||
userRole = null
|
||||
}
|
||||
}
|
@ -4,21 +4,41 @@ import retrofit2.Response
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.PATCH
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Path
|
||||
|
||||
interface ApiService {
|
||||
@GET("api/{login}/auth")
|
||||
suspend fun authenticate(
|
||||
@Path("login") login: String,
|
||||
@Header("Authorization") authorization: String // Добавляем заголовок Authorization
|
||||
): Response<Unit>
|
||||
@Header("Authorization") authorization: String
|
||||
): Response<UserAuthResponse> // Изменяем на UserAuthResponse
|
||||
|
||||
@GET("api/{login}/info")
|
||||
suspend fun getUserInfo(@Path("login") login: String): Response<Map<String, Any>> // Возвращаем Map вместо UserInfo
|
||||
suspend fun getUserInfo(@Path("login") login: String): Response<Map<String, Any>>
|
||||
|
||||
@PATCH("api/{login}/open")
|
||||
suspend fun openDoor(@Path("login") login: String, @Body body: OpenDoorRequest): Response<Unit>
|
||||
@POST("api/employee/toggleAccess")
|
||||
suspend fun toggleAccess(@Body request: ToggleAccessRequest): Response<Unit>
|
||||
|
||||
// Метод для получения информации о сотруднике
|
||||
@GET("api/employee/{login}")
|
||||
suspend fun getEmployeeInfo(@Path("login") login: String): Response<EmployeeData>
|
||||
}
|
||||
|
||||
data class OpenDoorRequest(val value: String)
|
||||
// Модель данных для ответа аутентификации
|
||||
data class UserAuthResponse(
|
||||
val role: String // Добавляем поле для роли
|
||||
)
|
||||
|
||||
// Модель данных для информации о сотруднике
|
||||
data class EmployeeData(
|
||||
val name: String,
|
||||
val position: String,
|
||||
val lastVisit: String
|
||||
)
|
||||
|
||||
// Модель данных для запроса блокировки/разблокировки доступа
|
||||
data class ToggleAccessRequest(
|
||||
val login: String,
|
||||
val action: String // "block" или "unblock"
|
||||
)
|
@ -1,60 +1,108 @@
|
||||
package ru.myitschool.work.ui.Main
|
||||
package ru.myitschool.work.ui.admin
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import kotlinx.coroutines.launch
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import ru.myitschool.work.R
|
||||
import ru.myitschool.work.api.ApiService
|
||||
import ru.myitschool.work.api.EmployeeData
|
||||
import ru.myitschool.work.api.ToggleAccessRequest
|
||||
import ru.myitschool.work.core.Constants
|
||||
import ru.myitschool.work.databinding.FragmentAdminBinding
|
||||
|
||||
// TODO: Rename parameter arguments, choose names that match
|
||||
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
||||
private const val ARG_PARAM1 = "param1"
|
||||
private const val ARG_PARAM2 = "param2"
|
||||
class AdminFragment : Fragment(R.layout.fragment_admin) {
|
||||
private var _binding: FragmentAdminBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
* Use the [AdminFragment.newInstance] factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class AdminFragment : Fragment() {
|
||||
// TODO: Rename and change types of parameters
|
||||
private var param1: String? = null
|
||||
private var param2: String? = null
|
||||
private val apiService: ApiService by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(Constants.SERVER_ADDRESS)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
.create(ApiService::class.java)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
arguments?.let {
|
||||
param1 = it.getString(ARG_PARAM1)
|
||||
param2 = it.getString(ARG_PARAM2)
|
||||
private var isAccessBlocked: Boolean = false // Переменная для отслеживания состояния доступа
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentAdminBinding.bind(view)
|
||||
|
||||
setupUI()
|
||||
}
|
||||
|
||||
private fun setupUI() {
|
||||
binding.viewEmployeeInfo.setOnClickListener {
|
||||
val login = binding.employeeLogin.text.toString()
|
||||
if (login.isNotEmpty()) {
|
||||
fetchEmployeeInfo(login)
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Введите логин сотрудника", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
binding.toggleAccess.setOnClickListener {
|
||||
val login = binding.employeeLogin.text.toString()
|
||||
if (login.isNotEmpty()) {
|
||||
// Определяем действие на основе текущего состояния доступа
|
||||
val action = if (isAccessBlocked) "unblock" else "block"
|
||||
toggleEmployeeAccess(login, action)
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Введите логин сотрудника", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_admin, container, false)
|
||||
private fun fetchEmployeeInfo(login: String) {
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = apiService.getEmployeeInfo(login)
|
||||
if (response.isSuccessful) {
|
||||
val employeeData = response.body()
|
||||
employeeData?.let {
|
||||
binding.employeeInfo.text = "Имя: ${it.name}, Должность: ${it.position}, Последний визит: ${it.lastVisit}"
|
||||
binding.employeeInfo.visibility = View.VISIBLE
|
||||
binding.toggleAccess.visibility = View.VISIBLE
|
||||
// Здесь можно установить состояние доступа, если оно доступно
|
||||
isAccessBlocked = false // Предположим, что доступ не заблокирован по умолчанию
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Ошибка получения данных", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(requireContext(), "Ошибка сети", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
* this fragment using the provided parameters.
|
||||
*
|
||||
* @param param1 Parameter 1.
|
||||
* @param param2 Parameter 2.
|
||||
* @return A new instance of fragment AdminFragment.
|
||||
*/
|
||||
// TODO: Rename and change types and number of parameters
|
||||
@JvmStatic
|
||||
fun newInstance(param1: String, param2: String) =
|
||||
AdminFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString(ARG_PARAM1, param1)
|
||||
putString(ARG_PARAM2, param2)
|
||||
private fun toggleEmployeeAccess(login: String, action: String) {
|
||||
val request = ToggleAccessRequest(login, action)
|
||||
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = apiService.toggleAccess(request)
|
||||
if (response.isSuccessful) {
|
||||
isAccessBlocked = !isAccessBlocked // Переключаем состояние доступа
|
||||
val message = if (action == "block") "Доступ заблокирован" else "Доступ разблокирован"
|
||||
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Ошибка изменения доступа", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(requireContext(), "Ошибка сети", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
_binding = null // Освобождаем binding, когда представление уничтожается
|
||||
super.onDestroyView()
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ import androidx.fragment.app.setFragmentResultListener
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -47,11 +46,24 @@ class MainFragment : Fragment(R.layout.fragment_main) {
|
||||
|
||||
setupUI()
|
||||
fetchUserData()
|
||||
checkAdminAccess() // Проверяем доступ администратора
|
||||
|
||||
// Проверяем, есть ли результат QR
|
||||
checkQrResult()
|
||||
}
|
||||
|
||||
private fun checkAdminAccess() {
|
||||
// Проверяем, является ли пользователь администратором
|
||||
if (SessionManager.userRole == "admin") {
|
||||
binding.adminPanel.visibility = View.VISIBLE // Показываем кнопку AdminPanel
|
||||
binding.adminPanel.setOnClickListener {
|
||||
findNavController().navigate(R.id.adminFragment) // Переход на экран администратора
|
||||
}
|
||||
} else {
|
||||
binding.adminPanel.visibility = View.GONE // Скрываем кнопку для обычных пользователей
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkQrResult() {
|
||||
// Слушаем результат QR сканирования
|
||||
setFragmentResultListener(QrScanDestination.REQUEST_KEY) { _, bundle ->
|
||||
@ -81,25 +93,28 @@ class MainFragment : Fragment(R.layout.fragment_main) {
|
||||
lifecycleScope.launch {
|
||||
showError(null) // Скрыть ошибку, если она была
|
||||
try {
|
||||
val response = apiService.getUserInfo(SessionManager.userLogin) // Получаем данные пользователя
|
||||
if (response.isSuccessful) {
|
||||
response.body()?.let { data ->
|
||||
// Извлекаем значения из Map
|
||||
val fullName = data["name"] as? String ?: "Неизвестно"
|
||||
val position = data["position"] as? String ?: "Неизвестно"
|
||||
val lastVisit = data["lastVisit"] as? String ?: "Неизвестно"
|
||||
val photoUrl = data["photo"] as? String ?: ""
|
||||
val response =
|
||||
SessionManager.userLogin?.let { apiService.getUserInfo(it) } // Получаем данные пользователя
|
||||
if (response != null) {
|
||||
if (response.isSuccessful) {
|
||||
response.body()?.let { data ->
|
||||
// Извлекаем значения из Map
|
||||
val fullName = data["name"] as? String ?: "Неизвестно"
|
||||
val position = data["position"] as? String ?: "Неизвестно"
|
||||
val lastVisit = data["lastVisit"] as? String ?: "Неизвестно"
|
||||
val photoUrl = data["photo"] as? String ?: ""
|
||||
|
||||
// Обновляем UI
|
||||
updateUI(fullName, position, lastVisit, photoUrl)
|
||||
// Обновляем UI
|
||||
updateUI(fullName, position, lastVisit, photoUrl)
|
||||
|
||||
// Здесь вы можете добавить данные проходов в список
|
||||
// Пример:
|
||||
accessLogs.add(AccessLog("2024-02-31 08:31", "Считыватель 1", "карта"))
|
||||
accessLogAdapter.notifyDataSetChanged() // Обновляем адаптер
|
||||
// Здесь вы можете добавить данные проходов в список
|
||||
// Пример:
|
||||
accessLogs.add(AccessLog("2024-02-31 08:31", "Считыватель 1", "карта"))
|
||||
accessLogAdapter.notifyDataSetChanged() // Обновляем адаптер
|
||||
}
|
||||
} else {
|
||||
showError(getString(R.string.error_loading_data)) // Показываем ошибку, если данные не загрузились
|
||||
}
|
||||
} else {
|
||||
showError(getString(R.string.error_loading_data)) // Показываем ошибку, если данные не загрузились
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
showError(e.localizedMessage) // Показываем ошибку при исключении
|
||||
|
@ -10,15 +10,17 @@ import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import ru.myitschool.work.R
|
||||
import ru.myitschool.work.SessionManager
|
||||
import ru.myitschool.work.api.UserAuthResponse
|
||||
import ru.myitschool.work.databinding.FragmentLoginBinding
|
||||
import ru.myitschool.work.utils.collectWhenStarted
|
||||
import ru.myitschool.work.utils.visibleOrGone
|
||||
import ru.myitschool.work.utils.AuthPreferences
|
||||
import kotlinx.coroutines.launch
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
|
||||
@AndroidEntryPoint
|
||||
class LoginFragment : Fragment(R.layout.fragment_login) {
|
||||
@ -76,6 +78,7 @@ class LoginFragment : Fragment(R.layout.fragment_login) {
|
||||
|
||||
private fun performLogin(username: String, password: String) {
|
||||
lifecycleScope.launch {
|
||||
binding.loading.visibleOrGone(true) // Показываем индикатор загрузки
|
||||
viewModel.authenticate(username, password) // Передаем пароль в метод authenticate
|
||||
}
|
||||
}
|
||||
@ -94,6 +97,13 @@ class LoginFragment : Fragment(R.layout.fragment_login) {
|
||||
binding.error.visibility = View.GONE
|
||||
authPreferences.saveLoginState(true)
|
||||
authPreferences.saveLogin(binding.username.text.toString()) // Сохраняем логин
|
||||
|
||||
// Сохраняем роль пользователя в SessionManager
|
||||
val userAuthResponse: UserAuthResponse? = state.userAuthResponse
|
||||
userAuthResponse?.let {
|
||||
SessionManager.userRole = it.role // Сохраняем роль
|
||||
}
|
||||
|
||||
Toast.makeText(context, "Авторизация прошла успешно", Toast.LENGTH_SHORT).show()
|
||||
navigateToMainScreen()
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import ru.myitschool.work.SessionManager
|
||||
import ru.myitschool.work.api.ApiService
|
||||
import ru.myitschool.work.api.UserAuthResponse
|
||||
import ru.myitschool.work.core.Constants
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -38,8 +39,12 @@ class LoginViewModel @Inject constructor(
|
||||
val credentials = Credentials.basic(username, password) // Создаем Basic Auth заголовок
|
||||
val response = apiService.authenticate(username, credentials) // Передаем заголовок в запрос
|
||||
if (response.isSuccessful) {
|
||||
SessionManager.userLogin = username
|
||||
_state.value = LoginState(success = true)
|
||||
val userAuthResponse = response.body() // Получаем ответ с ролью пользователя
|
||||
userAuthResponse?.let {
|
||||
SessionManager.userLogin = username // Сохраняем логин
|
||||
SessionManager.userRole = it.role // Сохраняем роль
|
||||
}
|
||||
_state.value = LoginState(success = true, userAuthResponse = userAuthResponse)
|
||||
} else if (response.code() == 503) { // Пример кода для техработ
|
||||
_state.value = LoginState(maintenance = true)
|
||||
} else {
|
||||
@ -60,5 +65,10 @@ class LoginViewModel @Inject constructor(
|
||||
return username.length >= 3 && !username.first().isDigit() && username.all { it.isLetterOrDigit() }
|
||||
}
|
||||
|
||||
data class LoginState(val success: Boolean = false, val error: String? = null, val maintenance: Boolean = false)
|
||||
data class LoginState(
|
||||
val success: Boolean = false,
|
||||
val error: String? = null,
|
||||
val maintenance: Boolean = false,
|
||||
val userAuthResponse: UserAuthResponse? = null // Добавляем поле для хранения информации о роли
|
||||
)
|
||||
}
|
@ -1,14 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.Main.AdminFragment">
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- TODO: Update blank fragment layout -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/hello_blank_fragment" />
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Введите логин сотрудника:"
|
||||
android:textSize="18sp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
</FrameLayout>
|
||||
<EditText
|
||||
android:id="@+id/employee_login"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Логин сотрудника"
|
||||
android:inputType="text" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/view_employee_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Просмотреть информацию о сотруднике"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/employee_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/toggle_access"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Блокировать/Разблокировать доступ"
|
||||
android:layout_marginTop="16dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
@ -93,4 +93,13 @@
|
||||
android:backgroundTint="@color/colorPrimary"
|
||||
android:textColor="@android:color/white"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/admin_panel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Admin Panel"
|
||||
android:layout_marginTop="16dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -22,6 +22,12 @@
|
||||
android:label="Main Fragment"
|
||||
tools:layout="@layout/fragment_main" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/adminFragment"
|
||||
android:name="ru.myitschool.work.ui.admin.AdminFragment"
|
||||
android:label="Admin Fragment"
|
||||
tools:layout="@layout/fragment_admin" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/qrResultFragment"
|
||||
android:name="ru.myitschool.work.ui.qr.result.QrResult"
|
||||
|
Loading…
x
Reference in New Issue
Block a user