Compare commits

..

16 Commits

Author SHA1 Message Date
89d8794f55 day3_commit.1.5_push_to_main 2025-02-20 16:51:04 +03:00
60110e8e68 Merge branch 'Frontend' 2025-02-20 16:50:25 +03:00
3ed1bc84d7 day3_commit2_vse_slomalos231231 2025-02-20 16:49:59 +03:00
97fb903db3 day3_commit.1.4_push_to_main 2025-02-20 16:48:32 +03:00
636b2a22fc Merge branch 'refs/heads/Frontend' 2025-02-20 16:48:21 +03:00
239f4f8a22 day3_commit2_vse_slomalos 2025-02-20 16:47:15 +03:00
018decb0e8 Merge branch 'Frontend_UI' into Frontend 2025-02-20 16:46:43 +03:00
537daa1072 Merge remote-tracking branch 'origin/Frontend' into Frontend
# Conflicts:
#	app/src/main/java/ru/myitschool/work/api/ApiService.kt
#	app/src/main/java/ru/myitschool/work/ui/Main/MainFragment.kt
#	app/src/main/java/ru/myitschool/work/ui/qr/result/QrResult.kt
2025-02-20 16:42:46 +03:00
0eb8ec5872 day3_commit2_vse_slomalos 2025-02-20 16:41:48 +03:00
333d9d6227 day3_commit.1.3_push_to_main 2025-02-20 16:33:25 +03:00
44e17c69de Merge branch 'Frontend_UI' 2025-02-20 16:32:30 +03:00
ebc2f1675b day3_commit2_front_nice_backendDIIE 2025-02-20 15:46:37 +03:00
654099623a day3_commit.1.2_temp 2025-02-20 12:44:11 +03:00
f6d313e8a3 day2_commit.1.2 2025-02-19 17:45:25 +03:00
064a29139f Merge remote-tracking branch 'origin/Frontend_UI' 2025-02-19 17:44:19 +03:00
644ff7ae02 day2_commit_1_// 2025-02-19 16:59:24 +03:00
7 changed files with 94 additions and 26 deletions

View File

@ -4,6 +4,7 @@ import retrofit2.Response
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Header import retrofit2.http.Header
import retrofit2.http.PATCH
import retrofit2.http.POST import retrofit2.http.POST
import retrofit2.http.Path import retrofit2.http.Path
import retrofit2.http.Query import retrofit2.http.Query
@ -25,12 +26,11 @@ interface ApiService {
@GET("/api/employee/{login}") // Получение информации о сотруднике @GET("/api/employee/{login}") // Получение информации о сотруднике
suspend fun getEmployeeInfo(@Path("login") login: String): Response<EmployeeData> suspend fun getEmployeeInfo(@Path("login") login: String): Response<EmployeeData>
@POST("api/{username}/open") @PATCH("/api/open") // Открыть дверь
suspend fun openDoor( suspend fun openDoor(
@Path("username") username: String, @Header("Authorization") authHeader: String,
@Header("Authorization") authHeader: String, // Добавляем заголовок
@Body request: OpenDoorRequest @Body request: OpenDoorRequest
): Response<String> ): Response<Unit> // Измените Response<String> на Response<Unit>
@POST("/api/employee/toggleAccess") // Метод для блокировки/разблокировки доступа @POST("/api/employee/toggleAccess") // Метод для блокировки/разблокировки доступа
suspend fun toggleAccess(@Body request: ToggleAccessRequest): Response<Unit> suspend fun toggleAccess(@Body request: ToggleAccessRequest): Response<Unit>
@ -54,4 +54,6 @@ data class ToggleAccessRequest(
) )
// Модель данных для запроса открытия двери // Модель данных для запроса открытия двери
data class OpenDoorRequest(val value: Long) data class OpenDoorRequest(
val value: Long // Код для открытия двери
)

View File

@ -15,7 +15,7 @@ class AccessLogAdapter(private val accessLogs: List<AccessLog>) : RecyclerView.A
val readerId: TextView = itemView.findViewById(R.id.reader_id) val readerId: TextView = itemView.findViewById(R.id.reader_id)
val accessType: TextView = itemView.findViewById(R.id.access_type) val accessType: TextView = itemView.findViewById(R.id.access_type)
} }
//.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AccessLogViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AccessLogViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_access_log, parent, false) val view = LayoutInflater.from(parent.context).inflate(R.layout.item_access_log, parent, false)
return AccessLogViewHolder(view) return AccessLogViewHolder(view)

View File

@ -34,7 +34,7 @@ class AdminFragment : Fragment(R.layout.fragment_admin) {
setupUI() setupUI()
} }
//.
private fun setupUI() { private fun setupUI() {
binding.viewEmployeeInfo.setOnClickListener { binding.viewEmployeeInfo.setOnClickListener {
val login = binding.employeeLogin.text.toString() val login = binding.employeeLogin.text.toString()

View File

@ -8,7 +8,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.setFragmentResultListener import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.bumptech.glide.Glide import com.squareup.picasso.Picasso
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.myitschool.work.R import ru.myitschool.work.R
import ru.myitschool.work.api.ApiService import ru.myitschool.work.api.ApiService
@ -69,16 +69,37 @@ class MainFragment : Fragment(R.layout.fragment_main) {
// Переход к экрану сканирования QR-кода // Переход к экрану сканирования QR-кода
findNavController().navigate(R.id.qrScanFragment) // Убедитесь, что у вас есть правильный ID для навигации findNavController().navigate(R.id.qrScanFragment) // Убедитесь, что у вас есть правильный ID для навигации
} }
// Проверяем роль пользователя и показываем кнопку AdminPanel, если роль admin
if (SessionManager.userRole == "admin") {
binding.adminPanelButton?.visibility = View.VISIBLE
binding.adminPanelButton?.setOnClickListener {
findNavController().navigate(R.id.adminFragment) // Переход к экрану администратора
}
} else {
binding.adminPanelButton?.visibility = View.GONE // Скрываем кнопку, если не admin
}
} }
private fun fetchUserInfo() { private fun fetchUserInfo() {
lifecycleScope.launch { lifecycleScope.launch {
val login = SessionManager.userLogin ?: return@launch val login = SessionManager.userLogin ?: run {
val authHeader = SessionManager.getAuthHeader() ?: return@launch binding.error.text = "Пользователь не авторизован"
binding.error.visibility = View.VISIBLE
return@launch
}
val authHeader = SessionManager.getAuthHeader() ?: run {
binding.error.text = "Ошибка авторизации"
binding.error.visibility = View.VISIBLE
return@launch
}
try { try {
val response = apiService.getUserInfo(login, authHeader) val response = apiService.getUserInfo(login, authHeader)
// Логируем код ответа
Log.d("MainFragment", "Response code: ${response.code()}")
if (response.isSuccessful) { if (response.isSuccessful) {
val employeeData = response.body() val employeeData = response.body()
employeeData?.let { employeeData?.let {
@ -86,11 +107,15 @@ class MainFragment : Fragment(R.layout.fragment_main) {
binding.position.text = it.position binding.position.text = it.position
binding.lastEntry.text = it.lastVisit binding.lastEntry.text = it.lastVisit
// Загрузка аватара // Логируем URL аватара
if (it.avatarUrl != null) { // Предполагается, что у вас есть поле avatarUrl Log.d("MainFragment", "Avatar URL: ${it.avatarUrl}")
// Используйте библиотеку, такую как Glide или Picasso, для загрузки изображения
Glide.with(this@MainFragment) // Загрузка аватара с помощью Picasso
if (it.avatarUrl != null) {
Picasso.get()
.load(it.avatarUrl) .load(it.avatarUrl)
.placeholder(R.drawable.ic_refresh) // Замените на ваш ресурс-заполнитель
.error(R.drawable.ic_close) // Замените на ваш ресурс ошибки
.into(binding.photo) .into(binding.photo)
binding.photo.visibility = View.VISIBLE binding.photo.visibility = View.VISIBLE
} else { } else {
@ -111,4 +136,9 @@ class MainFragment : Fragment(R.layout.fragment_main) {
} }
} }
} }
override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
} }

View File

@ -22,7 +22,7 @@ class RootActivity : AppCompatActivity() {
navController.setGraph(R.navigation.nav_graph) // Устанавливаем граф навигации navController.setGraph(R.navigation.nav_graph) // Устанавливаем граф навигации
} }
// Настраиваем кнопку "Назад" // Настройка кнопки "Назад"
onBackPressedDispatcher.addCallback( onBackPressedDispatcher.addCallback(
this, this,
object : OnBackPressedCallback(true) { object : OnBackPressedCallback(true) {

View File

@ -5,8 +5,10 @@ import androidx.navigation.fragment.findNavController
import ru.myitschool.work.SessionManager import ru.myitschool.work.SessionManager
import ru.myitschool.work.api.OpenDoorRequest import ru.myitschool.work.api.OpenDoorRequest
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.util.Base64
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -14,14 +16,14 @@ import kotlinx.coroutines.launch
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import ru.myitschool.work.R import ru.myitschool.work.R
import android.util.Base64
import android.util.Log
import ru.myitschool.work.api.ApiService import ru.myitschool.work.api.ApiService
import ru.myitschool.work.core.Constants import ru.myitschool.work.core.Constants
import ru.myitschool.work.databinding.FragmentQrScanResultBinding import ru.myitschool.work.databinding.FragmentQrScanResultBinding
class QrResult : Fragment(R.layout.fragment_qr_scan_result) { class QrResult : Fragment(R.layout.fragment_qr_scan_result) {
private lateinit var binding: FragmentQrScanResultBinding private var _binding: FragmentQrScanResultBinding? = null
private val binding get() = _binding!!
private lateinit var apiService: ApiService private lateinit var apiService: ApiService
override fun onCreateView( override fun onCreateView(
@ -29,7 +31,7 @@ class QrResult : Fragment(R.layout.fragment_qr_scan_result) {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
binding = FragmentQrScanResultBinding.inflate(inflater, container, false) _binding = FragmentQrScanResultBinding.inflate(inflater, container, false)
apiService = Retrofit.Builder() apiService = Retrofit.Builder()
.baseUrl(Constants.SERVER_ADDRESS) .baseUrl(Constants.SERVER_ADDRESS)
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
@ -42,8 +44,12 @@ class QrResult : Fragment(R.layout.fragment_qr_scan_result) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
// Получаем данные из аргументов
val qrData = QrScanDestination.getDataIfExist(requireArguments()) val qrData = QrScanDestination.getDataIfExist(requireArguments())
Log.d("QrResult", "QR Data: $qrData") // Логируем полученные данные
if (qrData != null) { if (qrData != null) {
binding.result.text = "Результат сканирования: $qrData" // Отображаем результат сканирования
sendRequestToServer(qrData) sendRequestToServer(qrData)
} else { } else {
binding.result.text = "Вход был отменён/Operation was cancelled" binding.result.text = "Вход был отменён/Operation was cancelled"
@ -59,19 +65,23 @@ class QrResult : Fragment(R.layout.fragment_qr_scan_result) {
try { try {
val qrValue = qrData.toLong() // Преобразуем данные QR-кода в Long val qrValue = qrData.toLong() // Преобразуем данные QR-кода в Long
val login = SessionManager.userLogin ?: "default_login" // Замените на ваш логин val login = SessionManager.userLogin ?: "default_login" // Замените на ваш логин
val password = "password123" // Замените на ваш пароль val password = "your_password" // Замените на ваш пароль
val authHeader = "Basic " + Base64.encodeToString("$login:$password".toByteArray(), Base64.NO_WRAP) val authHeader = "Basic " + Base64.encodeToString("$login:$password".toByteArray(), Base64.NO_WRAP)
// Логируем данные перед отправкой // Логируем данные перед отправкой
Log.d("QrResult", "Sending request with QR value: $qrValue and authHeader: $authHeader") Log.d("QrResult", "Sending request with QR value: $qrValue and authHeader: $authHeader")
val response = apiService.openDoor(login, authHeader, OpenDoorRequest(qrValue)) // Создаем объект запроса
val request = OpenDoorRequest(qrValue)
// Вызываем метод openDoor с правильными параметрами
val response = apiService.openDoor(authHeader, request)
// Логируем код ответа и тело ответа // Логируем код ответа и тело ответа
Log.d("QrResult", "Response code: ${response.code()}") Log.d("QrResult", "Response code: ${response.code()}")
Log.d("QrResult", "Response body: ${response.body()}") Log.d("QrResult", "Response body: ${response.body()}")
if (response.code() == 200) { if (response.isSuccessful) {
binding.result.text = "Door Opened" // Сообщение о том, что дверь открыта binding.result.text = "Door Opened" // Сообщение о том, что дверь открыта
} else { } else {
binding.result.text = "Door Closed" // Сообщение о том, что дверь закрыта binding.result.text = "Door Closed" // Сообщение о том, что дверь закрыта
@ -79,9 +89,14 @@ class QrResult : Fragment(R.layout.fragment_qr_scan_result) {
} catch (e: NumberFormatException) { } catch (e: NumberFormatException) {
binding.result.text = "Некорректные данные QR-кода" binding.result.text = "Некорректные данные QR-кода"
} catch (e: Exception) { } catch (e: Exception) {
binding.result.text = "Что-то пошло не так: ${e.message}" binding.result.text = "Что-то пошло не так/Something went wrong: ${e.message}"
Log.e("QrResult", "Error: ${e.message}", e) // Логируем ошибку Log.e("QrResult", "Error sending request to server", e)
} }
} }
} }
override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
} }

View File

@ -1,6 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="16dp">
@ -33,6 +34,10 @@
android:id="@+id/refresh" android:id="@+id/refresh"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:backgroundTint="@color/colorPrimary"
android:textColor="@android:color/white"
android:padding="12dp"
app:cornerRadius="16dp"
android:text="@string/refresh" /> android:text="@string/refresh" />
<TextView <TextView
@ -52,6 +57,22 @@
android:id="@+id/scan_qr_code" android:id="@+id/scan_qr_code"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:backgroundTint="@color/colorPrimary"
android:textColor="@android:color/white"
android:padding="12dp"
app:cornerRadius="16dp"
android:text="Сканировать QR-код" android:text="Сканировать QR-код"
android:visibility="gone" /> android:visibility="gone" />
<Button
android:id="@+id/adminPanelButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/colorPrimary"
android:textColor="@android:color/white"
android:padding="12dp"
app:cornerRadius="16dp"
android:text="Admin Panel"
android:visibility="gone" />
</LinearLayout> </LinearLayout>