day3_commit1_fixed_loginauth

This commit is contained in:
Terebov_Maksim 2025-02-20 12:08:52 +03:00
parent 8fc1f2decd
commit 194a1dc466
13 changed files with 301 additions and 255 deletions

View File

@ -0,0 +1,82 @@
kotlin version: 2.0.21
error message: Daemon compilation failed: null
java.lang.Exception
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:69)
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:65)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:240)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:195)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:128)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:170)
at org.gradle.internal.Factories$1.create(Factories.java:31)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:267)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:131)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:136)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:165)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:134)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.nio.file.DirectoryNotEmptyException: C:\Users\User\AppData\Local\Temp\kotlin-backups11164380389062662786
at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(Unknown Source)
at java.base/sun.nio.fs.AbstractFileSystemProvider.delete(Unknown Source)
at java.base/java.nio.file.Files.delete(Unknown Source)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash$lambda$11$lambda$10$lambda$9(CompilationTransaction.kt:244)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Unknown Source)
at java.base/java.util.ArrayList.forEach(Unknown Source)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(Unknown Source)
at java.base/java.util.stream.Sink$ChainedReference.end(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.base/java.util.stream.ReferencePipeline.forEach(Unknown Source)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.close(CompilationTransaction.kt:254)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally(IncrementalCompilerRunner.kt:747)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:120)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
... 3 more

View File

@ -0,0 +1,82 @@
kotlin version: 2.0.21
error message: Daemon compilation failed: null
java.lang.Exception
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:69)
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:65)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:240)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:195)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:128)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:170)
at org.gradle.internal.Factories$1.create(Factories.java:31)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:267)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:131)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:136)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:165)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:134)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.nio.file.DirectoryNotEmptyException: C:\Users\User\AppData\Local\Temp\kotlin-backups8341820686666786180
at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(Unknown Source)
at java.base/sun.nio.fs.AbstractFileSystemProvider.delete(Unknown Source)
at java.base/java.nio.file.Files.delete(Unknown Source)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash$lambda$11$lambda$10$lambda$9(CompilationTransaction.kt:244)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Unknown Source)
at java.base/java.util.ArrayList.forEach(Unknown Source)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(Unknown Source)
at java.base/java.util.stream.Sink$ChainedReference.end(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.base/java.util.stream.ReferencePipeline.forEach(Unknown Source)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.close(CompilationTransaction.kt:254)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally(IncrementalCompilerRunner.kt:747)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:120)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
... 3 more

View File

@ -4,4 +4,9 @@ import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class App : Application()
class App : Application() {
override fun onCreate() {
super.onCreate()
SessionManager.init(this) // Инициализация SessionManager
}
}

View File

@ -1,10 +1,39 @@
package ru.myitschool.work
object SessionManager {
var userLogin: String? = null // Логин пользователя
var userRole: String? = null // Роль пользователя
import android.content.Context
import android.content.SharedPreferences
import java.util.Base64
object SessionManager {
private const val PREF_NAME = "user_session"
private const val KEY_USER_LOGIN = "user_login"
private const val KEY_USER_ROLE = "user_role"
private lateinit var preferences: SharedPreferences
fun init(context: Context) {
preferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
}
var userLogin: String?
get() = preferences.getString(KEY_USER_LOGIN, null)
set(value) {
preferences.edit().putString(KEY_USER_LOGIN, value).apply()
}
var userRole: String?
get() = preferences.getString(KEY_USER_ROLE, null)
set(value) {
preferences.edit().putString(KEY_USER_ROLE, value).apply()
}
fun getAuthHeader(): String {
val username = userLogin ?: return ""
val password = "password123" // Замените на ваш пароль
val credential = Base64.getEncoder().encodeToString("$username:$password".toByteArray())
return "Basic $credential"
}
// Метод для очистки данных сессии
fun clearSession() {
userLogin = null
userRole = null

View File

@ -1,5 +1,6 @@
package ru.myitschool.work.api
import LoggingInterceptor
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -17,7 +18,8 @@ object ApiModule {
@Singleton
fun provideOkHttpClient(authInterceptor: AuthInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(authInterceptor) // Добавляем интерсептор
.addInterceptor(authInterceptor) // Добавляем интерсептор аутентификации
.addInterceptor(LoggingInterceptor()) // Добавляем интерсептор логирования
.build()
}

View File

@ -4,6 +4,7 @@ import okhttp3.ResponseBody
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
@ -17,9 +18,11 @@ interface ApiService {
@Query("password") password: String
): Response<Unit> // Измените Response<String> на Response<Unit>
// Другие методы...
@GET("/api/{login}/info") // Получение информации о пользователе
suspend fun getUserInfo(@Path("login") login: String): Response<Map<String, Any>>
@GET("/api/{login}/info")
suspend fun getUserInfo(
@Path("login") login: String,
@Header("Authorization") authHeader: String
): Response<EmployeeData>
@GET("/api/employee/{login}") // Получение информации о сотруднике
suspend fun getEmployeeInfo(@Path("login") login: String): Response<EmployeeData>

View File

@ -0,0 +1,15 @@
import okhttp3.Interceptor
import okhttp3.Response
import android.util.Log
class LoggingInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
Log.d("LoggingInterceptor", "Sending request to ${request.url} with headers ${request.headers}")
val response = chain.proceed(request)
Log.d("LoggingInterceptor", "Received response for ${response.request.url} with code ${response.code}")
return response
}
}

View File

@ -10,7 +10,6 @@ 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

View File

@ -1,201 +1,98 @@
package ru.myitschool.work.ui.main
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.view.View
import android.widget.Toast
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.coroutines.Dispatchers
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import ru.myitschool.work.R
import ru.myitschool.work.SessionManager
import ru.myitschool.work.api.AccessLog
import ru.myitschool.work.api.ApiService
import ru.myitschool.work.api.AccessLog
import ru.myitschool.work.core.Constants
import ru.myitschool.work.databinding.FragmentMainBinding
import ru.myitschool.work.ui.qr.scan.QrScanDestination
import java.net.HttpURLConnection
import java.net.URL
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import ru.myitschool.work.SessionManager
class MainFragment : Fragment(R.layout.fragment_main) {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
private val apiService: ApiService by lazy {
Retrofit.Builder()
private lateinit var apiService: ApiService
private lateinit var accessLogAdapter: AccessLogAdapter
private val accessLogs = mutableListOf<AccessLog>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
apiService = Retrofit.Builder()
.baseUrl(Constants.SERVER_ADDRESS)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
private lateinit var accessLogAdapter: AccessLogAdapter
private val accessLogs = mutableListOf<AccessLog>() // Список для хранения данных проходов
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentMainBinding.bind(view) // Подключаем binding
_binding = FragmentMainBinding.bind(view)
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 ->
val qrData = QrScanDestination.getDataIfExist(bundle)
if (qrData != null) {
// Если данные QR есть, переходим на экран с результатом
findNavController().navigate(R.id.qrResultFragment)
}
}
fetchUserInfo()
fetchAccessLogs()
}
private fun setupUI() {
// Настройка RecyclerView
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
accessLogAdapter = AccessLogAdapter(accessLogs)
binding.recyclerView.adapter = accessLogAdapter
// Проверяем, что binding не null, прежде чем устанавливать слушателей
binding.apply {
refresh.setOnClickListener { fetchUserData() }
logout.setOnClickListener { logout() }
scan.setOnClickListener { navigateToQrScan() }
binding.refresh.setOnClickListener {
fetchUserInfo()
fetchAccessLogs()
}
}
private fun fetchUserData() {
private fun fetchUserInfo() {
lifecycleScope.launch {
showError(null) // Скрыть ошибку, если она была
try {
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 ?: ""
val login = SessionManager.userLogin ?: return@launch
val authHeader = "Basic ${SessionManager.getAuthHeader()}"
val response = apiService.getUserInfo(login, authHeader)
// Обновляем UI
updateUI(fullName, position, lastVisit, photoUrl)
// Здесь вы можете добавить данные проходов в список
// Пример:
accessLogs.add(AccessLog("2024-02-31 08:31", "Считыватель 1", "карта"))
accessLogAdapter.notifyDataSetChanged() // Обновляем адаптер
}
} else {
showError(getString(R.string.error_loading_data)) // Показываем ошибку, если данные не загрузились
}
if (response.isSuccessful) {
val employeeData = response.body()
employeeData?.let {
binding.fullname.text = it.name
binding.position.text = it.position
binding.lastEntry.text = it.lastVisit
// Здесь можно установить изображение пользователя, если оно доступно
binding.photo.visibility = View.VISIBLE
binding.fullname.visibility = View.VISIBLE
binding.position.visibility = View.VISIBLE
binding.lastEntry.visibility = View.VISIBLE
}
} catch (e: Exception) {
showError(e.localizedMessage) // Показываем ошибку при исключении
}
}
}
private fun updateUI(fullName: String, position1: String, lastVisit: String, photoUrl: String) {
// Проверяем, что binding не null, прежде чем обновлять UI
binding?.apply {
fullname.text = fullName
position.text = position1
lastEntry.text = lastVisit
if (photoUrl.isNotEmpty()) {
// Загружаем изображение
lifecycleScope.launch {
val bitmap = loadImageFromUrl(photoUrl)
bitmap?.let { photo.setImageBitmap(it) }
}
}
// Показываем элементы
fullname.visibility = View.VISIBLE
position.visibility = View.VISIBLE
lastEntry.visibility = View.VISIBLE
photo.visibility = View.VISIBLE
logout.visibility = View.VISIBLE
scan.visibility = View.VISIBLE
}
}
private suspend fun loadImageFromUrl(urlString: String): Bitmap? {
return withContext(Dispatchers.IO) {
try {
val url = URL(urlString)
val connection = url.openConnection() as HttpURLConnection
connection.doInput = true
connection.connect()
val inputStream = connection.inputStream
BitmapFactory.decodeStream(inputStream)
} catch (e: Exception) {
e.printStackTrace()
null
}
}
}
private fun showError(message: String?) {
// Проверяем, что binding не null, прежде чем обновлять ошибку
binding.apply {
if (message != null) {
error.text = message
error.visibility = View.VISIBLE
// Скрываем остальные элементы, когда возникает ошибка
fullname.visibility = View.GONE
position.visibility = View.GONE
lastEntry.visibility = View.GONE
photo.visibility = View.GONE
logout.visibility = View.GONE
scan.visibility = View.GONE
recyclerView.visibility = View.GONE // Скрываем RecyclerView при ошибке
} else {
error.visibility = View.GONE
recyclerView.visibility = View.VISIBLE // Показываем RecyclerView, если ошибки нет
binding.error.text = "Ошибка получения данных"
binding.error.visibility = View.VISIBLE
}
}
}
private fun logout() {
// Очистите данные пользователя
Toast.makeText(requireContext(), getString(R.string.logged_out), Toast.LENGTH_SHORT).show()
findNavController().navigate(R.id.loginFragment) // Переход на экран входа
}
private fun navigateToQrScan() {
findNavController().navigate(R.id.qrScanFragment) // Переход на экран сканирования QR
private fun fetchAccessLogs() {
// Здесь вы можете реализовать логику для получения данных о проходах
// Например, вы можете сделать запрос к API для получения списка AccessLog
// Для примера, добавим несколько фиктивных данных
accessLogs.clear()
accessLogs.add(AccessLog("2024-02-31 08:31", "Reader 1", "карта"))
accessLogs.add(AccessLog("2024-02-31 09:00", "Reader 2", "смартфон"))
accessLogAdapter.notifyDataSetChanged()
}
override fun onDestroyView() {
_binding = null // Освобождаем binding, когда представление уничтожается
_binding = null
super.onDestroyView()
}
}

View File

@ -1,47 +1,39 @@
package ru.myitschool.work.ui.main
import android.util.Log
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.launch
import ru.myitschool.work.SessionManager
import ru.myitschool.work.api.ApiService
import ru.myitschool.work.api.EmployeeData
import javax.inject.Inject
@HiltViewModel
class MainViewModel @Inject constructor(
private val apiService: ApiService
) : ViewModel() {
private val _userInfoState = MutableStateFlow<Map<String, Any>?>(null)
val userInfoState: StateFlow<Map<String, Any>?> = _userInfoState
init {
loadUserData()
}
private val _employeeData = MutableStateFlow<EmployeeData?>(null)
val employeeData: StateFlow<EmployeeData?> get() = _employeeData
private fun loadUserData() {
private val _errorMessage = MutableStateFlow<String?>(null)
val errorMessage: StateFlow<String?> get() = _errorMessage
fun fetchUserInfo(login: String, authHeader: String) {
viewModelScope.launch {
try {
val login = SessionManager.userLogin
if (login != null) {
val response = apiService.getUserInfo(login)
if (response.isSuccessful) {
_userInfoState.value = response.body()
} else {
// Обработка ошибки, если ответ не успешен
_userInfoState.value = null // Или установите какое-то состояние ошибки
}
val response = apiService.getUserInfo(login, authHeader)
if (response.isSuccessful) {
_employeeData.value = response.body()
} else {
// Логин равен null, обработайте это состояние
_userInfoState.value = null // Или установите какое-то состояние ошибки
_errorMessage.value = "Ошибка получения данных: ${response.message()}"
}
} catch (e: Exception) {
// Логирование ошибки
e.printStackTrace()
// Установите состояние ошибки
_userInfoState.value = null // Или установите какое-то состояние ошибки
Log.e("MainViewModel", "Error fetching user info", e)
_errorMessage.value = "Ошибка сети: ${e.message}"
}
}
}

View File

@ -8,6 +8,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import ru.myitschool.work.SessionManager
import javax.inject.Inject
@HiltViewModel
@ -31,6 +32,7 @@ class LoginViewModel @Inject constructor(
// Проверяем код ответа
when (response.code()) {
200 -> {
SessionManager.userLogin = username
_state.value = LoginState(success = true) // Успешная авторизация
Log.d("LoginViewModel", "Authentication successful") // Логируем успешную аутентификацию
}

View File

@ -1,110 +1,50 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:gravity="bottom"
android:padding="16dp"
android:background="@android:color/white">
android:padding="16dp">
<!-- Поле для ФИО -->
<TextView
android:id="@+id/fullname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/fullname_label"
android:textSize="18sp"
android:layout_marginBottom="5dp"
android:visibility="gone" />
android:textSize="18sp" />
<!-- Фото пользователя. -->
<ImageView
android:id="@+id/photo"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:contentDescription="@string/photo_description"
android:layout_marginBottom="5dp"
android:visibility="gone" />
android:contentDescription="@string/photo_description" />
<!-- Поле для должности -->
<TextView
android:id="@+id/position"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/position_label"
android:layout_marginBottom="5dp"
android:visibility="gone" />
android:textSize="16sp" />
<!-- Поле для даты последнего входа -->
<TextView
android:id="@+id/lastEntry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="2024-02-31 08:31"
android:layout_marginBottom="75dp"
android:visibility="gone" />
android:textSize="14sp" />
<!-- Кнопка обновления -->
<Button
android:id="@+id/refresh"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/refresh"
app:cornerRadius="16dp"
android:backgroundTint="@color/colorPrimary"
android:textColor="@android:color/white"
android:layout_marginBottom="12dp"
android:padding="12dp"/>
android:text="@string/refresh" />
<!-- Поле ошибки -->
<TextView
android:id="@+id/error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/error_placeholder"
android:textColor="@android:color/holo_red_dark"
android:visibility="gone" />
<!-- RecyclerView для списка проходов -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:visibility="gone" />
<!-- Кнопки -->
<Button
android:id="@+id/scan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/scan_qr_code"
android:layout_marginBottom="12dp"
android:backgroundTint="@color/colorPrimary"
app:cornerRadius="16dp"
android:textColor="@android:color/white"
android:visibility="gone" />
<Button
android:id="@+id/logout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/logout"
android:layout_marginBottom="50dp"
app:cornerRadius="16dp"
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="@string/admin_panel"
app:cornerRadius="16dp"
android:backgroundTint="@color/colorPrimary"
android:layout_marginTop="16dp"
android:visibility="gone" />
android:layout_weight="1" />
</LinearLayout>

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -8,20 +9,17 @@
android:id="@+id/scan_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Время сканирования"
android:textSize="16sp" />
android:textSize="14sp" />
<TextView
android:id="@+id/reader_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Идентификатор считывателя"
android:textSize="16sp" />
android:textSize="14sp" />
<TextView
android:id="@+id/access_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Тип прохода"
android:textSize="16sp" />
android:textSize="14sp" />
</LinearLayout>