Skip to content
This repository has been archived by the owner on Jan 7, 2025. It is now read-only.

Commit

Permalink
Merge pull request #15 from fictadvisor/user_profile
Browse files Browse the repository at this point in the history
User profile
  • Loading branch information
vita133 authored Apr 11, 2024
2 parents 1558b5e + 3f6ffdf commit ef25bd8
Show file tree
Hide file tree
Showing 19 changed files with 674 additions and 41 deletions.
6 changes: 6 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ dependencies {
implementation "com.squareup.okhttp3:okhttp:$logging_version"
implementation "com.squareup.okhttp3:logging-interceptor:$logging_version"

// - - Glide

implementation "com.github.bumptech.glide:glide:4.12.0"
kapt "com.github.bumptech.glide:compiler:4.12.0"
implementation "androidx.activity:activity-ktx:1.8.2"

// - - MockWebServer
def mock_web_server_version = "4.3.1"
testImplementation "com.squareup.okhttp3:mockwebserver:$mock_web_server_version"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<application
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.fictadvisor.android.data.remote

import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule

@GlideModule
class GlideModule: AppGlideModule()
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@ package com.fictadvisor.android.data.remote.api
import com.fictadvisor.android.data.dto.*
import okhttp3.ResponseBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.Query
import retrofit2.http.*

interface AuthApi {

Expand Down Expand Up @@ -37,13 +32,13 @@ interface AuthApi {
suspend fun verifyEmailToken(@Path("token") token: String): Response<AuthLoginResponse>

@PUT("/v2/auth/updatePassword")
suspend fun updatePassword(@Body updatePasswordRequest: UpdatePasswordDTO): Response<AuthLoginResponse>
suspend fun updatePassword(@Header("Authorization") token: String, @Body updatePasswordRequest: UpdatePasswordDTO): Response<AuthLoginResponse>

@POST("/v2/auth/resetPassword/{token}")
suspend fun resetPassword(@Path("token") token: String, @Body resetPasswordRequest: ResetPasswordDTO): Response<AuthLoginResponse>

@GET("/v2/auth/me")
suspend fun getStudent(): Response<OrdinaryStudentResponse>
suspend fun getStudent(@Header("Authorization") token: String): Response<OrdinaryStudentResponse>

@GET("/v2/auth/verifyIsRegistered")
suspend fun verifyIsRegistered(@Query("username") username: String?, @Query("email") email: String?): Response<Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class AuthRepository() {

suspend fun verifyEmailToken(token: String) = authService.verifyEmailToken(token)

suspend fun updatePassword(oldPassword: String, newPassword: String) = authService.updatePassword(
suspend fun updatePassword(token: String, oldPassword: String, newPassword: String) = authService.updatePassword(
"Bearer $token",
UpdatePasswordDTO(
oldPassword,
newPassword,
Expand All @@ -49,7 +50,7 @@ class AuthRepository() {
),
)

suspend fun getStudent() = authService.getStudent()
suspend fun getStudent(token: String) = authService.getStudent("Bearer $token")

suspend fun verifyIsRegistered(username: String?, email: String?) = authService.verifyIsRegistered(username, email)

Expand Down
42 changes: 41 additions & 1 deletion app/src/main/java/com/fictadvisor/android/ui/LoginFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.navigation.Navigation
import com.fictadvisor.android.R
import com.fictadvisor.android.data.dto.AuthLoginResponse
import com.fictadvisor.android.data.dto.BaseResponse
import com.fictadvisor.android.data.dto.OrdinaryStudentResponse
import com.fictadvisor.android.databinding.FragmentLoginBinding
import com.fictadvisor.android.repository.AuthRepository
import com.fictadvisor.android.utils.StorageUtil
Expand Down Expand Up @@ -42,6 +43,7 @@ class LoginFragment : Fragment() {
inputValidator = LoginInputValidator(requireContext())
storageUtil = StorageUtil(requireContext())


authViewModel = ViewModelProvider(
this,
AuthViewModelFactory(authRepository)
Expand All @@ -65,6 +67,9 @@ class LoginFragment : Fragment() {
val password = binding.editTextPassword.text.toString()
if (inputValidator.isLoginDataValid(username)) {
loginUser(username, password)
if (storageUtil.getTokens()?.accessToken != null) {
getStudentInfo(storageUtil.getTokens()?.accessToken!!)
}
}
}
}
Expand Down Expand Up @@ -107,7 +112,6 @@ class LoginFragment : Fragment() {
}
}
}

private fun saveRefreshAndAccessTokens(response: BaseResponse.Success<AuthLoginResponse>) {
val responseData = response.data!!
val accessToken = responseData.accessToken
Expand All @@ -116,6 +120,42 @@ class LoginFragment : Fragment() {
Log.d("LoginFragment", "Access token: ${storageUtil.getTokens()?.accessToken}")
}

private fun getStudentInfo(token: String) {
CoroutineScope(Dispatchers.IO).launch {
authViewModel.getStudent(token)
}

authViewModel.authOrdinaryStudentResponse.observe(viewLifecycleOwner) { studentInfoResponse ->
studentInfoResponse?.let {
handleStudentInfoResponse(studentInfoResponse)
}
}
}

private fun handleStudentInfoResponse(studentInfoResponse: BaseResponse<OrdinaryStudentResponse>) {
when (studentInfoResponse) {
is BaseResponse.Success -> {
showSuccessLog("Інформація про студента успішно отримана")
saveStudentInfo(studentInfoResponse)
}

is BaseResponse.Error -> {
showErrorLog("Помилка отримання інформації про студента: ${studentInfoResponse.error?.message}")
}

is BaseResponse.Loading -> {
// Loading, if needed
}
}
}

private fun saveStudentInfo(response: BaseResponse.Success<OrdinaryStudentResponse>) {
val responseData = response.data!!
storageUtil.setOrdinaryStudentInfo(responseData)
Log.d("LoginFragment", "Student info: ${storageUtil.getOrdinaryStudentInfo()}")

}

private fun showSuccessLog(message: String) {
Log.d("LoginFragment", message)
}
Expand Down
84 changes: 77 additions & 7 deletions app/src/main/java/com/fictadvisor/android/ui/ScheduleFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.Navigation
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.fictadvisor.android.R
import com.fictadvisor.android.data.dto.BaseResponse
import com.fictadvisor.android.data.dto.OrdinaryStudentResponse
import com.fictadvisor.android.databinding.FragmentScheduleBinding
import com.fictadvisor.android.repository.AuthRepository
import com.fictadvisor.android.utils.StorageUtil
import com.fictadvisor.android.viewmodel.AuthViewModel
import com.fictadvisor.android.viewmodel.AuthViewModelFactory
import com.fictadvisor.android.data.dto.ResetPasswordDTO
import com.fictadvisor.android.data.dto.schedule.DetailedEventResponse
import com.fictadvisor.android.data.dto.schedule.PatchEventDTO
Expand All @@ -16,15 +26,17 @@ import com.fictadvisor.android.data.dto.schedule.TDiscipline
import com.fictadvisor.android.data.dto.schedule.TEventPeriod
import com.fictadvisor.android.databinding.FragmentResetPasswordBinding
import com.fictadvisor.android.repository.ScheduleRepository
import com.fictadvisor.android.utils.StorageUtil
import com.fictadvisor.android.viewmodel.ScheduleViewModel
import com.fictadvisor.android.viewmodel.ScheduleViewModelFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class ScheduleFragment : Fragment() {
private lateinit var binding: FragmentResetPasswordBinding
private lateinit var binding: FragmentScheduleBinding
private lateinit var authViewModel: AuthViewModel
private val authRepository = AuthRepository()
private lateinit var storageUtil: StorageUtil
private lateinit var scheduleViewModel: ScheduleViewModel
private val scheduleRepository = ScheduleRepository()

Expand All @@ -38,11 +50,25 @@ class ScheduleFragment : Fragment() {
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {

binding = FragmentResetPasswordBinding.inflate(inflater, container, false)
binding = FragmentScheduleBinding.inflate(inflater, container, false)
val view = binding.root

scheduleViewModel = ViewModelProvider(
storageUtil = StorageUtil(requireContext())
authViewModel = ViewModelProvider(
this,
AuthViewModelFactory(authRepository)
).get(AuthViewModel::class.java)
val userToken = storageUtil.getTokens()?.accessToken
if (userToken != null) {
getStudentInfo(userToken)
val userData = storageUtil.getOrdinaryStudentInfo()
Glide.with(this).load(userData?.avatar).apply(RequestOptions.circleCropTransform())
.into(binding.imageButton)
}
binding.imageButton.setOnClickListener {
Navigation.findNavController(view).navigate(R.id.action_scheduleFragment_to_studentProfileFragment)
}

scheduleViewModel = ViewModelProvider(
this,
ScheduleViewModelFactory(scheduleRepository)
).get(ScheduleViewModel::class.java)
Expand All @@ -51,6 +77,51 @@ class ScheduleFragment : Fragment() {

return view
}

private fun getStudentInfo(token: String) {
CoroutineScope(Dispatchers.IO).launch {
authViewModel.getStudent(token)
}

authViewModel.authOrdinaryStudentResponse.observe(viewLifecycleOwner) { studentInfoResponse ->
studentInfoResponse?.let {
handleStudentInfoResponse(studentInfoResponse)
}
}
}

private fun handleStudentInfoResponse(studentInfoResponse: BaseResponse<OrdinaryStudentResponse>) {
when (studentInfoResponse) {
is BaseResponse.Success -> {
showSuccessLog("Інформація про студента успішно отримана")
saveStudentInfo(studentInfoResponse)
}

is BaseResponse.Error -> {
showErrorLog("Помилка отримання інформації про студента: ${studentInfoResponse.error?.message}")
}

is BaseResponse.Loading -> {
// Loading, if needed
}
}
}

private fun saveStudentInfo(response: BaseResponse.Success<OrdinaryStudentResponse>) {
val responseData = response.data!!
storageUtil.setOrdinaryStudentInfo(responseData)
Log.d("LoginFragment", "Student info: ${storageUtil.getOrdinaryStudentInfo()}")

}

private fun showSuccessLog(message: String) {
Log.d("LoginFragment", message)
}

private fun showErrorLog(message: String) {
Log.e("LoginFragment", message)
}


private fun testScheduleApiMethods() {
// testGetEvents()
Expand Down Expand Up @@ -189,6 +260,5 @@ class ScheduleFragment : Fragment() {
fun newInstance(): ScheduleFragment {
return ScheduleFragment()
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.fictadvisor.android.ui

import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.Navigation
import com.fictadvisor.android.R
import com.fictadvisor.android.data.dto.AuthLoginResponse
import com.fictadvisor.android.data.dto.BaseResponse
import com.fictadvisor.android.databinding.FragmentSecurityStudentProfileBinding
import com.fictadvisor.android.repository.AuthRepository
import com.fictadvisor.android.utils.StorageUtil
import com.fictadvisor.android.viewmodel.AuthViewModel
import com.fictadvisor.android.viewmodel.AuthViewModelFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch


class SecurityStudentProfileFragment : Fragment() {
private lateinit var binding: FragmentSecurityStudentProfileBinding
private lateinit var authViewModel: AuthViewModel
private val authRepository = AuthRepository()
private lateinit var storageUtil: StorageUtil

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
}

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentSecurityStudentProfileBinding.inflate(inflater, container, false)
val view = binding.root
authViewModel = ViewModelProvider(
this,
AuthViewModelFactory(authRepository)
).get(AuthViewModel::class.java)

storageUtil = StorageUtil(requireContext())

if (storageUtil.getTokens()?.accessToken != null) {
binding.buttonChangePassword.setOnClickListener {
val oldPassword = binding.editTextOldPassword.text.toString()
val newPassword = binding.editTextNewPassword.text.toString()
val token = storageUtil.getTokens()?.accessToken.toString()
updatePassword(token, oldPassword, newPassword)
Navigation.findNavController(view).navigate(R.id.action_securityStudentProfileFragment_to_studentProfileFragment)
}
}

binding.buttonPrevious.setOnClickListener {
view.let { it1 -> Navigation.findNavController(it1).navigateUp() }
}

return view
}

private fun updatePassword(token: String, oldPassword: String, newPassword: String) {
CoroutineScope(Dispatchers.IO).launch {
authViewModel.updatePassword(token, oldPassword, newPassword)
}

authViewModel.authUpdatePasswordResponse.observe(viewLifecycleOwner) { updatePasswordResponse ->
updatePasswordResponse?.let {
handleUpdatePasswordResponse(it)
}
}
}

private fun handleUpdatePasswordResponse(response: BaseResponse<AuthLoginResponse>) {
when (response) {
is BaseResponse.Success -> {
showSuccessLog("Пароль успішно змінено")
}

is BaseResponse.Error -> {
showErrorLog("Помилка зміни паролю: ${response.error?.message}")
}

is BaseResponse.Loading -> {
showSuccessLog("Завантаження...")
}
}
}

private fun showSuccessLog(message: String) {
Log.d("SecurityStudentProfileFragment", message)
}

private fun showErrorLog(message: String) {
Log.e("SecurityStudentProfileFragment", message)
}

companion object {
@JvmStatic
fun newInstance() = SecurityStudentProfileFragment()
}
}
Loading

0 comments on commit ef25bd8

Please sign in to comment.