Skip to content

Commit

Permalink
Merge pull request #465 from bounswe/feature/mobile-449-add-request-r…
Browse files Browse the repository at this point in the history
…esource

Send requests to backend for Need Creation
  • Loading branch information
alperenDagi authored Nov 26, 2023
2 parents 296f87b + 984b22c commit 4e64d13
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class UserSessionManager(appContext: Context) {
editor.putString(USER_EMAIL, userEmail)
editor.putString(USER_ROLES, rolesJson)
if (userRoles.isNotEmpty()) {
editor.putString(SELECTED_ROLE, userRoles.last())
editor.putString(SELECTED_ROLE, userRoles.first())
}
editor.putBoolean(KEY_IS_LOGGED_IN, true)
editor.apply()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ data class CategoryNode(
val children: List<CategoryNode>
)

data class CreateNeedRequestBody(
val description: String,
val latitude: Double,
val longitude: Double,
val categoryTreeId: String,
val quantity: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import com.cmpe451.resq.data.Constants
import com.cmpe451.resq.data.manager.UserSessionManager
import com.cmpe451.resq.data.models.CategoryNode
import com.cmpe451.resq.data.models.CreateNeedRequestBody
import com.cmpe451.resq.data.models.LoginRequestBody
import com.cmpe451.resq.data.models.LoginResponse
import com.cmpe451.resq.data.models.ProfileData
Expand All @@ -26,9 +27,11 @@ interface CategoryTreeNodeService {
interface NeedService {
@POST("need/createNeed")
suspend fun createNeed(
@Query("userId") userId: Int,
@Header("Authorization") jwtToken: String,
@Header("X-Selected-Role") role: String
)
@Header("X-Selected-Role") role: String,
@Body requestBody: CreateNeedRequestBody
): Response<Int>
}

interface AuthService {
Expand All @@ -55,6 +58,7 @@ class ResqService(appContext: Context) {
.build()

private val categoryTreeNodeService: CategoryTreeNodeService = retrofit.create(CategoryTreeNodeService::class.java)
private val needService: NeedService = retrofit.create(NeedService::class.java)
private val authService: AuthService = retrofit.create(AuthService::class.java)
private val profileService: ProfileService = retrofit.create(ProfileService::class.java)

Expand All @@ -71,14 +75,28 @@ class ResqService(appContext: Context) {
)
}

// Need methods
suspend fun createNeed(request: CreateNeedRequestBody): Response<Int> {
val userId = userSessionManager.getUserId()
val token = userSessionManager.getUserToken() ?: ""
val selectedRole = userSessionManager.getSelectedRole() ?: ""

return needService.createNeed(
userId = userId,
jwtToken = "Bearer $token",
role = selectedRole,
requestBody = request
)
}

// Auth methods
suspend fun login(request: LoginRequestBody): Response<LoginResponse> = authService.login(request)
suspend fun register(request: RegisterRequestBody): Response<ResponseBody> = authService.register(request)

// Profile methods
suspend fun getUserInfo(): ProfileData {
val token = userSessionManager.getUserToken() ?: ""
val userId = userSessionManager.getUserId()
val token = userSessionManager.getUserToken() ?: ""
val selectedRole = userSessionManager.getSelectedRole() ?: ""

val response = profileService.getUserInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
Expand Down Expand Up @@ -58,12 +61,11 @@ fun RequestScreen(
val selectedCategoryState = viewModel.selectedCategory
val categories = viewModel.categories.value


val priorities = listOf("HIGH", "MEDIUM", "LOW")
var selectedPriority by remember { mutableStateOf(viewModel.selectedPriority.value) }

var description by remember { mutableStateOf("") }
var quantity by remember { mutableStateOf("") }

val snackbarHostState = remember { SnackbarHostState() }

Column(
modifier = Modifier
.background(Color.White)
Expand Down Expand Up @@ -132,22 +134,18 @@ fun RequestScreen(

Spacer(modifier = Modifier.height(16.dp))

DropdownMenuComponent(
label = "Priority",
items = priorities,
selectedItem = selectedPriority,
itemToString = { it },
onItemSelected = { priority ->
selectedPriority = priority
viewModel.updatePriority(priority)
}
OutlinedTextField(
value = description,
onValueChange = { description = it },
label = { Text("Description") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
modifier = Modifier.fillMaxWidth()
)


Spacer(modifier = Modifier.height(16.dp))

OutlinedTextField(
value = quantity, // you can bind this to a state variable to store the quantity
value = quantity,
onValueChange = { quantity = it },
label = { Text("Quantity") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
Expand All @@ -158,14 +156,24 @@ fun RequestScreen(

// Enter Button
Button(
onClick = { viewModel.onEnter() },
onClick = { viewModel.onEnter(description, quantity, appContext) },
colors = ButtonDefaults.buttonColors(backgroundColor = LightGreen),
shape = RoundedCornerShape(50)
) {
Text(text = "Enter")
}
}
}
// Success and Error messages
if (viewModel.createNeedResponse.value != null) {
LaunchedEffect(key1 = viewModel.createNeedResponse.value) {
snackbarHostState.showSnackbar(
message = "Need created successfully.",
duration = SnackbarDuration.Long
)
}
}
SnackbarHost(hostState = snackbarHostState)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ class LoginViewModel() : ViewModel() {
)
}


private fun validateLoginInputs(email: String, password: String): Boolean {
return when {
email.isBlank() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.cmpe451.resq.data.manager.UserSessionManager
import com.cmpe451.resq.data.models.CategoryNode
import com.cmpe451.resq.data.models.CreateNeedRequestBody
import com.cmpe451.resq.data.models.LoginRequestBody
import com.cmpe451.resq.data.models.LoginResponse
import com.cmpe451.resq.data.remote.ResqService
import com.cmpe451.resq.utils.NavigationItem
import kotlinx.coroutines.launch

class RequestViewModel : ViewModel() {
Expand All @@ -29,11 +32,8 @@ class RequestViewModel : ViewModel() {
private val _items = mutableStateOf<List<CategoryNode>>(emptyList())
val items: State<List<CategoryNode>> = _items

private val _selectedPriority = mutableStateOf("LOW")
val selectedPriority: State<String> = _selectedPriority

private val _quantity = mutableStateOf<String?>(null)
val quantity: State<String?> = _quantity
private val _createNeedResponse = mutableStateOf<String?>(null)
val createNeedResponse: State<String?> = _createNeedResponse

fun updateCategory(category: CategoryNode) {
_selectedCategory.value = category
Expand All @@ -45,15 +45,10 @@ class RequestViewModel : ViewModel() {
fetchItemsForType(type.id)
}


fun updateItem(item: CategoryNode) {
_selectedItem.value = item
}

fun updatePriority(priority: String) {
_selectedPriority.value = priority
}

private fun fetchTypesForCategory(categoryId: Int) {
_types.value = _categories.value.find { it.id == categoryId }?.children ?: emptyList()
_selectedType.value = null
Expand Down Expand Up @@ -82,6 +77,38 @@ class RequestViewModel : ViewModel() {
}
}

fun onEnter() {
fun onEnter(description: String, quantity: String, appContext: Context) {
viewModelScope.launch {
val result = getCreateNeedResponse(description, quantity, appContext)

if (result.isSuccess) {
_createNeedResponse.value = result.getOrNull().toString()
} else {
_createNeedResponse.value = result.exceptionOrNull()?.message
}
}
}

private suspend fun getCreateNeedResponse(description: String, quantity: String, appContext: Context): Result<Int> {
val api = ResqService(appContext)
val categoryId = _selectedItem.value?.id?.toString() ?: _selectedType.value?.id?.toString() ?: ""

if (categoryId.isNotEmpty()) {
val requestBody = CreateNeedRequestBody(
description = description,
latitude = 0.0,
longitude = 0.0,
categoryTreeId = categoryId,
quantity = quantity.toIntOrNull() ?: 0
)
val response = api.createNeed(requestBody)
if (response.isSuccessful) {
response.body()?.let {
return Result.success(it)
}
}
return Result.failure(Throwable(response.message()))
}
return Result.failure(Throwable(message = "No category"))
}
}

0 comments on commit 4e64d13

Please sign in to comment.